package edu.washington.cs.oneswarm.f2f.share; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; import org.bouncycastle.util.encoders.Base64; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.ConfigurationManager; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerInitialisationAdapter; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.torrent.TOTorrentException; import org.gudy.azureus2.core3.torrent.TOTorrentFile; import org.gudy.azureus2.core3.torrent.impl.TOTorrentFileImpl; import org.gudy.azureus2.core3.torrent.impl.TOTorrentImpl; 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.SystemProperties; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.impl.AzureusCoreImpl; import edu.washington.cs.oneswarm.f2f.FileCollection; import edu.washington.cs.oneswarm.f2f.FileListFile; import edu.washington.cs.oneswarm.f2f.multisource.Sha1HashManager; import edu.washington.cs.oneswarm.f2f.permissions.GroupBean; import edu.washington.cs.oneswarm.f2f.permissions.PermissionsDAO; public class ShareManagerTools { private static Logger logger = Logger.getLogger(ShareManagerTools.class.getName()); public static DownloadManager addDownload(final Set<String> selectedFiles, final ArrayList<GroupBean> inPerms, String path, final boolean noStream, File torrentFile, TOTorrent torrent) throws IOException, TOTorrentException { AzureusCore core = AzureusCoreImpl.getSingleton(); if (core.getGlobalManager().getDownloadManager(torrent) != null) { String msg = "Trying to add download manager with hash that already exists: " + new String(torrent.getName()); logger.warning(msg); throw new IOException(msg); } try { PermissionsDAO.get().setGroupsForHash(ByteFormatter.encodeString(torrent.getHash()), inPerms, true); logger.finest("add dl, groups: "); for (GroupBean g : inPerms) { logger.finest(g.toString()); } logger.finest("end groups"); } catch (Exception e) { e.printStackTrace(); Debug.out("couldn't set perms for swarm! " + torrent.getName()); } /** * Use specified path if we have it, otherwise look for saved path. If * we don't have a save path (corrupt settings?) -- we instead use * docPath/OneSwarm Downloads */ if (path == null) { path = COConfigurationManager.getDirectoryParameter("Default save path"); if (path == null) { String docPath = SystemProperties.getDocPath(); File dlTmp = new File(docPath, "OneSwarm Downloads"); ConfigurationManager.getInstance().setParameter("Default save path", dlTmp.getAbsolutePath()); path = dlTmp.getAbsolutePath(); } } final TOTorrentFile[] files = torrent.getFiles(); final DownloadManager dm = core.getGlobalManager().addDownloadManager(torrentFile.getAbsolutePath(), torrent.getHash(), path, null, DownloadManager.STATE_WAITING, true, false, new DownloadManagerInitialisationAdapter() { public void initialised(DownloadManager dm) { DiskManagerFileInfo[] fileInfos = dm.getDiskManagerFileInfo(); try { dm.getDownloadState().supressStateSave(true); for (int fileIndex = 0; fileIndex < fileInfos.length; fileIndex++) { DiskManagerFileInfo diskManagerFileInfo = fileInfos[fileIndex]; String fileName = diskManagerFileInfo.getTorrentFile().getRelativePath(); if (files[fileIndex].getLength() == diskManagerFileInfo.getLength()) { if (!selectedFiles.contains(fileName)) { diskManagerFileInfo.setSkipped(true); if (!diskManagerFileInfo.getFile(false).exists()) { logger.finest("setting compact since file doesn't exist"); diskManagerFileInfo.setStorageType(DiskManagerFileInfo.ST_COMPACT); } else { logger.finest("Couldn't set compact since file exists."); } } } else { logger.finest("Skipping file: " + files[fileIndex].getRelativePath() + " since lengths disagree: " + files[fileIndex].getLength() + " / " + diskManagerFileInfo.getLength()); } } } finally { dm.getDownloadState().supressStateSave(false); dm.getDownloadState().setBooleanAttribute(FileCollection.ONESWARM_STREAM_ATTRIBUTE, !noStream); } } }); if (dm == null) { String msg = "Couldn't create download manager for torrent: " + new String(torrent.getName()); logger.severe(msg); throw new IOException(msg); } logger.fine("Starting torrent download"); return dm; } public static void setSha1AndEd2k(TOTorrent torrent, TOTorrentFile torrentFile, FileListFile f) { Map torrentMap = null; if (torrent.isSimpleTorrent()) { logger.finest("simple torrent: " + new String(torrent.getName())); try { if ((torrent instanceof TOTorrentImpl)) { torrentMap = ((TOTorrentImpl) torrent).getAdditionalInfoProperties(); } else { torrentMap = (Map) torrent.serialiseToMap().get("info"); } } catch (Exception e) { e.printStackTrace(); return; } } else if (torrentFile instanceof TOTorrentFileImpl) { torrentMap = ((TOTorrentFileImpl) torrentFile).getAdditionalProperties(); } else { return; } if (torrentMap.containsKey(FileListFile.KEY_SHA1_HASH)) { byte[] hash = (byte[]) torrentMap.get(FileListFile.KEY_SHA1_HASH); f.setSha1Hash(hash); logger.finest("adding sha1 hash to '" + f.getFileName() + "': " + new String(Base64.encode(hash))); } else { logger.finest("not adding sha1 hash to '" + f.getFileName() + "', no key in map"); } if (torrentMap.containsKey(FileListFile.KEY_ED2K_HASH)) { byte[] hash = (byte[]) torrentMap.get(FileListFile.KEY_ED2K_HASH); f.setEd2kHash(hash); logger.finest("adding ed2k hash to '" + f.getFileName() + "': " + new String(Base64.encode(hash))); } else { logger.finest("not adding ed2k hash to '" + f.getFileName() + "', no key in map"); } } public static String baseXtoBase64(String encoded, int expectedBytes) throws UnsupportedEncodingException { return new String(Base64.encode(baseXdecode(encoded, expectedBytes))); } public static byte[] baseXdecode(String encoded, int expectedBytes) throws UnsupportedEncodingException { // check what encoding that is likely encoded = encoded.trim(); int stringLength = encoded.length(); logger.finest("trying to find base of '" + encoded + "' input bytes=" + stringLength + ", expected after decode=" + expectedBytes); /* * check for base 64, base64 converts 3 input bytes to 4 output bytes */ // base64 has special rules for padding, if the string ends with "=" the expected length will be 1 more int base64expectedBytes = expectedBytes; if (encoded.endsWith("=")) { base64expectedBytes = expectedBytes + 1; } if (stringLength * 3 == base64expectedBytes * 4) { logger.finest("detected base64 encoding"); try { byte[] result = Base64.decode(encoded); return result; } catch (Exception e) { logger.finest("tried base 64 encoding but got exception: " + e.getMessage()); } } /* * base32 encodes in chunks of 40 bits, each 40 bit chunk becomes 8 characters */ if (stringLength * 5 == expectedBytes * 8) { logger.finest("detected base32 encoding"); try { byte[] result = Base32.decode(encoded); return result; } catch (Exception e) { logger.finest("tried base 32 encoding but got exception: " + e.getMessage()); } } /* * base16 encoding (hex) */ if (stringLength == 2 * expectedBytes) { logger.finest("detected base16 encoding"); try { byte[] result = base16Decode(encoded); return result; } catch (Exception e) { logger.finest("tried base 16 encoding but got exception: " + e.getMessage()); } } throw new UnsupportedEncodingException("unable to detect base for input '" + encoded + "'"); } private static byte[] base16Decode(String enc) { enc = enc.trim().toUpperCase(); int l = enc.length(); int i = 0, j = 0; byte[] dec = new byte[l / 2]; while (i < l) { byte n, b; b = (byte) (enc.charAt(i)); if ((b >= (byte) ('0')) && (b <= (byte) ('9'))) n = (byte) (b - (byte) ('0')); else n = (byte) (b - (byte) ('A') + 10); b = (byte) (enc.charAt(i + 1)); if ((b >= (byte) ('0')) && (b <= (byte) ('9'))) n = (byte) ((n << 4) + b - (byte) ('0')); else n = (byte) ((n << 4) + b - (byte) ('A') + 10); dec[j] = n; i += 2; j++; } return dec; } private static final byte[] HEX_CHAR_TABLE = { (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 String base16Encode(byte[] raw) { byte[] hex = new byte[2 * raw.length]; int index = 0; for (byte b : raw) { int v = b & 0xFF; hex[index++] = HEX_CHAR_TABLE[v >>> 4]; hex[index++] = HEX_CHAR_TABLE[v & 0xF]; } try { return new String(hex, "ASCII"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); return ""; } } public static void main(String[] args) { try { String path = new File("test").getCanonicalFile().getParentFile().getParentFile().getCanonicalPath(); System.out.println(path); File logConfig = new File(path + "/oneswarm_gwt_ui/logging.properties"); final LogManager logManager = LogManager.getLogManager(); logManager.readConfiguration(new FileInputStream(logConfig)); logger.setLevel(Level.ALL); String test1 = "62D28B6452CE095302957EC862B1273A"; String test2 = test1.toLowerCase(); System.out.println(base16Encode(baseXdecode(test1, 16))); System.out.println(base16Encode(baseXdecode(test2, 16))); System.out.println(baseXtoBase64("73518D92C27476BAD7DEBFC7F51B9F10", 16)); System.out.println(baseXtoBase64("yPZS9rqauuJSO7oDVuOiEeVstGY=", 20)); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }