Search in sources :

Example 1 with TOTorrentFile

use of com.biglybt.core.torrent.TOTorrentFile in project BiglyBT by BiglySoftware.

the class TorrentRelativePathItem method refresh.

@Override
public void refresh(TableCell cell) {
    DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) cell.getDataSource();
    TOTorrentFile torrentFile = fileInfo == null ? null : fileInfo.getTorrentFile();
    cell.setText(torrentFile == null ? "" : torrentFile.getRelativePath());
}
Also used : TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) DiskManagerFileInfo(com.biglybt.core.disk.DiskManagerFileInfo)

Example 2 with TOTorrentFile

use of com.biglybt.core.torrent.TOTorrentFile in project BiglyBT by BiglySoftware.

the class ManagerUtils method locateFiles.

public static void locateFiles(final DownloadManager[] dms, final DiskManagerFileInfo[][] dm_files, Shell shell) {
    DirectoryDialog dd = new DirectoryDialog(shell);
    dd.setFilterPath(TorrentOpener.getFilterPathData());
    dd.setText(MessageText.getString("MyTorrentsView.menu.locatefiles.dialog"));
    String path = dd.open();
    if (path != null) {
        TorrentOpener.setFilterPathData(path);
        final File dir = new File(path);
        final TextViewerWindow viewer = new TextViewerWindow(MessageText.getString("locatefiles.view.title"), null, "", true, true);
        viewer.setEditable(false);
        viewer.setOKEnabled(true);
        new AEThread2("FileLocator") {

            @Override
            public void run() {
                final int MAX_LINKS = DownloadManagerStateFactory.MAX_FILES_FOR_INCOMPLETE_AND_DND_LINKAGE;
                final String LINK_LIMIT_MSG = "Link limit of " + MAX_LINKS + " exceeded. See Tools->Options->Files to increase this";
                try {
                    Map<Long, Set<File>> file_map = new HashMap<>();
                    final boolean[] quit = { false };
                    viewer.addListener(new TextViewerWindow.TextViewerWindowListener() {

                        @Override
                        public void closed() {
                            synchronized (quit) {
                                quit[0] = true;
                            }
                        }
                    });
                    logLine(viewer, new SimpleDateFormat().format(new Date()) + ": Enumerating files in " + dir);
                    long bfm_start = SystemTime.getMonotonousTime();
                    long[] last_log = { bfm_start };
                    int file_count = buildFileMap(viewer, dir, file_map, last_log, quit);
                    logLine(viewer, (bfm_start == last_log[0] ? "" : "\r\n") + "Found " + file_count + " files with " + file_map.size() + " distinct sizes");
                    Set<String> all_dm_incomplete_files = null;
                    ConcurrentHasher hasher = ConcurrentHasher.getSingleton();
                    int downloads_modified = 0;
                    for (int i = 0; i < dms.length; i++) {
                        DownloadManager dm = dms[i];
                        synchronized (quit) {
                            if (quit[0]) {
                                break;
                            }
                        }
                        if (!dm.isPersistent()) {
                            continue;
                        }
                        TOTorrent torrent = dm.getTorrent();
                        if (torrent == null) {
                            continue;
                        }
                        DiskManagerFileInfo[] selected_files = dm_files == null ? null : dm_files[i];
                        Set<Integer> selected_file_indexes;
                        if (selected_files == null) {
                            selected_file_indexes = null;
                        } else {
                            selected_file_indexes = new HashSet<>();
                            for (DiskManagerFileInfo f : selected_files) {
                                selected_file_indexes.add(f.getIndex());
                            }
                        }
                        TOTorrentFile[] to_files = torrent.getFiles();
                        long piece_size = torrent.getPieceLength();
                        byte[][] pieces = torrent.getPieces();
                        logLine(viewer, "Processing '" + dm.getDisplayName() + "', piece size=" + DisplayFormatters.formatByteCountToKiBEtc(piece_size));
                        int dm_state = dm.getState();
                        if (!(dm_state == DownloadManager.STATE_STOPPED || dm_state == DownloadManager.STATE_ERROR)) {
                            logLine(viewer, "    Download must be stopped");
                            continue;
                        }
                        DiskManagerFileInfo[] files = dm.getDiskManagerFileInfoSet().getFiles();
                        Set<String> dm_files = null;
                        Map<DiskManagerFileInfo, File> links_established = new HashMap<>();
                        Map<DiskManagerFileInfo, Set<String>> unmatched_files = new TreeMap<>(new Comparator<DiskManagerFileInfo>() {

                            @Override
                            public int compare(DiskManagerFileInfo o1, DiskManagerFileInfo o2) {
                                long diff = o2.getLength() - o1.getLength();
                                if (diff < 0) {
                                    return (-1);
                                } else if (diff > 0) {
                                    return (1);
                                } else {
                                    return (0);
                                }
                            }
                        });
                        int no_candidates = 0;
                        int already_complete = 0;
                        int link_count = 0;
                        try {
                            download_loop: for (final DiskManagerFileInfo file : files) {
                                synchronized (quit) {
                                    if (quit[0]) {
                                        break;
                                    }
                                }
                                if (selected_file_indexes != null) {
                                    if (!selected_file_indexes.contains(file.getIndex())) {
                                        continue;
                                    }
                                }
                                long file_length = file.getLength();
                                if (file.getDownloaded() == file_length) {
                                    already_complete++;
                                    continue;
                                }
                                Set<File> candidates = file_map.get(file_length);
                                if (candidates != null) {
                                    if (candidates.size() > 0) {
                                        if (all_dm_incomplete_files == null) {
                                            all_dm_incomplete_files = new HashSet<>();
                                            List<DownloadManager> all_dms = CoreFactory.getSingleton().getGlobalManager().getDownloadManagers();
                                            for (DownloadManager x : all_dms) {
                                                if (!x.isDownloadComplete(false)) {
                                                    DiskManagerFileInfo[] fs = x.getDiskManagerFileInfoSet().getFiles();
                                                    for (DiskManagerFileInfo f : fs) {
                                                        if (f.isSkipped() || f.getDownloaded() != f.getLength()) {
                                                            all_dm_incomplete_files.add(f.getFile(true).getAbsolutePath());
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        Iterator<File> it = candidates.iterator();
                                        while (it.hasNext()) {
                                            File f = it.next();
                                            if (all_dm_incomplete_files.contains(f.getAbsolutePath())) {
                                                it.remove();
                                            }
                                        }
                                    }
                                    if (candidates.size() > 0) {
                                        // duplicate now as this is download-specific
                                        candidates = new HashSet<>(candidates);
                                        if (dm_files == null) {
                                            dm_files = new HashSet<>();
                                            for (DiskManagerFileInfo f : files) {
                                                dm_files.add(f.getFile(true).getAbsolutePath());
                                            }
                                        }
                                        Iterator<File> it = candidates.iterator();
                                        while (it.hasNext()) {
                                            File f = it.next();
                                            if (dm_files.contains(f.getAbsolutePath())) {
                                                it.remove();
                                            }
                                        }
                                    }
                                    if (candidates.size() > 0) {
                                        boolean matched = false;
                                        Set<String> failed_candidates = new HashSet<>();
                                        TOTorrentFile to_file = file.getTorrentFile();
                                        long offset = 0;
                                        for (TOTorrentFile tf : to_files) {
                                            if (tf == to_file) {
                                                break;
                                            }
                                            offset += tf.getLength();
                                        }
                                        int to_piece_number = to_file.getFirstPieceNumber();
                                        long to_file_offset = offset % piece_size;
                                        if (to_file_offset != 0) {
                                            to_file_offset = piece_size - to_file_offset;
                                            to_piece_number++;
                                        }
                                        long to_stop_at = file_length - piece_size;
                                        if (to_file_offset < to_stop_at) {
                                            logLine(viewer, "    " + candidates.size() + " candidate(s) for " + to_file.getRelativePath() + " (size=" + DisplayFormatters.formatByteCountToKiBEtc(to_file.getLength()) + ")");
                                            byte[] buffer = new byte[(int) piece_size];
                                            for (File candidate : candidates) {
                                                synchronized (quit) {
                                                    if (quit[0]) {
                                                        break;
                                                    }
                                                }
                                                log(viewer, "        Testing " + candidate);
                                                RandomAccessFile raf = null;
                                                boolean error = false;
                                                boolean hash_failed = false;
                                                long last_ok_log = SystemTime.getMonotonousTime();
                                                try {
                                                    raf = new RandomAccessFile(candidate, "r");
                                                    long file_offset = to_file_offset;
                                                    int piece_number = to_piece_number;
                                                    while (file_offset < to_stop_at) {
                                                        synchronized (quit) {
                                                            if (quit[0]) {
                                                                break;
                                                            }
                                                        }
                                                        raf.seek(file_offset);
                                                        raf.read(buffer);
                                                        ConcurrentHasherRequest req = hasher.addRequest(ByteBuffer.wrap(buffer));
                                                        byte[] hash = req.getResult();
                                                        boolean match = Arrays.equals(pieces[piece_number], hash);
                                                        if (match) {
                                                            long now = SystemTime.getMonotonousTime();
                                                            if (now - last_ok_log >= 250) {
                                                                last_ok_log = now;
                                                                log(viewer, ".");
                                                            }
                                                            file_offset += piece_size;
                                                            piece_number++;
                                                        } else {
                                                            hash_failed = true;
                                                            failed_candidates.add(candidate.getAbsolutePath());
                                                            logLine(viewer, "X");
                                                            break;
                                                        }
                                                    }
                                                } catch (Throwable e) {
                                                    logLine(viewer, "X");
                                                    error = true;
                                                } finally {
                                                    if (raf != null) {
                                                        try {
                                                            raf.close();
                                                        } catch (Throwable e) {
                                                        }
                                                    }
                                                }
                                                if (!(error || hash_failed)) {
                                                    logLine(viewer, " Matched");
                                                    try {
                                                        dm.setUserData("set_link_dont_delete_existing", true);
                                                        if (file.setLink(candidate)) {
                                                            logLine(viewer, "        Link successful");
                                                            links_established.put(file, candidate);
                                                            link_count++;
                                                            matched = true;
                                                            if (link_count > MAX_LINKS) {
                                                                logLine(viewer, "    " + LINK_LIMIT_MSG);
                                                                break download_loop;
                                                            }
                                                        } else {
                                                            logLine(viewer, "        Link failed");
                                                        }
                                                    } finally {
                                                        dm.setUserData("set_link_dont_delete_existing", null);
                                                    }
                                                    break;
                                                }
                                            }
                                        }
                                        if (!matched) {
                                            unmatched_files.put(file, failed_candidates);
                                        }
                                    } else {
                                        no_candidates++;
                                    }
                                } else {
                                    no_candidates++;
                                }
                            }
                            logLine(viewer, "    Matched=" + links_established.size() + ", complete=" + already_complete + ", no candidates=" + no_candidates + ", remaining=" + unmatched_files.size() + " (total=" + files.length + ")");
                            if (links_established.size() > 0 && unmatched_files.size() > 0) {
                                logLine(viewer, "    Looking for other potential name-based matches");
                                File overall_root = null;
                                for (Map.Entry<DiskManagerFileInfo, File> entry : links_established.entrySet()) {
                                    DiskManagerFileInfo dm_file = entry.getKey();
                                    File root = entry.getValue();
                                    String rel = dm_file.getTorrentFile().getRelativePath();
                                    int pos = 0;
                                    while (root != null) {
                                        root = root.getParentFile();
                                        pos = rel.indexOf(File.separatorChar, pos);
                                        if (pos >= 0) {
                                            pos = pos + 1;
                                        } else {
                                            break;
                                        }
                                    }
                                    if (root == null) {
                                        logLine(viewer, "        No usable root folder found");
                                        break;
                                    }
                                    if (overall_root == null) {
                                        overall_root = root;
                                    } else {
                                        if (!overall_root.equals(root)) {
                                            overall_root = null;
                                            logLine(viewer, "        Inconsistent root folder found");
                                            break;
                                        }
                                    }
                                }
                                if (overall_root != null) {
                                    logLine(viewer, "        Root folder is " + overall_root.getAbsolutePath());
                                    int links_ok = 0;
                                    for (Map.Entry<DiskManagerFileInfo, Set<String>> entry : unmatched_files.entrySet()) {
                                        synchronized (quit) {
                                            if (quit[0]) {
                                                break;
                                            }
                                        }
                                        DiskManagerFileInfo file = entry.getKey();
                                        if (selected_file_indexes != null) {
                                            if (!selected_file_indexes.contains(file.getIndex())) {
                                                continue;
                                            }
                                        }
                                        File expected_file = new File(overall_root, file.getTorrentFile().getRelativePath());
                                        if (expected_file.exists() && expected_file.length() == file.getLength()) {
                                            if (!entry.getValue().contains(expected_file.getAbsolutePath())) {
                                                try {
                                                    dm.setUserData("set_link_dont_delete_existing", true);
                                                    if (file.setLink(expected_file)) {
                                                        links_ok++;
                                                        link_count++;
                                                        if (link_count > MAX_LINKS) {
                                                            logLine(viewer, "        " + LINK_LIMIT_MSG);
                                                            break;
                                                        }
                                                    }
                                                } finally {
                                                    dm.setUserData("set_link_dont_delete_existing", null);
                                                }
                                            }
                                        }
                                    }
                                    logLine(viewer, "        Linked " + links_ok + " of " + unmatched_files.size());
                                }
                            }
                        } finally {
                            if (link_count > 0) {
                                dm.forceRecheck();
                                downloads_modified++;
                            }
                        }
                    }
                    logLine(viewer, new SimpleDateFormat().format(new Date()) + ": Complete, downloads updated=" + downloads_modified);
                } catch (Throwable e) {
                    log(viewer, "\r\n" + new SimpleDateFormat().format(new Date()) + ": Failed: " + Debug.getNestedExceptionMessage(e) + "\r\n");
                }
            }
        }.start();
        viewer.goModal();
    }
}
Also used : DiskManagerFileInfoSet(com.biglybt.core.disk.DiskManagerFileInfoSet) DownloadManager(com.biglybt.core.download.DownloadManager) TextViewerWindow(com.biglybt.ui.swt.TextViewerWindow) DirectoryDialog(org.eclipse.swt.widgets.DirectoryDialog) DiskManagerFileInfo(com.biglybt.core.disk.DiskManagerFileInfo) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) TOTorrent(com.biglybt.core.torrent.TOTorrent) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) SimpleDateFormat(java.text.SimpleDateFormat)

Example 3 with TOTorrentFile

use of com.biglybt.core.torrent.TOTorrentFile in project BiglyBT by BiglySoftware.

the class ManagerUtils method browse.

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<>();

                private String protocol;

                private String host;

                private int port;

                @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<>();
                    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<>();
                                    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();
                    }
                    port = getServerPort();
                    log("Assigned port: " + port);
                    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 query = absolute_url.getQuery();
                    if (query != null) {
                        String[] args = query.split("&");
                        String vuze_source = null;
                        int vuze_file_index = -1;
                        String vuze_file_name = null;
                        List<String> networks = new ArrayList<>();
                        for (String arg : args) {
                            String[] bits = arg.split("=");
                            String lhs = bits[0];
                            String rhs = UrlUtils.decode(bits[1]);
                            if (lhs.equals("vuze_source")) {
                                if (rhs.endsWith(".torrent") || rhs.startsWith("magnet")) {
                                    vuze_source = rhs;
                                }
                            } else if (lhs.equals("vuze_file_index")) {
                                vuze_file_index = Integer.parseInt(rhs);
                            } else if (lhs.equals("vuze_file_name")) {
                                vuze_file_name = rhs;
                            } else if (lhs.equals("vuze_network")) {
                                String net = AENetworkClassifier.internalise(rhs);
                                if (net != null) {
                                    networks.add(net);
                                }
                            }
                        }
                        if (vuze_source != null) {
                            String referrer = (String) request.getHeaders().get("referer");
                            if (referrer == null || !referrer.contains("://" + host + ":" + port)) {
                                response.setReplyStatus(403);
                                return (true);
                            }
                            if (vuze_source.endsWith(".torrent")) {
                                Object file_node = file_map.get(vuze_source);
                                if (file_node instanceof DiskManagerFileInfo) {
                                    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;
                                    if (done) {
                                        return (handleRedirect(dm, target_file, vuze_file_index, vuze_file_name, networks, request, response));
                                    } else {
                                        try {
                                            File torrent_file = AETemporaryFileHandler.createTempFile();
                                            final FileOutputStream fos = new FileOutputStream(torrent_file);
                                            try {
                                                DiskManagerChannel chan = PluginCoreUtils.wrap(dm_file).createChannel();
                                                try {
                                                    final DiskManagerRequest req = chan.createRequest();
                                                    req.setOffset(0);
                                                    req.setLength(file_size);
                                                    req.addListener(new DiskManagerListener() {

                                                        @Override
                                                        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 {
                                                                byte[] data = buffer.toByteArray();
                                                                fos.write(data);
                                                            } catch (IOException e) {
                                                                throw (new RuntimeException("Failed to write to " + file, e));
                                                            } finally {
                                                                buffer.returnToPool();
                                                            }
                                                        }
                                                    });
                                                    req.run();
                                                } finally {
                                                    chan.destroy();
                                                }
                                            } finally {
                                                fos.close();
                                            }
                                            return (handleRedirect(dm, torrent_file, vuze_file_index, vuze_file_name, networks, request, response));
                                        } catch (Throwable e) {
                                            Debug.out(e);
                                            return (false);
                                        }
                                    }
                                } else {
                                    return (false);
                                }
                            } else {
                                URL magnet = new URL(vuze_source);
                                File torrent_file = AETemporaryFileHandler.createTempFile();
                                try {
                                    URLConnection connection = magnet.openConnection();
                                    connection.connect();
                                    FileUtil.copyFile(connection.getInputStream(), torrent_file.getAbsoluteFile());
                                    return (handleRedirect(dm, torrent_file, vuze_file_index, vuze_file_name, networks, request, response));
                                } catch (Throwable e) {
                                    Debug.out(e);
                                }
                            }
                        }
                    }
                    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) {
                        if (relative_url.equals("/favicon.ico")) {
                            try {
                                InputStream stream = getClass().getClassLoader().getResourceAsStream("com/biglybt/ui/icons/favicon.ico");
                                response.useStream("image/x-icon", stream);
                                return (true);
                            } catch (Throwable e) {
                            }
                        }
                        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 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<>(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);

                            @Override
                            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();
                            StringBuilder line = new StringBuilder(max_filename + 64);
                            line.append("<a href=\"").append(entry[0]).append("\">").append(XUXmlWriter.escapeXML(file_name)).append("</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>" + Constants.APP_NAME + " 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;
                        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 (file_size >= 512 * 1024) {
                            String content_type = HTTPUtils.guessContentTypeFromFileType(file_type);
                            if (content_type.startsWith("text/") || content_type.startsWith("image/")) {
                            // don't want to be redirecting here as (for example) .html needs
                            // to remain in the 'correct' place so that relative assets work
                            } else {
                                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);
                                }
                            }
                        }
                        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();
                                    os.write(("HTTP/1.1 200 OK" + NL + "Content-Type:" + HTTPUtils.guessContentTypeFromFileType(file_type) + NL + "Content-Length: " + file_size + NL + "Connection: close" + NL + NL).getBytes("UTF-8"));
                                    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);
                            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();
                                try {
                                    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() {

                                        @Override
                                        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;

                                        @Override
                                        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);
                                } finally {
                                    chan.destroy();
                                }
                            } catch (Throwable e) {
                                return (false);
                            }
                        }
                    }
                }

                private boolean handleRedirect(DownloadManager dm, File torrent_file, int file_index, String file_name, List<String> networks, TrackerWebPageRequest request, TrackerWebPageResponse response) {
                    try {
                        TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedFile(torrent_file);
                        GlobalManager gm = CoreFactory.getSingleton().getGlobalManager();
                        UIFunctions uif = UIFunctionsManager.getUIFunctions();
                        TorrentOpenOptions torrent_options = new TorrentOpenOptions(torrent_file.getAbsolutePath(), torrent, false);
                        torrent_options.setTorrent(torrent);
                        String[] existing_nets;
                        if (networks.size() == 0) {
                            // inherit networks from parent
                            existing_nets = dm.getDownloadState().getNetworks();
                        } else {
                            existing_nets = networks.toArray(new String[networks.size()]);
                        }
                        for (String net : AENetworkClassifier.AT_NETWORKS) {
                            boolean found = false;
                            for (String x : existing_nets) {
                                if (net == x) {
                                    found = true;
                                    break;
                                }
                            }
                            torrent_options.setNetworkEnabled(net, found);
                        }
                        Map<String, Object> add_options = new HashMap<>();
                        add_options.put(UIFunctions.OTO_SILENT, true);
                        if (uif.addTorrentWithOptions(torrent_options, add_options)) {
                            long start = SystemTime.getMonotonousTime();
                            while (true) {
                                DownloadManager o_dm = gm.getDownloadManager(torrent);
                                if (o_dm != null) {
                                    if (!o_dm.getDownloadState().getFlag(DownloadManagerState.FLAG_METADATA_DOWNLOAD)) {
                                        DiskManagerFileInfo[] files = o_dm.getDiskManagerFileInfoSet().getFiles();
                                        DiskManagerFileInfo o_dm_file = null;
                                        if (file_name != null) {
                                            for (DiskManagerFileInfo file : files) {
                                                String path = file.getTorrentFile().getRelativePath();
                                                if (path.equals(file_name)) {
                                                    o_dm_file = file;
                                                    break;
                                                }
                                            }
                                            if (o_dm_file == null) {
                                                o_dm_file = files[0];
                                            }
                                        } else {
                                            if (file_index < 0) {
                                                long largest = -1;
                                                for (DiskManagerFileInfo file : files) {
                                                    if (file.getLength() > largest) {
                                                        o_dm_file = file;
                                                        largest = file.getLength();
                                                    }
                                                }
                                            } else {
                                                o_dm_file = files[file_index];
                                            }
                                        }
                                        String original_path = request.getAbsoluteURL().getPath();
                                        if (original_path.endsWith(".html")) {
                                            String url = browse(o_dm, file_index < 0 ? null : o_dm_file, anon, false);
                                            OutputStream os = response.getRawOutputStream();
                                            os.write(("HTTP/1.1 302 Found" + NL + "Location: " + url + NL + NL).getBytes("UTF-8"));
                                            return (true);
                                        } else {
                                            URL stream_url = getMediaServerContentURL(o_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);
                                            }
                                        }
                                    }
                                }
                                long now = SystemTime.getMonotonousTime();
                                if (now - start > 3 * 60 * 1000) {
                                    Debug.out("Timeout waiting for download to be added");
                                    return (false);
                                }
                                Thread.sleep(1000);
                            }
                        } else {
                            Debug.out("Failed to add download for some reason");
                            return (false);
                        }
                    } catch (Throwable e) {
                        Debug.out(e);
                        return (false);
                    }
                }

                @Override
                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) {
                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);
            }
        }
    }
}
Also used : TrackerWebPageRequest(com.biglybt.pif.tracker.web.TrackerWebPageRequest) TrackerWebPageResponse(com.biglybt.pif.tracker.web.TrackerWebPageResponse) DownloadManager(com.biglybt.core.download.DownloadManager) GlobalManager(com.biglybt.core.global.GlobalManager) DiskManagerListener(com.biglybt.pif.disk.DiskManagerListener) UIFunctions(com.biglybt.ui.UIFunctions) DiskManagerChannel(com.biglybt.pif.disk.DiskManagerChannel) PluginException(com.biglybt.pif.PluginException) DiskManagerFileInfoSet(com.biglybt.core.disk.DiskManagerFileInfoSet) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) InetAddress(java.net.InetAddress) DiskManagerFileInfoSet(com.biglybt.core.disk.DiskManagerFileInfoSet) URL(java.net.URL) TorrentOpenOptions(com.biglybt.core.torrent.impl.TorrentOpenOptions) PooledByteBuffer(com.biglybt.pif.utils.PooledByteBuffer) WebPlugin(com.biglybt.ui.webplugin.WebPlugin) DiskManagerFileInfo(com.biglybt.core.disk.DiskManagerFileInfo) DiskManagerRequest(com.biglybt.pif.disk.DiskManagerRequest) PluginInterface(com.biglybt.pif.PluginInterface) FormattersImpl(com.biglybt.pifimpl.local.utils.FormattersImpl) URLConnection(java.net.URLConnection) TOTorrent(com.biglybt.core.torrent.TOTorrent) DiskManagerEvent(com.biglybt.pif.disk.DiskManagerEvent)

Example 4 with TOTorrentFile

use of com.biglybt.core.torrent.TOTorrentFile in project BiglyBT by BiglySoftware.

the class LocaleTorrentUtil method getTorrentCandidates.

/**
 * Checks the Torrent's text fields (path, comment, etc) against a list
 * of locals, returning only those that can handle all the fields.
 *
 * @param torrent
 * @return
 * @throws TOTorrentException
 * @throws UnsupportedEncodingException
 */
protected static LocaleUtilDecoderCandidate[] getTorrentCandidates(TOTorrent torrent) throws TOTorrentException, UnsupportedEncodingException {
    long lMinCandidates;
    byte[] minCandidatesArray;
    Set cand_set = new HashSet();
    LocaleUtil localeUtil = LocaleUtil.getSingleton();
    List candidateDecoders = localeUtil.getCandidateDecoders(torrent.getName());
    lMinCandidates = candidateDecoders.size();
    minCandidatesArray = torrent.getName();
    cand_set.addAll(candidateDecoders);
    TOTorrentFile[] files = torrent.getFiles();
    for (int i = 0; i < files.length; i++) {
        TOTorrentFile file = files[i];
        byte[][] comps = file.getPathComponents();
        for (int j = 0; j < comps.length; j++) {
            candidateDecoders = localeUtil.getCandidateDecoders(comps[j]);
            if (candidateDecoders.size() < lMinCandidates) {
                lMinCandidates = candidateDecoders.size();
                minCandidatesArray = comps[j];
            }
            cand_set.retainAll(candidateDecoders);
        }
    }
    byte[] comment = torrent.getComment();
    if (comment != null) {
        candidateDecoders = localeUtil.getCandidateDecoders(comment);
        if (candidateDecoders.size() < lMinCandidates) {
            lMinCandidates = candidateDecoders.size();
            minCandidatesArray = comment;
        }
        cand_set.retainAll(candidateDecoders);
    }
    byte[] created = torrent.getCreatedBy();
    if (created != null) {
        candidateDecoders = localeUtil.getCandidateDecoders(created);
        if (candidateDecoders.size() < lMinCandidates) {
            lMinCandidates = candidateDecoders.size();
            minCandidatesArray = created;
        }
        cand_set.retainAll(candidateDecoders);
    }
    List candidatesList = localeUtil.getCandidatesAsList(minCandidatesArray);
    LocaleUtilDecoderCandidate[] candidates;
    candidates = new LocaleUtilDecoderCandidate[candidatesList.size()];
    candidatesList.toArray(candidates);
    Arrays.sort(candidates, new Comparator() {

        @Override
        public int compare(Object o1, Object o2) {
            LocaleUtilDecoderCandidate luc1 = (LocaleUtilDecoderCandidate) o1;
            LocaleUtilDecoderCandidate luc2 = (LocaleUtilDecoderCandidate) o2;
            LocaleUtilDecoder dec1 = luc1.getDecoder();
            LocaleUtilDecoder dec2 = luc2.getDecoder();
            int res = dec1.getIndex() - dec2.getIndex();
            if (res == 0) {
                return (0);
            }
            String n1 = dec1.getName();
            String n2 = dec2.getName();
            if (n1.equals("UTF-8")) {
                return (-1);
            } else if (n2.equals("UTF-8")) {
                return (1);
            } else {
                return (res);
            }
        }
    });
    return candidates;
}
Also used : TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile)

Example 5 with TOTorrentFile

use of com.biglybt.core.torrent.TOTorrentFile in project BiglyBT by BiglySoftware.

the class TorrentImpl method getFiles.

@Override
public TorrentFile[] getFiles() {
    TOTorrentFile[] files = torrent.getFiles();
    TorrentFile[] res = new TorrentFile[files.length];
    for (int i = 0; i < res.length; i++) {
        TOTorrentFile tf = files[i];
        byte[][] comps = tf.getPathComponents();
        String name = "";
        for (int j = 0; j < comps.length; j++) {
            String comp = decode(comps[j]);
            comp = FileUtil.convertOSSpecificChars(comp, j != comps.length - 1);
            name += (j == 0 ? "" : File.separator) + comp;
        }
        res[i] = new TorrentFileImpl(name, tf.getLength());
    }
    return (res);
}
Also used : TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile)

Aggregations

TOTorrentFile (com.biglybt.core.torrent.TOTorrentFile)25 TOTorrent (com.biglybt.core.torrent.TOTorrent)11 File (java.io.File)9 DiskManagerFileInfo (com.biglybt.core.disk.DiskManagerFileInfo)5 DownloadManager (com.biglybt.core.download.DownloadManager)4 LocaleUtilDecoder (com.biglybt.core.internat.LocaleUtilDecoder)4 IOException (java.io.IOException)4 URL (java.net.URL)4 CacheFile (com.biglybt.core.diskmanager.cache.CacheFile)3 FMFileManagerException (com.biglybt.core.diskmanager.file.FMFileManagerException)3 DiskManager (com.biglybt.core.disk.DiskManager)2 DiskManagerFileInfoSet (com.biglybt.core.disk.DiskManagerFileInfoSet)2 DiskManagerPiece (com.biglybt.core.disk.DiskManagerPiece)2 FMFile (com.biglybt.core.diskmanager.file.FMFile)2 DownloadManagerException (com.biglybt.core.download.DownloadManagerException)2 DownloadManagerState (com.biglybt.core.download.DownloadManagerState)2 TOTorrentException (com.biglybt.core.torrent.TOTorrentException)2 PluginInterface (com.biglybt.pif.PluginInterface)2 Download (com.biglybt.pif.download.Download)2 RandomAccessFile (java.io.RandomAccessFile)2