/** * Copyright (C) 2006 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.torrent; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.cnetwork.ContentNetwork; /** * @author TuxPaper * @created Sep 27, 2006 * */ public class PlatformTorrentUtils { private static final long MIN_SPEED_DEFAULT = 100 * 1024; public static final String AELITIS_HOST_CORE = ".aelitis.com"; // needs to be lowercase public static final String VUZE_HOST_CORE = ".vuze.com"; // needs to be lowercase public static final boolean DEBUG_CACHING = System.getProperty( "az3.debug.caching", "0").equals("1"); private static final String TOR_AZ_PROP_MAP = "Content"; private static final String TOR_AZ_PROP_HASH = "Content Hash"; private static final String TOR_AZ_PROP_TITLE = "Title"; private static final String TOR_AZ_PROP_DESCRIPTION = "Description"; private static final String TOR_AZ_PROP_CONTENT_TYPE = "Content Type"; private static final String TOR_AZ_PROP_AUTHOR = "Author"; private static final String TOR_AZ_PROP_PUBLISHER = "Publisher"; private static final String TOR_AZ_PROP_URL = "URL"; private static final String TOR_AZ_PROP_THUMBNAIL = "Thumbnail"; private static final String TOR_AZ_PROP_THUMBNAIL_URL = "Thumbnail.url"; private static final String TOR_AZ_PROP_PROGRESSIVE = "Progressive"; private static final String TOR_AZ_PROP_SPEED = "Speed Bps"; private static final String TOR_AZ_PROP_MIN_SPEED = "Min Speed Bps"; private static final String TOR_AZ_PROP_QOS_CLASS = "QOS Class"; private static final String TOR_AZ_PROP_CONTENT_NETWORK = "Content Network"; private static final String TOR_AZ_PROP_EXPIRESON = "Expires On"; private static final String TOR_AZ_PROP_PRIMARY_FILE = "Primary File Index"; private static final ArrayList<HasBeenOpenedListener> hasBeenOpenedListeners = new ArrayList<HasBeenOpenedListener>(1); private static final String TOR_AZ_PROP_VIDEO_WIDTH = "Video Width"; private static final String TOR_AZ_PROP_VIDEO_HEIGHT = "Video Height"; private static final String TOR_AZ_PROP_VIDEO_RUNNINGTIME = "Running Time"; private static final String TOR_AZ_PROP_DURATION_MILLIS = "Duration"; private static final String TOR_AZ_PROP_OPENED = "Opened"; private static ArrayList<String> listPlatformHosts = new ArrayList<String>(); static{ for (int i = 0; i < Constants.AZUREUS_DOMAINS.length; i++) { listPlatformHosts.add(Constants.AZUREUS_DOMAINS[i].toLowerCase()); } } private static final Map mapPlatformTrackerTorrents = new WeakHashMap(); private static boolean embeddedPlayerAvail = false; public static Map getContentMap(TOTorrent torrent) { if (torrent == null) { return Collections.EMPTY_MAP; } Map mapAZProps = torrent.getAdditionalMapProperty(TOTorrent.AZUREUS_PROPERTIES); if (mapAZProps == null) { mapAZProps = new HashMap(); torrent.setAdditionalMapProperty(TOTorrent.AZUREUS_PROPERTIES, mapAZProps); } Object objExistingContentMap = mapAZProps.get(TOR_AZ_PROP_MAP); Map mapContent; if (objExistingContentMap instanceof Map) { mapContent = (Map) objExistingContentMap; } else { mapContent = new HashMap(); mapAZProps.put(TOR_AZ_PROP_MAP, mapContent); } return mapContent; } static Map getTempContentMap(TOTorrent torrent) { if (torrent == null) { return new HashMap(); } Map mapAZProps = torrent.getAdditionalMapProperty("attributes"); if (mapAZProps == null) { mapAZProps = new HashMap(); torrent.setAdditionalMapProperty("attributes", mapAZProps); } Object objExistingContentMap = mapAZProps.get(TOR_AZ_PROP_MAP); Map mapContent; if (objExistingContentMap instanceof Map) { mapContent = (Map) objExistingContentMap; } else { mapContent = new HashMap(); mapAZProps.put(TOR_AZ_PROP_MAP, mapContent); } return mapContent; } public static String getContentMapString(TOTorrent torrent, String key) { if (torrent == null) { return null; } Map mapContent = getContentMap(torrent); Object obj = mapContent.get(key); if (obj instanceof String) { return (String) obj; } else if (obj instanceof byte[]) { try { return new String((byte[]) obj, Constants.DEFAULT_ENCODING); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } private static void setContentMapString(TOTorrent torrent, String key, String value) { if (torrent == null) { return; } Map mapContent = getContentMap(torrent); mapContent.put(key, value); } private static long getContentMapLong(TOTorrent torrent, String key, long def) { if (torrent == null) { return def; } Map mapContent = getContentMap(torrent); Object obj = mapContent.get(key); try { if (obj instanceof Long) { return ((Long) obj).longValue(); } else if (obj instanceof Integer) { return ((Integer) obj).longValue(); } else if (obj instanceof String) { return Long.parseLong((String) obj); } else if (obj instanceof byte[]) { return Long.parseLong(new String((byte[]) obj)); } } catch (Exception e) { } return def; } public static Map getContentMapMap(TOTorrent torrent, String key ){ if ( torrent == null ){ return( null ); } Map mapContent = getContentMap(torrent); Object obj = mapContent.get(key); if ( obj instanceof Map ){ return((Map)obj); } return( null ); } private static void setContentMapLong(TOTorrent torrent, String key, long value) { if (torrent == null) { return; } Map mapContent = getContentMap(torrent); mapContent.put(key, new Long(value)); } public static void setContentMapMap(TOTorrent torrent, String key, Map value) { if (torrent == null) { return; } Map mapContent = getContentMap(torrent); mapContent.put(key, value); } public static String getContentHash(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_HASH); } public static String getContentTitle(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_TITLE); } public static void setContentTitle(TOTorrent torrent, String title) { setContentMapString(torrent, TOR_AZ_PROP_TITLE, title); } public static String getContentDescription(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_DESCRIPTION); } public static void setContentDescription(TOTorrent torrent, String desc) { setContentMapString(torrent, TOR_AZ_PROP_DESCRIPTION,desc); } public static String getContentType(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_CONTENT_TYPE); } public static void setContentType(TOTorrent torrent, String title) { setContentMapString(torrent, TOR_AZ_PROP_CONTENT_TYPE, title); } public static String getContentAuthor(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_AUTHOR); } public static String getContentPublisher(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_PUBLISHER); } public static String getContentURL(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_URL); } public static long getQOSClass(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_QOS_CLASS, 0); } public static void setQOSClass(TOTorrent torrent, long cla) { setContentMapLong(torrent, TOR_AZ_PROP_QOS_CLASS, cla); } public static long getContentNetworkID(TOTorrent torrent){ return( getContentNetworkID( torrent, ContentNetwork.CONTENT_NETWORK_UNKNOWN )); } public static long getContentNetworkID(TOTorrent torrent, long def) { long id = getContentMapLong(torrent, TOR_AZ_PROP_CONTENT_NETWORK, ContentNetwork.CONTENT_NETWORK_UNKNOWN); if (id == ContentNetwork.CONTENT_NETWORK_UNKNOWN) { return isContent(torrent, false) ? ContentNetwork.CONTENT_NETWORK_VUZE : def; } return id; } public static void setContentNetworkID(TOTorrent torrent, long cnet) { setContentMapLong(torrent, TOR_AZ_PROP_CONTENT_NETWORK, cnet); } public static boolean isFeaturedContent( TOTorrent torrent ) { String content_type = getContentType( torrent ); return( content_type != null && content_type.equalsIgnoreCase( "featured" )); } private static void putOrRemove(Map map, String key, Object obj) { if (obj == null) { map.remove(key); } else { map.put(key, obj); } } private static void writeTorrentIfExists(TOTorrent torrent) { if (!AzureusCoreFactory.isCoreRunning()) { return; } AzureusCore core = AzureusCoreFactory.getSingleton(); if (core == null || !core.isStarted()) { return; } GlobalManager gm = core.getGlobalManager(); if (gm == null || gm.getDownloadManager(torrent) == null) { return; } try { TorrentUtils.writeToFile(torrent); } catch (TOTorrentException e) { Debug.out(e); } } public static byte[] getContentThumbnail(TOTorrent torrent) { Map mapContent = getContentMap(torrent); Object obj = mapContent.get(TOR_AZ_PROP_THUMBNAIL); if (obj instanceof byte[]) { return (byte[]) obj; } return null; } public static String getContentThumbnailUrl(TOTorrent torrent) { return getContentMapString(torrent, TOR_AZ_PROP_THUMBNAIL_URL); } public static void setContentThumbnailUrl(TOTorrent torrent, String url) { setContentMapString(torrent, TOR_AZ_PROP_THUMBNAIL_URL, url); } public static void setContentThumbnail(TOTorrent torrent, byte[] thumbnail) { Map mapContent = getContentMap(torrent); putOrRemove(mapContent, TOR_AZ_PROP_THUMBNAIL, thumbnail); writeTorrentIfExists(torrent); } public static boolean isContent(TOTorrent torrent, boolean requirePlatformTracker) { if (torrent == null) { return false; } boolean bContent = PlatformTorrentUtils.getContentHash(torrent) != null; if (!bContent || (bContent && !requirePlatformTracker)) { return bContent; } return isPlatformTracker(torrent); } public static boolean isContent(Torrent torrent, boolean requirePlatformTracker) { if (torrent instanceof TorrentImpl) { return isContent(((TorrentImpl) torrent).getTorrent(), requirePlatformTracker); } return false; } public static List<String> getPlatformHosts() { return listPlatformHosts; } public static void addPlatformHost(String host) { List<String> platformHosts = getPlatformHosts(); host = host.toLowerCase(); if (!platformHosts.contains(host)) { platformHosts.add(host); mapPlatformTrackerTorrents.clear(); } } public static boolean isPlatformHost(String host) { Object[] domains = getPlatformHosts().toArray(); host = host.toLowerCase(); for (int i = 0; i < domains.length; i++) { String domain = (String) domains[i]; if (domain.equals(host)) { return (true); } if (host.endsWith("." + domain)) { return (true); } } if ( Constants.isCVSVersion()){ // allow local addresses for testing try{ InetAddress ia = InetAddress.getByName( host ); return( ia.isLoopbackAddress() || ia.isLinkLocalAddress() || ia.isSiteLocalAddress()); }catch( Throwable e ){ } } return (false); } public static boolean isPlatformTracker(TOTorrent torrent) { try { if (torrent == null) { return false; } Object oCache = mapPlatformTrackerTorrents.get(torrent); if (oCache instanceof Boolean) { return ((Boolean) oCache).booleanValue(); } // check them all incase someone includes one of our trackers in a multi-tracker // torrent URL announceURL = torrent.getAnnounceURL(); if (announceURL != null) { if (!isPlatformHost(announceURL.getHost())) { mapPlatformTrackerTorrents.put(torrent, new Boolean(false)); return (false); } } TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for (int i = 0; i < sets.length; i++) { URL[] urls = sets[i].getAnnounceURLs(); for (int j = 0; j < urls.length; j++) { if (!isPlatformHost(urls[j].getHost())) { mapPlatformTrackerTorrents.put(torrent, new Boolean(false)); return (false); } } } boolean b = announceURL != null; mapPlatformTrackerTorrents.put(torrent, new Boolean(b)); return b; } catch (Throwable e) { Debug.printStackTrace(e); mapPlatformTrackerTorrents.put(torrent, new Boolean(false)); return (false); } } public static boolean isPlatformTracker(Torrent torrent) { if (torrent instanceof TorrentImpl) { return isPlatformTracker(((TorrentImpl) torrent).getTorrent()); } return false; } public static boolean isAdvancedViewOnly(DownloadManager dm) { Boolean oisUpdate = (Boolean) dm.getUserData("isAdvancedViewOnly"); if (oisUpdate != null) { return oisUpdate.booleanValue(); } boolean advanced_view = true; if ( !dm.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){ TOTorrent torrent = dm.getTorrent(); if (torrent == null) { advanced_view = false; } else { URL announceURL = torrent.getAnnounceURL(); if (announceURL != null) { String host = announceURL.getHost(); if (!( host.endsWith(AELITIS_HOST_CORE)|| host.endsWith( VUZE_HOST_CORE ))){ advanced_view = false; } } if (advanced_view) { TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); for (int i = 0; i < sets.length; i++) { URL[] urls = sets[i].getAnnounceURLs(); for (int j = 0; j < urls.length; j++) { String host = urls[j].getHost(); if (!( host.endsWith(AELITIS_HOST_CORE)|| host.endsWith( VUZE_HOST_CORE ))){ advanced_view = false; break; } } } } } } dm.setUserData("isAdvancedViewOnly", new Boolean(advanced_view)); return advanced_view; } public static boolean isContentProgressive(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_PROGRESSIVE, 0) == 1; } public static long getContentStreamSpeedBps(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_SPEED, 0); } public static long getContentMinimumSpeedBps(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_MIN_SPEED, MIN_SPEED_DEFAULT); } public static long getExpiresOn(TOTorrent torrent) { Map mapContent = getContentMap(torrent); Long l = (Long) mapContent.get(TOR_AZ_PROP_EXPIRESON); if (l == null) { return 0; } return l.longValue(); } public static int getContentPrimaryFileIndex(TOTorrent torrent ){ return (int)getContentMapLong(torrent, TOR_AZ_PROP_PRIMARY_FILE, -1 ); } private static long getContentVideoWidth(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_WIDTH, -1); } private static long getContentVideoHeight(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_HEIGHT, -1); } public static long getContentVideoRunningTime(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_RUNNINGTIME, -1); } public static long getContentDurationMillis(TOTorrent torrent) { return getContentMapLong(torrent, TOR_AZ_PROP_DURATION_MILLIS, -1); } public static void setContentDurationMillis(TOTorrent torrent, long millis ) { setContentMapLong(torrent, TOR_AZ_PROP_DURATION_MILLIS, millis ); } public static int[] getContentVideoResolution(TOTorrent torrent) { long width = getContentVideoWidth(torrent); if (width <= 0) { return null; } long height = getContentVideoHeight(torrent); if (height <= 0) { return null; } return new int[] { (int) width, (int) height }; } public static void log(String str) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.MD"); diag_logger.log(str); if (DEBUG_CACHING) { System.out.println(Thread.currentThread().getName() + "|" + System.currentTimeMillis() + "] " + str); } } /** * @param torrent * @param string * * @since 3.0.1.5 */ public static void log(TOTorrent torrent, String string) { String hash = ""; try { hash = torrent.getHashWrapper().toBase32String(); } catch (Exception e) { } log(hash + "] " + string); } public static boolean embeddedPlayerAvail() { // cache true, always recheck false in case plugin installs. if (embeddedPlayerAvail) { return true; } try { PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azemp", true); if (pi != null) { embeddedPlayerAvail = true; } } catch (Throwable e1) { } return embeddedPlayerAvail; } /** * @param torrent * * @since 3.0.4.3 */ public static String getContentTitle2(DownloadManager dm) { if (dm == null) { return null; } // DM state's display name can be set by user, so show that if we have it String name = dm.getDownloadState().getDisplayName(); if (name == null || name.length() == 0) { name = PlatformTorrentUtils.getContentTitle(dm.getTorrent()); if (name == null) { name = dm.getDisplayName(); } } return name; } public static void setHasBeenOpened(DownloadManager dm, boolean opened) { TOTorrent torrent = dm.getTorrent(); if (torrent == null) { return; } if (opened == getHasBeenOpened(dm)) { return; } setContentMapLong(torrent, TOR_AZ_PROP_OPENED, opened ? 1 : 0); writeTorrentIfExists(torrent); Object[] array = hasBeenOpenedListeners.toArray(); for (int i = 0; i < array.length; i++) { try { HasBeenOpenedListener l = (HasBeenOpenedListener) array[i]; l.hasBeenOpenedChanged(dm, opened); } catch (Exception e) { Debug.out(e); } } } public static boolean getHasBeenOpened(DownloadManager dm) { TOTorrent torrent = dm.getTorrent(); if (torrent == null) { return true; } boolean opened = getContentMapLong(torrent, TOR_AZ_PROP_OPENED, -1) > 0; if (opened || isAdvancedViewOnly(dm)) { return true; } return false; } public static void addHasBeenOpenedListener(HasBeenOpenedListener l) { hasBeenOpenedListeners.add(l); } }