package org.commcare.network; import org.commcare.core.network.ModernHttpRequester; import org.commcare.logging.AndroidLogger; import org.javarosa.core.services.Logger; import java.io.IOException; import java.io.InputStream; import java.net.Authenticator; import java.net.HttpURLConnection; import java.net.PasswordAuthentication; import java.net.URL; /** * Makes simple redirect-following GET requests that can be authenticated or * not * * @author Phillip Mates (pmates@dimagi.com) */ class SimpleGetRequest { protected static InputStream makeRequest(final String username, final String password, URL url) throws IOException { if (username == null || password == null) { // clear any prior set authenticator to make unauthed requests Authenticator.setDefault(null); } else { // make authenticated requests Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication( HttpRequestGenerator.buildDomainUser(username), password.toCharArray()); } }); } return makeModernRequest(url); } private static InputStream makeModernRequest(URL url) throws IOException { int responseCode = -1; HttpURLConnection con = (HttpURLConnection)url.openConnection(); setupGetConnection(con); con.connect(); try { responseCode = con.getResponseCode(); return followRedirect(con).getInputStream(); } catch (IOException e) { if (e.getMessage().toLowerCase().contains("authentication") || responseCode == 401) { //Android http libraries _suuuuuck_, let's try apache. return null; } else { throw e; } } } private static HttpURLConnection followRedirect(HttpURLConnection httpConnection) throws IOException { final URL url = httpConnection.getURL(); if (httpConnection.getResponseCode() == 301) { String redirectString = url.toString() + " to " + httpConnection.getURL().toString(); Logger.log(AndroidLogger.TYPE_WARNING_NETWORK, "Attempting 1 stage redirect from " + redirectString); //only allow one level of redirection here for now. URL newUrl = new URL(httpConnection.getHeaderField("Location")); httpConnection.disconnect(); httpConnection = (HttpURLConnection)newUrl.openConnection(); setupGetConnection(httpConnection); httpConnection.connect(); // Don't allow redirects _from_ https _to_ https unless they are // redirecting to the same server. if (!HttpRequestGenerator.isValidRedirect(url, httpConnection.getURL())) { Logger.log(AndroidLogger.TYPE_WARNING_NETWORK, "Invalid redirect from " + redirectString); String errorMessage = "Invalid redirect from secure server to insecure server"; throw new IOException(errorMessage); } } return httpConnection; } private static void setupGetConnection(HttpURLConnection con) throws IOException { con.setConnectTimeout(ModernHttpRequester.CONNECTION_TIMEOUT); con.setReadTimeout(ModernHttpRequester.CONNECTION_SO_TIMEOUT); con.setRequestMethod("GET"); con.setDoInput(true); con.setInstanceFollowRedirects(true); } }