Search in sources :

Example 11 with PluginProxy

use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.

the class TorrentDownloaderImpl method runSupport.

@Override
public void runSupport() {
    try {
        // determine if this is already a proper URL
        new URL(url_str);
    } catch (Throwable t) {
        // it's not
        // check if the string is just a base32/hex-encoded torrent infohash
        String magnet_uri = UrlUtils.normaliseMagnetURI(url_str);
        if (magnet_uri != null) {
            url_str = magnet_uri;
        }
    }
    try {
        url = AddressUtils.adjustURL(new URL(url_str));
        String protocol = url.getProtocol().toLowerCase(Locale.US);
        if (protocol.equals("magnet") || protocol.equals("maggot") || protocol.equals("dht")) {
            url = AddressUtils.adjustURL(new URL(url_str + (url_str.contains("?") ? "&" : "?") + "pause_on_error=true"));
        }
        Set<String> redirect_urls = new HashSet<>();
        boolean follow_redirect = true;
        URL current_url = url;
        Proxy current_proxy = proxy;
        PluginProxy current_plugin_proxy = AEProxyFactory.getPluginProxy(current_proxy);
        redirect_label: while (follow_redirect) {
            follow_redirect = false;
            boolean dh_hack = false;
            boolean internal_error_hack = false;
            for (int connect_loop = 0; connect_loop < 3; connect_loop++) {
                protocol = current_url.getProtocol().toLowerCase(Locale.US);
                try {
                    if (protocol.equals("https")) {
                        // see ConfigurationChecker for SSL client defaults
                        HttpsURLConnection ssl_con;
                        if (current_proxy == null) {
                            ssl_con = (HttpsURLConnection) current_url.openConnection();
                        } else {
                            ssl_con = (HttpsURLConnection) current_url.openConnection(current_proxy);
                        }
                        if (!internal_error_hack) {
                            // allow for certs that contain IP addresses rather than dns names
                            ssl_con.setHostnameVerifier(new HostnameVerifier() {

                                @Override
                                public boolean verify(String host, SSLSession session) {
                                    return (true);
                                }
                            });
                        }
                        if (dh_hack) {
                            UrlUtils.DHHackIt(ssl_con);
                        }
                        if (connect_loop > 0) {
                            // meh, some https trackers are just screwed
                            TrustManager[] trustAllCerts = SESecurityManager.getAllTrustingTrustManager();
                            try {
                                SSLContext sc = SSLContext.getInstance("SSL");
                                sc.init(null, trustAllCerts, RandomUtils.SECURE_RANDOM);
                                SSLSocketFactory factory = sc.getSocketFactory();
                                ssl_con.setSSLSocketFactory(factory);
                            } catch (Throwable e) {
                            }
                        }
                        if (internal_error_hack) {
                            if (current_plugin_proxy != null) {
                                String host = current_plugin_proxy.getURLHostRewrite();
                                UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
                            }
                        }
                        con = ssl_con;
                    } else {
                        if (current_proxy == null) {
                            con = current_url.openConnection();
                        } else {
                            con = current_url.openConnection(current_proxy);
                        }
                    }
                    if (con instanceof HttpURLConnection) {
                        // we want this true but some plugins (grrr) set the global default not to follow
                        // redirects
                        ((HttpURLConnection) con).setInstanceFollowRedirects(proxy == null);
                    }
                    Properties props = new Properties();
                    ClientIDManagerImpl.getSingleton().getGenerator().generateHTTPProperties(null, props);
                    String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
                    con.setRequestProperty("User-Agent", ua);
                    if (referrer != null && referrer.length() > 0) {
                        con.setRequestProperty("Referer", referrer);
                    }
                    if (request_properties != null) {
                        Iterator it = request_properties.entrySet().iterator();
                        while (it.hasNext()) {
                            Map.Entry entry = (Map.Entry) it.next();
                            String key = (String) entry.getKey();
                            String value = (String) entry.getValue();
                            if (!key.equalsIgnoreCase("Accept-Encoding")) {
                                con.setRequestProperty(key, value);
                            }
                        }
                    }
                    this.con.connect();
                    String magnetURI = con.getHeaderField("Magnet-Uri");
                    if (magnetURI != null) {
                        closeConnection();
                        url_str = magnetURI;
                        runSupport();
                        return;
                    }
                    int response = con instanceof HttpURLConnection ? ((HttpURLConnection) con).getResponseCode() : HttpURLConnection.HTTP_OK;
                    if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
                        // auto redirect doesn't work from http to https or vice-versa
                        String move_to = con.getHeaderField("location");
                        if (move_to != null) {
                            if (redirect_urls.contains(move_to) || redirect_urls.size() > 32) {
                                break;
                            }
                            redirect_urls.add(move_to);
                            try {
                                // don't URL decode the move-to as its already in the right format!
                                // URLDecoder.decode( move_to, "UTF-8" ));
                                URL move_to_url = new URL(move_to);
                                boolean follow = false;
                                if (current_plugin_proxy != null) {
                                    PluginProxy child = current_plugin_proxy.getChildProxy("redirect", move_to_url);
                                    if (child != null) {
                                        // use an overall property to force this through on the redirect
                                        request_properties.put("HOST", child.getURLHostRewrite() + (move_to_url.getPort() == -1 ? "" : (":" + move_to_url.getPort())));
                                        current_proxy = child.getProxy();
                                        move_to_url = child.getURL();
                                        follow = true;
                                    }
                                }
                                String original_protocol = current_url.getProtocol().toLowerCase();
                                String new_protocol = move_to_url.getProtocol().toLowerCase();
                                if (follow || !original_protocol.equals(new_protocol)) {
                                    current_url = move_to_url;
                                    try {
                                        List<String> cookies_list = con.getHeaderFields().get("Set-cookie");
                                        List<String> cookies_set = new ArrayList<>();
                                        if (cookies_list != null) {
                                            for (int i = 0; i < cookies_list.size(); i++) {
                                                String[] cookie_bits = ((String) cookies_list.get(i)).split(";");
                                                if (cookie_bits.length > 0) {
                                                    cookies_set.add(cookie_bits[0]);
                                                }
                                            }
                                        }
                                        if (cookies_set.size() > 0) {
                                            String new_cookies = "";
                                            Object obj = request_properties.get("Cookie");
                                            if (obj instanceof String) {
                                                new_cookies = (String) obj;
                                            }
                                            for (String s : cookies_set) {
                                                new_cookies += (new_cookies.length() == 0 ? "" : "; ") + s;
                                            }
                                            request_properties.put("Cookie", new_cookies);
                                        }
                                    } catch (Throwable e) {
                                        Debug.out(e);
                                    }
                                    follow_redirect = true;
                                    continue redirect_label;
                                }
                            } catch (Throwable e) {
                            }
                        }
                    }
                    break;
                } catch (SSLException e) {
                    if (connect_loop < 3) {
                        String msg = Debug.getNestedExceptionMessage(e);
                        boolean try_again = false;
                        if (msg.contains("DH keypair")) {
                            if (!dh_hack) {
                                dh_hack = true;
                                try_again = true;
                            }
                        } else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
                            if (!internal_error_hack) {
                                internal_error_hack = true;
                                try_again = true;
                            }
                        }
                        if (current_plugin_proxy == null) {
                            if (SESecurityManager.installServerCertificates(url) != null) {
                                // certificate has been installed
                                try_again = true;
                            }
                        }
                        if (url != current_url && current_plugin_proxy == null && SESecurityManager.installServerCertificates(current_url) != null) {
                            // certificate has been installed
                            try_again = true;
                        }
                        if (try_again) {
                            continue;
                        }
                    }
                    throw (e);
                } catch (IOException e) {
                    if (connect_loop == 0) {
                        URL retry_url = UrlUtils.getIPV4Fallback(url);
                        if (retry_url != null) {
                            url = retry_url;
                        } else {
                            throw (e);
                        }
                    }
                    if (e instanceof UnknownHostException) {
                        throw (e);
                    }
                }
            }
        }
        int response = con instanceof HttpURLConnection ? ((HttpURLConnection) con).getResponseCode() : HttpURLConnection.HTTP_OK;
        if (!ignoreReponseCode) {
            if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) {
                this.error(response, Integer.toString(response) + ": " + ((HttpURLConnection) con).getResponseMessage());
                return;
            }
        }
        /*
      Map headerFields = this.con.getHeaderFields();

      System.out.println("Header of download of " + url_str);
      for (Iterator iter = headerFields.keySet().iterator(); iter.hasNext();) {
				String s = (String) iter.next();
				System.out.println(s + ":" + headerFields.get(s));

			}
	*/
        filename = this.con.getHeaderField("Content-Disposition");
        if ((filename != null) && filename.toLowerCase().matches(".*attachment.*")) {
            while (filename.toLowerCase().charAt(0) != 'a') {
                filename = filename.substring(1);
            }
        }
        // see if we can grab the filename directly (thanks Angel)
        Pattern p = Pattern.compile(".*filename=\\\"(.*)\\\"");
        Matcher m = null;
        if (filename != null && ((m = p.matcher(filename)) != null) && m.matches()) {
            filename = m.group(1).trim();
        } else if (filename == null || !filename.toLowerCase().startsWith("attachment") || filename.indexOf('=') == -1) {
            String tmp = this.url.getFile();
            if (tmp.length() == 0 || tmp.equals("/")) {
                filename = url.getHost();
            } else if (tmp.startsWith("?")) {
                // probably a magnet URI - use the hash
                // magnet:?xt=urn:sha1:VGC53ZWCUXUWVGX7LQPVZIYF4L6RXSU6
                String query = tmp.toUpperCase();
                int pos = query.indexOf("XT=URN:SHA1:");
                if (pos == -1) {
                    pos = query.indexOf("XT=URN:BTIH:");
                }
                if (pos != -1) {
                    pos += 12;
                    int p2 = query.indexOf("&", pos);
                    if (p2 == -1) {
                        filename = query.substring(pos);
                    } else {
                        filename = query.substring(pos, p2);
                    }
                } else {
                    filename = "Torrent" + (long) (Math.random() * Long.MAX_VALUE);
                }
                filename += ".tmp";
            } else {
                while (tmp.endsWith("/")) {
                    tmp = tmp.substring(0, tmp.length() - 1);
                }
                if (tmp.lastIndexOf('/') != -1) {
                    tmp = tmp.substring(tmp.lastIndexOf('/') + 1);
                }
                // remove any params in the url
                int param_pos = tmp.indexOf('?');
                if (param_pos != -1) {
                    tmp = tmp.substring(0, param_pos);
                }
                filename = URLDecoder.decode(tmp, Constants.DEFAULT_ENCODING);
                if (filename.length() == 0) {
                    filename = "Torrent" + (long) (Math.random() * Long.MAX_VALUE);
                }
            }
        } else {
            filename = filename.substring(filename.indexOf('=') + 1);
            if (filename.startsWith("\"") && filename.endsWith("\""))
                filename = filename.substring(1, filename.lastIndexOf('\"'));
            filename = URLDecoder.decode(filename, Constants.DEFAULT_ENCODING);
            // this code removes any parent directories from the filename we've extracted
            File temp = new File(filename);
            filename = temp.getName();
        }
        filename = FileUtil.convertOSSpecificChars(filename, false);
        directoryname = COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory");
        boolean useTorrentSave = COConfigurationManager.getBooleanParameter("Save Torrent Files");
        if (file_str != null) {
            // not completely sure about the whole logic in this block
            File temp = new File(file_str);
            // if we're not using a default torrent save dir
            if (!useTorrentSave || directoryname.length() == 0) {
                // if it's already a dir
                if (temp.isDirectory()) {
                    // use it
                    directoryname = temp.getCanonicalPath();
                } else // it's a file
                {
                    // so use its parent dir
                    directoryname = temp.getCanonicalFile().getParent();
                }
            }
            // if it's a file
            if (!temp.isDirectory()) {
                // set the file name
                filename = temp.getName();
            }
        }
        // what would happen here if directoryname == null and file_str == null??
        this.state = STATE_INIT;
        this.notifyListener();
    } catch (java.net.MalformedURLException e) {
        this.error(0, "Exception while parsing URL '" + url_str + "':" + e.getMessage());
    } catch (java.net.UnknownHostException e) {
        this.error(0, "Exception while initializing download of '" + url + "': Unknown Host '" + e.getMessage() + "'");
    } catch (java.io.IOException ioe) {
        this.error(0, "I/O Exception while initializing download of '" + url + "':" + ioe.toString());
    } catch (Throwable e) {
        this.error(0, "Exception while initializing download of '" + url + "':" + e.toString());
    }
    if (this.state == STATE_ERROR) {
        return;
    }
    try {
        final boolean[] status_reader_run = { true };
        this.state = STATE_START;
        notifyListener();
        this.state = STATE_DOWNLOADING;
        notifyListener();
        if (con instanceof HttpURLConnection) {
            Thread status_reader = new AEThread("TorrentDownloader:statusreader") {

                @Override
                public void runSupport() {
                    HttpURLConnection http_con = (HttpURLConnection) con;
                    boolean changed_status = false;
                    String last_status = "";
                    boolean sleep = false;
                    long last_progress_update = SystemTime.getMonotonousTime();
                    while (true) {
                        try {
                            if (sleep) {
                                Thread.sleep(50);
                                sleep = false;
                            }
                            try {
                                this_mon.enter();
                                if (!status_reader_run[0]) {
                                    break;
                                }
                            } finally {
                                this_mon.exit();
                            }
                            String s = http_con.getResponseMessage();
                            if (s.equals(last_status)) {
                                sleep = true;
                            } else {
                                last_status = s;
                                String lc_s = s.toLowerCase();
                                if (!lc_s.startsWith("error:")) {
                                    if (s.toLowerCase().contains("alive")) {
                                        if (percentDone < 10) {
                                            percentDone++;
                                        }
                                    }
                                    boolean progress_update = false;
                                    int pos = s.indexOf('%');
                                    if (pos != -1) {
                                        int i;
                                        for (i = pos - 1; i >= 0; i--) {
                                            char c = s.charAt(i);
                                            if (!Character.isDigit(c) && c != ' ') {
                                                i++;
                                                break;
                                            }
                                        }
                                        try {
                                            percentDone = Integer.parseInt(s.substring(i, pos).trim());
                                            progress_update = true;
                                        } catch (Throwable e) {
                                        }
                                    }
                                    if (lc_s.startsWith("received")) {
                                        progress_update = true;
                                    }
                                    if (progress_update) {
                                        long now = SystemTime.getMonotonousTime();
                                        if (now - last_progress_update < 250) {
                                            continue;
                                        }
                                        last_progress_update = now;
                                    }
                                    setStatus(s);
                                } else {
                                    error(http_con.getResponseCode(), s.substring(6));
                                }
                                changed_status = true;
                            }
                        } catch (Throwable e) {
                            break;
                        }
                    }
                    if (changed_status) {
                        setStatus("");
                    }
                }
            };
            status_reader.setDaemon(true);
            status_reader.start();
        }
        InputStream in = null;
        FileOutputStream fileout = null;
        try {
            try {
                in = this.con.getInputStream();
            } catch (FileNotFoundException e) {
                if (ignoreReponseCode) {
                    if (con instanceof HttpURLConnection) {
                        in = ((HttpURLConnection) con).getErrorStream();
                    } else {
                        in = null;
                    }
                } else {
                    throw e;
                }
            } finally {
                try {
                    this_mon.enter();
                    status_reader_run[0] = false;
                } finally {
                    this_mon.exit();
                }
            }
            // handle some servers that return gzip'd torrents even though we don't request it!
            String encoding = con.getHeaderField("content-encoding");
            if (encoding != null) {
                if (encoding.equalsIgnoreCase("gzip")) {
                    in = new GZIPInputStream(in);
                } else if (encoding.equalsIgnoreCase("deflate")) {
                    in = new InflaterInputStream(in);
                }
            }
            if (this.state != STATE_ERROR) {
                this.file = new File(this.directoryname, filename);
                boolean useTempFile = file.exists();
                if (!useTempFile) {
                    try {
                        this.file.createNewFile();
                        useTempFile = !this.file.exists();
                    } catch (Throwable t) {
                        useTempFile = true;
                    }
                }
                if (useTempFile) {
                    this.file = File.createTempFile("AZU", ".torrent", new File(this.directoryname));
                    this.file.createNewFile();
                }
                fileout = new FileOutputStream(this.file, false);
                bufBytes = 0;
                int size = (int) UrlUtils.getContentLength(con);
                this.percentDone = -1;
                do {
                    if (this.cancel) {
                        break;
                    }
                    try {
                        bufBytes = in.read(buf);
                        this.readTotal += bufBytes;
                        if (size > 0) {
                            this.percentDone = (100 * this.readTotal) / size;
                        }
                        notifyListener();
                    } catch (IOException e) {
                    }
                    if (bufBytes > 0) {
                        fileout.write(buf, 0, bufBytes);
                    }
                } while (bufBytes > 0);
                in.close();
                fileout.flush();
                fileout.close();
                if (this.cancel) {
                    this.state = STATE_CANCELLED;
                    if (deleteFileOnCancel) {
                        this.cleanUpFile();
                    }
                } else {
                    if (this.readTotal <= 0) {
                        this.error(0, "No data contained in '" + this.url.toString() + "'");
                        return;
                    }
                    try {
                        if (!filename.toLowerCase().endsWith(".torrent")) {
                            TOTorrent torrent = TorrentUtils.readFromFile(file, false);
                            String name = TorrentUtils.getLocalisedName(torrent) + ".torrent";
                            File new_file = new File(directoryname, name);
                            if (file.renameTo(new_file)) {
                                filename = name;
                                file = new_file;
                            }
                        }
                    } catch (Throwable e) {
                        boolean is_vuze_file = false;
                        try {
                            if (VuzeFileHandler.isAcceptedVuzeFileName(filename)) {
                                is_vuze_file = true;
                            } else {
                                if (VuzeFileHandler.getSingleton().loadVuzeFile(file) != null) {
                                    is_vuze_file = true;
                                    String name = VuzeFileHandler.getVuzeFileName(filename);
                                    File new_file = new File(directoryname, name);
                                    if (file.renameTo(new_file)) {
                                        filename = name;
                                        file = new_file;
                                    }
                                }
                            }
                        } catch (Throwable f) {
                        }
                        if (!is_vuze_file) {
                            if (!RSSUtils.isRSSFeed(file)) {
                                Debug.printStackTrace(e);
                            }
                        }
                    }
                    if (proxy == null) {
                        TorrentUtils.setObtainedFrom(file, original_url);
                    }
                    this.state = STATE_FINISHED;
                }
                this.notifyListener();
            }
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Throwable e) {
                }
            }
            if (fileout != null) {
                try {
                    fileout.close();
                } catch (Throwable e) {
                }
            }
        }
    } catch (Throwable e) {
        String url_log_string = this.url_str.toString().replaceAll("\\Q&pause_on_error=true\\E", "");
        String log_msg = MessageText.getString("torrentdownload.error.dl_fail", new String[] { url_log_string, file == null ? filename : file.getAbsolutePath(), e.getMessage() });
        if (!cancel) {
            Debug.out(log_msg, e);
        }
        this.error(0, log_msg);
    }
}
Also used : Matcher(java.util.regex.Matcher) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) GZIPInputStream(java.util.zip.GZIPInputStream) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) java.net(java.net) Pattern(java.util.regex.Pattern) java.io(java.io) GZIPInputStream(java.util.zip.GZIPInputStream) InflaterInputStream(java.util.zip.InflaterInputStream) InflaterInputStream(java.util.zip.InflaterInputStream) TOTorrent(com.biglybt.core.torrent.TOTorrent)

Example 12 with PluginProxy

use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.

the class ResourceDownloaderURLImpl method download.

@Override
public InputStream download() throws ResourceDownloaderException {
    try {
        reportActivity(this, getLogIndent() + "Downloading: " + trimForDisplay(original_url));
        try {
            this_mon.enter();
            if (download_initiated) {
                throw (new ResourceDownloaderException(this, "Download already initiated"));
            }
            download_initiated = true;
        } finally {
            this_mon.exit();
        }
        try {
            URL outer_url = new URL(original_url.toString().replaceAll(" ", "%20"));
            // some authentications screw up without an explicit port number here
            String protocol = outer_url.getProtocol().toLowerCase();
            if (protocol.equals("vuze") || protocol.equals("biglybt")) {
                outer_url = original_url;
            } else if (protocol.equals("file")) {
                File file = new File(original_url.toURI());
                FileInputStream fis = new FileInputStream(file);
                informAmountComplete(file.length());
                informPercentDone(100);
                informComplete(fis);
                return (fis);
            } else if (outer_url.getPort() == -1 && (protocol.equals("http") || protocol.equals("https"))) {
                int target_port;
                if (protocol.equals("http")) {
                    target_port = 80;
                } else {
                    target_port = 443;
                }
                try {
                    String str = original_url.toString().replaceAll(" ", "%20");
                    int pos = str.indexOf("://");
                    pos = str.indexOf("/", pos + 4);
                    if (pos == -1) {
                        outer_url = new URL(str + ":" + target_port + "/");
                    } else {
                        outer_url = new URL(str.substring(0, pos) + ":" + target_port + str.substring(pos));
                    }
                } catch (Throwable e) {
                    Debug.printStackTrace(e);
                }
            }
            outer_url = AddressUtils.adjustURL(outer_url);
            try {
                if (force_no_proxy) {
                    AEProxySelectorFactory.getSelector().startNoProxy();
                }
                if (auth_supplied) {
                    SESecurityManager.setPasswordHandler(outer_url, this);
                }
                boolean use_compression = true;
                boolean follow_redirect = true;
                boolean dh_hack = false;
                boolean internal_error_hack = false;
                Set<String> redirect_urls = new HashSet<>();
                URL current_url = outer_url;
                Proxy current_proxy = force_proxy;
                PluginProxy current_plugin_proxy = null;
                URL initial_url = current_url;
                redirect_label: while (follow_redirect) {
                    follow_redirect = false;
                    PluginProxy plugin_proxy_auto;
                    boolean ok = false;
                    if (auto_plugin_proxy || isAnonymous()) {
                        plugin_proxy_auto = AEProxyFactory.getPluginProxy("downloading resource", current_url);
                        if (plugin_proxy_auto == null) {
                            throw (new ResourceDownloaderException(this, "No plugin proxy available"));
                        }
                        current_url = plugin_proxy_auto.getURL();
                        current_proxy = plugin_proxy_auto.getProxy();
                    } else {
                        plugin_proxy_auto = null;
                    }
                    try {
                        SSLSocketFactory ssl_socket_factory = null;
                        for (int connect_loop = 0; connect_loop < 3; connect_loop++) {
                            File temp_file = null;
                            try {
                                URLConnection con;
                                current_plugin_proxy = plugin_proxy_auto == null ? AEProxyFactory.getPluginProxy(force_proxy) : plugin_proxy_auto;
                                if (current_url.getProtocol().equalsIgnoreCase("https")) {
                                    // see ConfigurationChecker for SSL client defaults
                                    HttpsURLConnection ssl_con = (HttpsURLConnection) openConnection(current_proxy, current_url);
                                    if (ssl_socket_factory != null) {
                                        ssl_con.setSSLSocketFactory(ssl_socket_factory);
                                    }
                                    if (!internal_error_hack) {
                                        // for some reason, on java 8 at least, even setting a host name verifier
                                        // causes an SSL internal_error on some websites :(
                                        // allow for certs that contain IP addresses rather than dns names
                                        ssl_con.setHostnameVerifier(new HostnameVerifier() {

                                            @Override
                                            public boolean verify(String host, SSLSession session) {
                                                return (true);
                                            }
                                        });
                                    }
                                    if (current_plugin_proxy != null) {
                                        // unfortunately the use of an intermediate host name causes
                                        // SSL to completely fail (the hostname verifier above isn't enough to
                                        // stop borkage) so what can we do?
                                        // actually, not sure why, but when I hacked in this delegator things magically
                                        // started working :(
                                        TrustManagerFactory tmf = SESecurityManager.getTrustManagerFactory();
                                        final List<X509TrustManager> default_tms = new ArrayList<>();
                                        if (tmf != null) {
                                            for (TrustManager tm : tmf.getTrustManagers()) {
                                                if (tm instanceof X509TrustManager) {
                                                    default_tms.add((X509TrustManager) tm);
                                                }
                                            }
                                        }
                                        TrustManager[] tms_delegate = SESecurityManager.getAllTrustingTrustManager(new X509TrustManager() {

                                            @Override
                                            public X509Certificate[] getAcceptedIssuers() {
                                                List<X509Certificate> result = new ArrayList<>();
                                                for (X509TrustManager tm : default_tms) {
                                                    result.addAll(Arrays.asList(tm.getAcceptedIssuers()));
                                                }
                                                return (result.toArray(new X509Certificate[result.size()]));
                                            }

                                            @Override
                                            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                                                for (X509TrustManager tm : default_tms) {
                                                    tm.checkClientTrusted(chain, authType);
                                                }
                                            }

                                            @Override
                                            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                                                for (X509TrustManager tm : default_tms) {
                                                    tm.checkServerTrusted(chain, authType);
                                                }
                                            }
                                        });
                                        SSLContext sc = SSLContext.getInstance("SSL");
                                        sc.init(null, tms_delegate, RandomUtils.SECURE_RANDOM);
                                        SSLSocketFactory factory = sc.getSocketFactory();
                                        ssl_con.setSSLSocketFactory(factory);
                                    }
                                    if (dh_hack) {
                                        UrlUtils.DHHackIt(ssl_con);
                                    }
                                    if (internal_error_hack && current_plugin_proxy != null) {
                                        String host = current_plugin_proxy.getURLHostRewrite();
                                        UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
                                    }
                                    con = ssl_con;
                                } else {
                                    con = openConnection(current_proxy, current_url);
                                }
                                if (con instanceof HttpURLConnection) {
                                    if (current_plugin_proxy != null) {
                                        // need to manually handle redirects as we need to re-proxy
                                        ((HttpURLConnection) con).setInstanceFollowRedirects(false);
                                    } else {
                                        ((HttpURLConnection) con).setInstanceFollowRedirects(true);
                                    }
                                }
                                if (current_plugin_proxy != null) {
                                    con.setRequestProperty("HOST", current_plugin_proxy.getURLHostRewrite() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
                                }
                                ClientIDGenerator cidg = ClientIDManagerImpl.getSingleton().getGenerator();
                                if (cidg != null) {
                                    Properties props = new Properties();
                                    cidg.generateHTTPProperties(null, props);
                                    String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
                                    con.setRequestProperty("User-Agent", ua);
                                }
                                String connection = getStringProperty("URL_Connection");
                                if (connection != null && connection.equalsIgnoreCase("Keep-Alive")) {
                                    con.setRequestProperty("Connection", "Keep-Alive");
                                // gah, no idea what the intent behind 'skip' is!
                                } else if (connection == null || !connection.equals("skip")) {
                                    // default is close
                                    con.setRequestProperty("Connection", "close");
                                }
                                if (use_compression) {
                                    con.addRequestProperty("Accept-Encoding", "gzip");
                                }
                                setRequestProperties(con, use_compression);
                                if (post_data != null && con instanceof HttpURLConnection) {
                                    con.setDoOutput(true);
                                    String verb = (String) getStringProperty("URL_HTTP_VERB");
                                    if (verb == null) {
                                        verb = "POST";
                                    }
                                    ((HttpURLConnection) con).setRequestMethod(verb);
                                    if (post_data.length > 0) {
                                        OutputStream os = con.getOutputStream();
                                        os.write(post_data);
                                        os.flush();
                                    }
                                }
                                long connect_timeout = getLongProperty("URL_Connect_Timeout");
                                if (connect_timeout >= 0) {
                                    con.setConnectTimeout((int) connect_timeout);
                                }
                                long read_timeout = getLongProperty("URL_Read_Timeout");
                                if (read_timeout >= 0) {
                                    con.setReadTimeout((int) read_timeout);
                                }
                                boolean trust_content_length = getBooleanProperty("URL_Trust_Content_Length");
                                try {
                                    con.connect();
                                } catch (AEProxyFactory.UnknownHostException e) {
                                    throw (new UnknownHostException(e.getMessage()));
                                }
                                int response = con instanceof HttpURLConnection ? ((HttpURLConnection) con).getResponseCode() : HttpURLConnection.HTTP_OK;
                                ok = true;
                                if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
                                    // auto redirect doesn't work from http to https or vice-versa
                                    String move_to = con.getHeaderField("location");
                                    if (move_to != null) {
                                        if (redirect_urls.contains(move_to) || redirect_urls.size() > 32) {
                                            throw (new ResourceDownloaderException(this, "redirect loop"));
                                        }
                                        redirect_urls.add(move_to);
                                        try {
                                            // don't URL decode the move-to as its already in the right format!
                                            // URLDecoder.decode( move_to, "UTF-8" ));
                                            URL move_to_url = new URL(move_to);
                                            boolean follow = false;
                                            if (current_plugin_proxy != null) {
                                                PluginProxy child = current_plugin_proxy.getChildProxy("redirect", move_to_url);
                                                if (child != null) {
                                                    initial_url = move_to_url;
                                                    // use an overall property to force this through on the redirect
                                                    setProperty("URL_HOST", initial_url.getHost() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
                                                    current_proxy = child.getProxy();
                                                    move_to_url = child.getURL();
                                                    follow = true;
                                                }
                                            }
                                            String original_protocol = current_url.getProtocol().toLowerCase();
                                            String new_protocol = move_to_url.getProtocol().toLowerCase();
                                            if (follow || !original_protocol.equals(new_protocol)) {
                                                current_url = move_to_url;
                                                try {
                                                    List<String> cookies_list = con.getHeaderFields().get("Set-cookie");
                                                    List<String> cookies_set = new ArrayList<>();
                                                    if (cookies_list != null) {
                                                        for (int i = 0; i < cookies_list.size(); i++) {
                                                            String[] cookie_bits = ((String) cookies_list.get(i)).split(";");
                                                            if (cookie_bits.length > 0) {
                                                                cookies_set.add(cookie_bits[0]);
                                                            }
                                                        }
                                                    }
                                                    if (cookies_set.size() > 0) {
                                                        String new_cookies = "";
                                                        Map properties = getLCKeyProperties();
                                                        Object obj = properties.get("url_cookie");
                                                        if (obj instanceof String) {
                                                            new_cookies = (String) obj;
                                                        }
                                                        for (String s : cookies_set) {
                                                            new_cookies += (new_cookies.length() == 0 ? "" : "; ") + s;
                                                        }
                                                        setProperty("URL_Cookie", new_cookies);
                                                    }
                                                } catch (Throwable e) {
                                                    Debug.out(e);
                                                }
                                                follow_redirect = true;
                                                continue redirect_label;
                                            }
                                        } catch (Throwable e) {
                                        }
                                    }
                                }
                                setProperty("URL_HTTP_Response", new Long(response));
                                if (response != HttpURLConnection.HTTP_CREATED && response != HttpURLConnection.HTTP_ACCEPTED && response != HttpURLConnection.HTTP_NO_CONTENT && response != HttpURLConnection.HTTP_OK) {
                                    HttpURLConnection http_con = (HttpURLConnection) con;
                                    InputStream error_stream = http_con.getErrorStream();
                                    String error_str = null;
                                    if (error_stream != null) {
                                        String encoding = con.getHeaderField("content-encoding");
                                        if (encoding != null) {
                                            if (encoding.equalsIgnoreCase("gzip")) {
                                                error_stream = new GZIPInputStream(error_stream);
                                            } else if (encoding.equalsIgnoreCase("deflate")) {
                                                error_stream = new InflaterInputStream(error_stream);
                                            }
                                        }
                                        error_str = FileUtil.readInputStreamAsString(error_stream, 512);
                                    }
                                    // grab properties anyway as they may be useful
                                    getRequestProperties(con);
                                    URL dest = current_url;
                                    if (current_plugin_proxy != null) {
                                        try {
                                            dest = new URL(current_plugin_proxy.getTarget());
                                        } catch (Throwable e) {
                                        }
                                    }
                                    throw (new ResourceDownloaderException(this, "Error on connect for '" + trimForDisplay(dest) + "': " + Integer.toString(response) + " " + http_con.getResponseMessage() + (error_str == null ? "" : (": error=" + error_str))));
                                }
                                getRequestProperties(con);
                                boolean compressed = false;
                                try {
                                    this_mon.enter();
                                    input_stream = con.getInputStream();
                                    String encoding = con.getHeaderField("content-encoding");
                                    if (encoding != null) {
                                        if (encoding.equalsIgnoreCase("gzip")) {
                                            compressed = true;
                                            input_stream = new GZIPInputStream(input_stream);
                                        } else if (encoding.equalsIgnoreCase("deflate")) {
                                            compressed = true;
                                            input_stream = new InflaterInputStream(input_stream);
                                        }
                                    }
                                } finally {
                                    this_mon.exit();
                                }
                                if (con instanceof MagnetConnection2) {
                                    // hack - status reports for magnet connections are returned
                                    List<String> errors = ((MagnetConnection2) con).getResponseMessages(true);
                                    if (errors.size() > 0) {
                                        throw (new ResourceDownloaderException(this, errors.get(0)));
                                    }
                                }
                                ByteArrayOutputStream baos = null;
                                FileOutputStream fos = null;
                                try {
                                    byte[] buf = new byte[BUFFER_SIZE];
                                    long total_read = 0;
                                    // unfortunately not all servers set content length
                                    /* From Apache's mod_deflate doc:
										 * http://httpd.apache.org/docs/2.0/mod/mod_deflate.html
												Note on Content-Length

												If you evaluate the request body yourself, don't trust the
												Content-Length header! The Content-Length header reflects
												the length of the incoming data from the client and not the
												byte count of the decompressed data stream.
										 */
                                    long size = compressed ? -1 : UrlUtils.getContentLength(con);
                                    baos = size > 0 ? new ByteArrayOutputStream(size > MAX_IN_MEM_READ_SIZE ? MAX_IN_MEM_READ_SIZE : (int) size) : new ByteArrayOutputStream();
                                    while (!cancel_download) {
                                        if (size >= 0 && total_read >= size && trust_content_length) {
                                            break;
                                        }
                                        int read = input_stream.read(buf);
                                        if (read > 0) {
                                            if (total_read > MAX_IN_MEM_READ_SIZE) {
                                                if (fos == null) {
                                                    temp_file = AETemporaryFileHandler.createTempFile();
                                                    fos = new FileOutputStream(temp_file);
                                                    fos.write(baos.toByteArray());
                                                    baos = null;
                                                }
                                                fos.write(buf, 0, read);
                                            } else {
                                                baos.write(buf, 0, read);
                                            }
                                            total_read += read;
                                            informAmountComplete(total_read);
                                            if (size > 0) {
                                                informPercentDone((int) ((100 * total_read) / size));
                                            }
                                        } else {
                                            break;
                                        }
                                    }
                                    if (size > 0 && total_read != size) {
                                        if (total_read > size) {
                                            // this has been seen with UPnP linksys - more data is read than
                                            // the content-length has us believe is coming (1 byte in fact...)
                                            Debug.outNoStack("Inconsistent stream length for '" + trimForDisplay(original_url) + "': expected = " + size + ", actual = " + total_read);
                                        } else {
                                            throw (new IOException("Premature end of stream"));
                                        }
                                    }
                                } finally {
                                    if (fos != null) {
                                        try {
                                            fos.close();
                                        } catch (Throwable e) {
                                        }
                                    }
                                    input_stream.close();
                                }
                                InputStream res;
                                if (temp_file != null) {
                                    res = new DeleteFileOnCloseInputStream(temp_file);
                                    temp_file = null;
                                } else {
                                    res = new ByteArrayInputStream(baos.toByteArray());
                                }
                                boolean handed_over = false;
                                try {
                                    if (informComplete(res)) {
                                        handed_over = true;
                                        return (res);
                                    }
                                } finally {
                                    if (!handed_over) {
                                        res.close();
                                    }
                                }
                                throw (new ResourceDownloaderException(this, "Contents downloaded but rejected: '" + trimForDisplay(original_url) + "'"));
                            } catch (SSLException e) {
                                String msg = Debug.getNestedExceptionMessage(e);
                                if (connect_loop < 3) {
                                    boolean try_again = false;
                                    if (msg.contains("DH keypair")) {
                                        if (!dh_hack) {
                                            dh_hack = true;
                                            try_again = true;
                                        }
                                    } else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
                                        if (!internal_error_hack) {
                                            internal_error_hack = true;
                                            try_again = true;
                                        }
                                    }
                                    ssl_socket_factory = SESecurityManager.installServerCertificates(current_url);
                                    if (ssl_socket_factory != null) {
                                        // certificate has been installed
                                        try_again = true;
                                    }
                                    if (try_again) {
                                        continue;
                                    }
                                }
                                throw (e);
                            } catch (ZipException e) {
                                if (connect_loop == 0) {
                                    use_compression = false;
                                    continue;
                                }
                            } catch (IOException e) {
                                if (connect_loop == 0) {
                                    String msg = e.getMessage();
                                    if (msg != null) {
                                        msg = msg.toLowerCase(MessageText.LOCALE_ENGLISH);
                                        if (msg.contains("gzip")) {
                                            use_compression = false;
                                            continue;
                                        }
                                    }
                                    URL retry_url = UrlUtils.getIPV4Fallback(current_url);
                                    if (retry_url != null) {
                                        current_url = retry_url;
                                        continue;
                                    }
                                }
                                throw (e);
                            } finally {
                                if (temp_file != null) {
                                    temp_file.delete();
                                }
                            }
                        }
                    } finally {
                        if (plugin_proxy_auto != null) {
                            plugin_proxy_auto.setOK(ok);
                        }
                    }
                }
                throw (new ResourceDownloaderException(this, "Should never get here"));
            } finally {
                if (auth_supplied) {
                    SESecurityManager.setPasswordHandler(outer_url, null);
                }
                if (force_no_proxy) {
                    AEProxySelectorFactory.getSelector().endNoProxy();
                }
            }
        } catch (java.net.MalformedURLException e) {
            throw (new ResourceDownloaderException(this, "Exception while parsing URL '" + trimForDisplay(original_url) + "':" + e.getMessage(), e));
        } catch (java.net.UnknownHostException e) {
            throw (new ResourceDownloaderException(this, "Exception while initializing download of '" + trimForDisplay(original_url) + "': Unknown Host '" + e.getMessage() + "'", e));
        } catch (java.io.IOException e) {
            throw (new ResourceDownloaderException(this, "I/O Exception while downloading '" + trimForDisplay(original_url) + "'", e));
        }
    } catch (Throwable e) {
        ResourceDownloaderException rde;
        if (e instanceof ResourceDownloaderException) {
            rde = (ResourceDownloaderException) e;
        } else {
            Debug.out(e);
            rde = new ResourceDownloaderException(this, "Unexpected error", e);
        }
        informFailed(rde);
        throw (rde);
    }
}
Also used : java.net(java.net) ClientIDGenerator(com.biglybt.pif.clientid.ClientIDGenerator) java.io(java.io) X509Certificate(java.security.cert.X509Certificate) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) GZIPInputStream(java.util.zip.GZIPInputStream) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) GZIPInputStream(java.util.zip.GZIPInputStream) InflaterInputStream(java.util.zip.InflaterInputStream) InflaterInputStream(java.util.zip.InflaterInputStream) ZipException(java.util.zip.ZipException) MagnetConnection2(com.biglybt.core.util.protocol.magnet.MagnetConnection2)

Example 13 with PluginProxy

use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.

the class ResourceDownloaderURLImpl method getSizeSupport.

protected long getSizeSupport() throws ResourceDownloaderException {
    try {
        String protocol = original_url.getProtocol().toLowerCase();
        if (protocol.equals("magnet") || protocol.equals("maggot") || protocol.equals("dht") || protocol.equals("vuze") || protocol.equals("biglybt") || protocol.equals("azplug") || protocol.equals("ftp")) {
            return (-1);
        } else if (protocol.equals("file")) {
            return (new File(original_url.toURI()).length());
        }
        reportActivity(this, "Getting size of " + original_url);
        try {
            URL url = new URL(original_url.toString().replaceAll(" ", "%20"));
            url = AddressUtils.adjustURL(url);
            URL initial_url = url;
            PluginProxy plugin_proxy;
            boolean ok = false;
            if (auto_plugin_proxy || isAnonymous()) {
                plugin_proxy = AEProxyFactory.getPluginProxy("downloading resource", url);
                if (plugin_proxy == null) {
                    throw (new ResourceDownloaderException(this, "No plugin proxy available"));
                }
                url = plugin_proxy.getURL();
                force_proxy = plugin_proxy.getProxy();
            } else {
                plugin_proxy = null;
            }
            try {
                if (force_no_proxy) {
                    AEProxySelectorFactory.getSelector().startNoProxy();
                }
                if (auth_supplied) {
                    SESecurityManager.setPasswordHandler(url, this);
                }
                boolean dh_hack = false;
                boolean internal_error_hack = false;
                SSLSocketFactory ssl_socket_factory = null;
                for (int connect_loop = 0; connect_loop < 2; connect_loop++) {
                    try {
                        HttpURLConnection con;
                        if (url.getProtocol().equalsIgnoreCase("https")) {
                            // see ConfigurationChecker for SSL client defaults
                            HttpsURLConnection ssl_con = (HttpsURLConnection) openConnection(force_proxy, url);
                            if (ssl_socket_factory != null) {
                                ssl_con.setSSLSocketFactory(ssl_socket_factory);
                            }
                            if (!internal_error_hack) {
                                ssl_con.setHostnameVerifier(new HostnameVerifier() {

                                    @Override
                                    public boolean verify(String host, SSLSession session) {
                                        return (true);
                                    }
                                });
                            }
                            if (plugin_proxy != null) {
                                TrustManagerFactory tmf = SESecurityManager.getTrustManagerFactory();
                                final List<X509TrustManager> default_tms = new ArrayList<>();
                                if (tmf != null) {
                                    for (TrustManager tm : tmf.getTrustManagers()) {
                                        if (tm instanceof X509TrustManager) {
                                            default_tms.add((X509TrustManager) tm);
                                        }
                                    }
                                }
                                TrustManager[] tms_delegate = SESecurityManager.getAllTrustingTrustManager(new X509TrustManager() {

                                    @Override
                                    public X509Certificate[] getAcceptedIssuers() {
                                        List<X509Certificate> result = new ArrayList<>();
                                        for (X509TrustManager tm : default_tms) {
                                            result.addAll(Arrays.asList(tm.getAcceptedIssuers()));
                                        }
                                        return (result.toArray(new X509Certificate[result.size()]));
                                    }

                                    @Override
                                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                                        for (X509TrustManager tm : default_tms) {
                                            tm.checkClientTrusted(chain, authType);
                                        }
                                    }

                                    @Override
                                    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                                        for (X509TrustManager tm : default_tms) {
                                            tm.checkServerTrusted(chain, authType);
                                        }
                                    }
                                });
                                SSLContext sc = SSLContext.getInstance("SSL");
                                sc.init(null, tms_delegate, RandomUtils.SECURE_RANDOM);
                                SSLSocketFactory factory = sc.getSocketFactory();
                                ssl_con.setSSLSocketFactory(factory);
                            }
                            if (dh_hack) {
                                UrlUtils.DHHackIt(ssl_con);
                            }
                            if (internal_error_hack && plugin_proxy != null) {
                                String host = plugin_proxy.getURLHostRewrite();
                                UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
                            }
                            con = ssl_con;
                        } else {
                            con = (HttpURLConnection) openConnection(force_proxy, url);
                        }
                        con.setInstanceFollowRedirects(plugin_proxy == null);
                        if (plugin_proxy != null) {
                            con.setRequestProperty("HOST", plugin_proxy.getURLHostRewrite() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
                        }
                        con.setRequestMethod("HEAD");
                        ClientIDGenerator cidg = ClientIDManagerImpl.getSingleton().getGenerator();
                        if (cidg != null) {
                            Properties props = new Properties();
                            cidg.generateHTTPProperties(null, props);
                            String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
                            con.setRequestProperty("User-Agent", ua);
                        }
                        setRequestProperties(con, false);
                        try {
                            con.connect();
                        } catch (AEProxyFactory.UnknownHostException e) {
                            throw (new UnknownHostException(e.getMessage()));
                        }
                        int response = con.getResponseCode();
                        setProperty("URL_HTTP_Response", new Long(response));
                        if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) {
                            if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
                                // cheap option for the moment
                                return (-1);
                            }
                            URL dest = url;
                            if (plugin_proxy != null) {
                                try {
                                    dest = new URL(plugin_proxy.getTarget());
                                } catch (Throwable e) {
                                }
                            }
                            throw (new ResourceDownloaderException(this, "Error on connect for '" + trimForDisplay(dest) + "': " + Integer.toString(response) + " " + con.getResponseMessage()));
                        }
                        getRequestProperties(con);
                        ok = true;
                        return (UrlUtils.getContentLength(con));
                    } catch (SSLException e) {
                        String msg = Debug.getNestedExceptionMessage(e);
                        if (connect_loop < 3) {
                            boolean try_again = false;
                            if (msg.contains("DH keypair")) {
                                if (!dh_hack) {
                                    dh_hack = true;
                                    try_again = true;
                                }
                            } else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
                                if (!internal_error_hack) {
                                    internal_error_hack = true;
                                    try_again = true;
                                }
                            }
                            ssl_socket_factory = SESecurityManager.installServerCertificates(url);
                            if (ssl_socket_factory != null) {
                                // certificate has been installed
                                try_again = true;
                            }
                            if (try_again) {
                                continue;
                            }
                        }
                        throw (e);
                    } catch (IOException e) {
                        if (connect_loop == 0) {
                            URL retry_url = UrlUtils.getIPV4Fallback(url);
                            if (retry_url != null) {
                                url = retry_url;
                                continue;
                            }
                        }
                        throw (e);
                    }
                }
                throw (new ResourceDownloaderException(this, "Should never get here"));
            } finally {
                if (auth_supplied) {
                    SESecurityManager.setPasswordHandler(url, null);
                }
                if (force_no_proxy) {
                    AEProxySelectorFactory.getSelector().endNoProxy();
                }
                if (plugin_proxy != null) {
                    plugin_proxy.setOK(ok);
                    force_proxy = null;
                }
            }
        } catch (java.net.MalformedURLException e) {
            throw (new ResourceDownloaderException(this, "Exception while parsing URL '" + original_url + "':" + e.getMessage(), e));
        } catch (java.net.UnknownHostException e) {
            throw (new ResourceDownloaderException(this, "Exception while initializing download of '" + trimForDisplay(original_url) + "': Unknown Host '" + e.getMessage() + "'", e));
        } catch (java.io.IOException e) {
            throw (new ResourceDownloaderException(this, "I/O Exception while downloading '" + trimForDisplay(original_url) + "'", e));
        }
    } catch (Throwable e) {
        ResourceDownloaderException rde;
        if (e instanceof ResourceDownloaderException) {
            rde = (ResourceDownloaderException) e;
        } else {
            Debug.out(e);
            rde = new ResourceDownloaderException(this, "Unexpected error", e);
        }
        throw (rde);
    }
}
Also used : PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) CertificateException(java.security.cert.CertificateException) java.net(java.net) ClientIDGenerator(com.biglybt.pif.clientid.ClientIDGenerator) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) java.io(java.io) X509Certificate(java.security.cert.X509Certificate) AEProxyFactory(com.biglybt.core.proxy.AEProxyFactory)

Example 14 with PluginProxy

use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.

the class UtilitiesImpl method getRSSFeed.

@Override
public RSSFeed getRSSFeed(URL feed_location) throws ResourceDownloaderException, SimpleXMLParserDocumentException {
    String feed_str = feed_location.toExternalForm();
    String lc_feed_str = feed_str.toLowerCase(Locale.US);
    ResourceDownloader rd;
    PluginProxy plugin_proxy = null;
    try {
        if (lc_feed_str.startsWith("tor:")) {
            String target_resource = feed_str.substring(4);
            try {
                feed_location = new URL(target_resource);
            } catch (MalformedURLException e) {
                throw (new ResourceDownloaderException(e));
            }
            Map<String, Object> options = new HashMap<>();
            options.put(AEProxyFactory.PO_PEER_NETWORKS, new String[] { AENetworkClassifier.AT_TOR });
            plugin_proxy = AEProxyFactory.getPluginProxy("RSS Feed download of '" + target_resource + "'", feed_location, options, true);
            if (plugin_proxy == null) {
                throw (new ResourceDownloaderException("No Tor plugin proxy available for '" + feed_str + "'"));
            }
            rd = getResourceDownloaderFactory().create(plugin_proxy.getURL(), plugin_proxy.getProxy());
            rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort() == -1 ? "" : (":" + feed_location.getPort())));
        } else {
            if (AENetworkClassifier.categoriseAddress(feed_location.getHost()) != AENetworkClassifier.AT_PUBLIC) {
                plugin_proxy = AEProxyFactory.getPluginProxy("RSS Feed download of '" + feed_location + "'", feed_location, true);
                if (plugin_proxy == null) {
                    throw (new ResourceDownloaderException("No Plugin proxy available for '" + feed_str + "'"));
                }
                rd = getResourceDownloaderFactory().create(plugin_proxy.getURL(), plugin_proxy.getProxy());
                rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort() == -1 ? "" : (":" + feed_location.getPort())));
            } else {
                rd = getResourceDownloaderFactory().create(feed_location);
            }
        }
        return (getRSSFeed(feed_location, rd));
    } finally {
        if (plugin_proxy != null) {
            plugin_proxy.setOK(true);
        }
    }
}
Also used : MalformedURLException(java.net.MalformedURLException) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) ResourceDownloader(com.biglybt.pif.utils.resourcedownloader.ResourceDownloader) URL(java.net.URL)

Example 15 with PluginProxy

use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.

the class ExternalSeedHTTPDownloaderRange method downloadSocket.

public void downloadSocket(String[] prop_names, String[] prop_values, int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail) throws ExternalSeedException {
    Socket socket = null;
    boolean connected = false;
    PluginProxy plugin_proxy = null;
    boolean proxy_ok = false;
    try {
        String output_header = "GET " + very_original_url.getPath() + "?" + very_original_url.getQuery() + " HTTP/1.1" + NL + "Host: " + very_original_url.getHost() + (very_original_url.getPort() == -1 ? "" : (":" + very_original_url.getPort())) + NL + "Accept: */*" + NL + "Connection: Close" + // if we want to support keep-alive we'll need to implement a socket cache etc.
        NL + "User-Agent: " + user_agent + NL;
        for (int i = 0; i < prop_names.length; i++) {
            output_header += prop_names[i] + ":" + prop_values[i] + NL;
        }
        output_header += NL;
        int time_remaining = listener.getPermittedTime();
        URL original_url = very_original_url;
        URL current_url = original_url;
        Proxy current_proxy = null;
        if (AENetworkClassifier.categoriseAddress(very_original_url.getHost()) != AENetworkClassifier.AT_PUBLIC) {
            plugin_proxy = AEProxyFactory.getPluginProxy("webseed", original_url);
            if (plugin_proxy != null) {
                current_url = plugin_proxy.getURL();
                current_proxy = plugin_proxy.getProxy();
            }
        }
        if (time_remaining > 0) {
            if (current_proxy == null) {
                socket = new Socket();
            } else {
                socket = new Socket(current_proxy);
            }
            socket.connect(new InetSocketAddress(current_url.getHost(), current_url.getPort() == -1 ? current_url.getDefaultPort() : current_url.getPort()), time_remaining);
        } else {
            if (current_proxy == null) {
                socket = new Socket(current_url.getHost(), current_url.getPort() == -1 ? current_url.getDefaultPort() : current_url.getPort());
            } else {
                socket = new Socket(current_proxy);
                socket.connect(new InetSocketAddress(current_url.getHost(), current_url.getPort() == -1 ? current_url.getDefaultPort() : current_url.getPort()));
            }
        }
        connected = true;
        proxy_ok = true;
        time_remaining = listener.getPermittedTime();
        if (time_remaining < 0) {
            throw (new IOException("Timeout during connect"));
        } else if (time_remaining > 0) {
            socket.setSoTimeout(time_remaining);
        }
        OutputStream os = socket.getOutputStream();
        os.write(output_header.getBytes("ISO-8859-1"));
        os.flush();
        InputStream is = socket.getInputStream();
        try {
            String input_header = "";
            while (true) {
                byte[] buffer = new byte[1];
                int len = is.read(buffer);
                if (len < 0) {
                    throw (new IOException("input too short reading header"));
                }
                input_header += (char) buffer[0];
                if (input_header.endsWith(NL + NL)) {
                    break;
                }
            }
            // HTTP/1.1 403 Forbidden
            int line_end = input_header.indexOf(NL);
            if (line_end == -1) {
                throw (new IOException("header too short"));
            }
            String first_line = input_header.substring(0, line_end);
            StringTokenizer tok = new StringTokenizer(first_line, " ");
            tok.nextToken();
            int response = Integer.parseInt(tok.nextToken());
            last_response = response;
            last_response_retry_after_secs = -1;
            String response_str = tok.nextToken();
            if (response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL) {
                byte[] buffer = null;
                int buffer_pos = 0;
                int buffer_len = 0;
                int pos = 0;
                while (pos < length) {
                    if (buffer == null) {
                        buffer = listener.getBuffer();
                        buffer_pos = listener.getBufferPosition();
                        buffer_len = listener.getBufferLength();
                    }
                    int to_read = buffer_len - buffer_pos;
                    int permitted = listener.getPermittedBytes();
                    if (permitted < to_read) {
                        to_read = permitted;
                    }
                    int len = is.read(buffer, buffer_pos, to_read);
                    if (len < 0) {
                        break;
                    }
                    listener.reportBytesRead(len);
                    pos += len;
                    buffer_pos += len;
                    if (buffer_pos == buffer_len) {
                        listener.done();
                        buffer = null;
                        buffer_pos = 0;
                    }
                }
                if (pos != length) {
                    String log_str;
                    if (buffer == null) {
                        log_str = "No buffer assigned";
                    } else {
                        log_str = new String(buffer, 0, buffer_pos > 64 ? 64 : buffer_pos);
                    }
                    throw (new ExternalSeedException("Connection failed: data too short - " + length + "/" + pos + " [last=" + log_str + "]"));
                }
            // System.out.println( "download length: " + pos );
            } else if (response == 503) {
                // webseed support for temp unavail - read the data
                String data_str = "";
                while (true) {
                    byte[] buffer = new byte[1];
                    int len = is.read(buffer);
                    if (len < 0) {
                        break;
                    }
                    data_str += (char) buffer[0];
                }
                last_response_retry_after_secs = Integer.parseInt(data_str);
                throw (new IOException("Server overloaded"));
            } else {
                ExternalSeedException error = new ExternalSeedException("Connection failed: " + response_str);
                error.setPermanentFailure(true);
                throw (error);
            }
        } finally {
            is.close();
        }
    } catch (IOException e) {
        if (con_fail_is_perm_fail && !connected) {
            ExternalSeedException error = new ExternalSeedException("Connection failed: " + e.getMessage());
            error.setPermanentFailure(true);
            throw (error);
        } else {
            String outcome = "Connection failed: " + Debug.getNestedExceptionMessage(e);
            if (last_response_retry_after_secs >= 0) {
                outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
            }
            throw (new ExternalSeedException(outcome, e));
        }
    } catch (Throwable e) {
        if (e instanceof ExternalSeedException) {
            throw ((ExternalSeedException) e);
        }
        throw (new ExternalSeedException("Connection failed", e));
    } finally {
        if (socket != null) {
            try {
                socket.close();
            } catch (Throwable e) {
            }
        }
        if (plugin_proxy != null) {
            plugin_proxy.setOK(proxy_ok);
        }
    }
}
Also used : InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) IOException(java.io.IOException) ExternalSeedException(com.biglybt.plugin.extseed.ExternalSeedException) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) StringTokenizer(java.util.StringTokenizer)

Aggregations

PluginProxy (com.biglybt.core.proxy.AEProxyFactory.PluginProxy)18 URL (java.net.URL)7 ResourceDownloader (com.biglybt.pif.utils.resourcedownloader.ResourceDownloader)6 InputStream (java.io.InputStream)6 ResourceDownloaderException (com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException)5 Proxy (java.net.Proxy)4 LogEvent (com.biglybt.core.logging.LogEvent)3 java.io (java.io)3 java.net (java.net)3 ClientIDGenerator (com.biglybt.pif.clientid.ClientIDGenerator)2 ResourceDownloaderFactory (com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderFactory)2 SFPluginDetailsException (com.biglybt.pifimpl.update.sf.SFPluginDetailsException)2 ExternalSeedException (com.biglybt.plugin.extseed.ExternalSeedException)2 IOException (java.io.IOException)2 X509Certificate (java.security.cert.X509Certificate)2 GZIPInputStream (java.util.zip.GZIPInputStream)2 InflaterInputStream (java.util.zip.InflaterInputStream)2 Engine (com.biglybt.core.metasearch.Engine)1 SearchException (com.biglybt.core.metasearch.SearchException)1 WebEngine (com.biglybt.core.metasearch.impl.web.WebEngine)1