package org.basex.io; import static org.basex.core.Text.*; import java.io.*; import java.net.*; import java.nio.file.*; import java.security.*; import java.security.cert.*; import javax.net.ssl.*; import javax.xml.transform.stream.*; import org.basex.core.*; import org.basex.io.in.*; import org.basex.util.*; import org.basex.util.http.*; import org.xml.sax.*; /** * {@link IO} reference, representing a URL. * * @author BaseX Team 2005-17, BSD License * @author Christian Gruen */ public final class IOUrl extends IO { /** Timeout for connecting to a resource (seconds). */ private static final int TIMEOUT = 10; /** * Constructor. * @param url url */ public IOUrl(final String url) { super(url); } @Override public byte[] read() throws IOException { return new BufferInput(this).content(); } @Override public InputSource inputSource() { return new InputSource(pth); } @Override public StreamSource streamSource() { return new StreamSource(pth); } @Override public InputStream inputStream() throws IOException { URLConnection conn = null; try { conn = connection(); return conn.getInputStream(); } catch(final IOException ex) { final TokenBuilder msg = new TokenBuilder(Util.message(ex)); // try to retrieve more information on why the request failed if(conn instanceof HttpURLConnection) { final InputStream es = ((HttpURLConnection) conn).getErrorStream(); if(es != null) { final byte[] error = new IOStream(es).read(); if(error.length != 0) msg.add(NL).add(INFORMATION).add(COL).add(NL).add(error); } } final IOException io = new IOException(msg.toString()); io.setStackTrace(ex.getStackTrace()); throw io; } catch(final RuntimeException ex) { // catch unexpected runtime exceptions Util.debug(ex); throw new BaseXException(NOT_PARSED_X, pth); } } /** * Returns a connection to the URL. * @return connection * @throws IOException I/O exception */ public URLConnection connection() throws IOException { final URL url = new URL(pth); final URLConnection conn = url.openConnection(); conn.setConnectTimeout(TIMEOUT * 1000); // use basic authentication if credentials are contained in the url final String ui = url.getUserInfo(); if(ui != null) conn.setRequestProperty(HttpText.AUTHORIZATION, HttpText.BASIC + ' ' + org.basex.util.Base64.encode(ui)); return conn; } @Override public boolean isDir() { return pth.endsWith("/"); } /** * Checks if the specified uri starts with a valid scheme. * @param url url to be converted * @return file path */ static boolean isValid(final String url) { int u = -1; final int us = url.length(); while(++u < us) { final char c = url.charAt(u); if(!Token.letterOrDigit(c) && c != '+' && c != '-' && c != '.') break; } return u > 2 && u + 1 < us && url.charAt(u) == ':' && url.charAt(u + 1) == '/'; } /** * Normalizes the specified URI and creates a new instance of this class. * @param uri uri to be converted * @return file path */ static String toFile(final String uri) { try { final String path = Paths.get(new URI(uri)).toString(); return uri.endsWith("/") || uri.endsWith("\\") ? path + File.separator : path; } catch(final Exception ex) { Util.errln(ex); return uri; } } /** * Checks if the specified string is a valid file URL. * @param url url to be tested * @return result of check */ static boolean isFileURL(final String url) { return url.startsWith(FILEPREF); } /** * Ignore certificates. */ public static void ignoreCert() { // http://www.rgagnon.com/javadetails/java-fix-certificate-problem-in-HTTPS.html HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(final String hostname, final SSLSession session) { return true; } }); final TrustManager[] tm = { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(final X509Certificate[] certs, final String authType) { } @Override public void checkServerTrusted(final X509Certificate[] certs, final String authType) { } }}; try { final SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, tm, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch(final Exception ex) { Util.errln(ex); } } }