Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #17 from jstemmer/12ea20ddbe511d11aa1ff3e03fb21700…

…f1451782

Close the http connection after each request and manually add the auth header
  • Loading branch information...
commit 171186de38645d5cfc9bd96ad1f2d24a85519531 2 parents ef31ece + 12ea20d
@freezy freezy authored
View
6 src/org/xbmc/android/remote/presentation/controller/AbstractController.java
@@ -234,7 +234,7 @@ public void onClick(DialogInterface dialog, int which) {
}
});
} catch (IOException e) {
- if (e.getMessage().startsWith("Network unreachable")) {
+ if (e.getMessage() != null && e.getMessage().startsWith("Network unreachable")) {
builder.setTitle("No network");
builder.setMessage("XBMC Remote needs local network access. Please make sure that your wireless network is activated. You can click on the Settings button below to directly access your network settings.");
builder.setNeutralButton("Settings", new OnClickListener() {
@@ -245,7 +245,9 @@ public void onClick(DialogInterface dialog, int which) {
});
} else {
builder.setTitle("I/O Exception (" + e.getClass().getCanonicalName() + ")");
- builder.setMessage(e.getMessage().toString());
+ if (e.getMessage() != null) {
+ builder.setMessage(e.getMessage().toString());
+ }
Log.e(TAG, e.getStackTrace().toString());
}
} catch (HttpException e) {
View
191 src/org/xbmc/httpapi/Connection.java
@@ -21,36 +21,32 @@
package org.xbmc.httpapi;
-import java.io.ByteArrayOutputStream;
+import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.net.Authenticator;
+import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
-import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
+import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.http.HttpException;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.StatusLine;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
import org.xbmc.android.util.ClientFactory;
import org.xbmc.api.business.INotifiableManager;
import org.xbmc.api.object.Host;
+import android.util.Base64;
import android.util.Log;
/**
* Singleton class. Will be instantiated only once
- *
+ *
* @author Team XBMC
*/
public class Connection {
@@ -60,33 +56,28 @@
private static final String XBMC_MICROHTTPD_THUMB_BOOTSTRAP = "/thumb/";
private static final String XBMC_MICROHTTPD_VFS_BOOTSTRAP = "/vfs/";
private static final int SOCKET_CONNECTION_TIMEOUT = 5000;
-
+
/**
* Singleton class instance
*/
private static Connection sConnection;
-
+
/**
* Complete URL without any attached command parameters, for instance:
* <code>http://192.168.0.10:8080</code>
*/
private String mUrlSuffix;
-
+
/**
* Socket read timeout (connection timeout is default)
*/
private int mSocketReadTimeout = 0;
-
+
/**
- * Performs HTTP Authentication
+ * Holds the base64 encoded user/pass for http authentication
*/
- private HttpAuthenticator mAuthenticator = null;
-
- String mHost;
- int mPort;
- String mUser;
- String mPass;
-
+ private String authEncoded = null;
+
/**
* Use getInstance() for public class instantiation
* @param host XBMC host
@@ -95,9 +86,9 @@
private Connection(String host, int port) {
setHost(host, port);
}
-
+
/**
- * Returns the singleton instance of this connection. Note that host and
+ * Returns the singleton instance of this connection. Note that host and
* port settings are only looked at the first time. Use {@link setHost()}
* if you want to update these parameters.
* @param host XBMC host
@@ -126,16 +117,13 @@ public void setHost(Host host) {
setAuth(host.user, host.pass);
}
}
-
+
/**
* Updates host and port parameters of the connection instance.
* @param host Host or IP address of the host
* @param port Port the HTTP API is listening to
*/
public void setHost(String host, int port) {
- mHost = host;
- mPort = port;
-
if (host == null || port <= 0) {
mUrlSuffix = null;
} else {
@@ -147,25 +135,21 @@ public void setHost(String host, int port) {
mUrlSuffix = sb.toString();
}
}
-
+
/**
* Sets authentication info
* @param user HTTP API username
* @param pass HTTP API password
*/
public void setAuth(String user, String pass) {
- if (pass != null && pass.length() > 0) {
- mAuthenticator = new HttpAuthenticator(user, pass);
- Authenticator.setDefault(mAuthenticator);
+ if (user != null && pass != null) {
+ String auth = user + ":" + pass;
+ authEncoded = Base64.encodeToString(auth.getBytes(), Base64.DEFAULT);
} else {
- mAuthenticator = null;
- Authenticator.setDefault(null);
+ authEncoded = null;
}
-
- mUser = user;
- mPass = pass;
}
-
+
/**
* Sets socket read timeout (connection timeout has constant value)
* @param timeout Read timeout in milliseconds.
@@ -175,7 +159,7 @@ public void setTimeout(int timeout) {
mSocketReadTimeout = timeout;
}
}
-
+
/**
* Returns the full URL of an HTTP API request
* @param command Name of the command to execute
@@ -207,13 +191,8 @@ public InputStream getThumbInputStream(String command, String parameters, INotif
if (mUrlSuffix == null) {
throw new NoSettingsException();
}
- if (mAuthenticator != null) {
- mAuthenticator.resetCounter();
- }
URL url = new URL(getUrl(command, parameters));
- uc = url.openConnection();
- uc.setConnectTimeout(SOCKET_CONNECTION_TIMEOUT);
- uc.setReadTimeout(mSocketReadTimeout);
+ uc = getUrlConnection(url);
Log.i(TAG, "Preparing input stream from " + url);
return uc.getInputStream();
} catch (MalformedURLException e) {
@@ -239,9 +218,6 @@ public InputStream getThumbInputStreamForMicroHTTPd(String thumb, INotifiableMan
if (mUrlSuffix == null) {
throw new NoSettingsException();
}
- if (mAuthenticator != null) {
- mAuthenticator.resetCounter();
- }
final URL url;
if (ClientFactory.XBMC_REV > 0 && ClientFactory.XBMC_REV >= ClientFactory.THUMB_TO_VFS_REV) {
url = new URL(mUrlSuffix + XBMC_MICROHTTPD_VFS_BOOTSTRAP + URLEncoder.encode(thumb));
@@ -249,9 +225,7 @@ public InputStream getThumbInputStreamForMicroHTTPd(String thumb, INotifiableMan
url = new URL(mUrlSuffix + XBMC_MICROHTTPD_THUMB_BOOTSTRAP + thumb + ".jpg");
}
Log.i(TAG, "Preparing input stream from " + url + " for microhttpd..");
- uc = url.openConnection();
- uc.setConnectTimeout(SOCKET_CONNECTION_TIMEOUT);
- uc.setReadTimeout(mSocketReadTimeout);
+ uc = getUrlConnection(url);
return uc.getInputStream();
} catch (FileNotFoundException e) {
throw e;
@@ -264,7 +238,7 @@ public InputStream getThumbInputStreamForMicroHTTPd(String thumb, INotifiableMan
}
return null;
}
-
+
/**
* Executes a query.
* @param command Name of the command to execute
@@ -273,43 +247,38 @@ public InputStream getThumbInputStreamForMicroHTTPd(String thumb, INotifiableMan
* @return HTTP response string.
*/
public String query(String command, String parameters, INotifiableManager manager) {
- int responseCode = -1;
-
- try {
- String responseString = "";
+ URLConnection uc = null;
+ try {
if (mUrlSuffix == null) {
throw new NoSettingsException();
}
- if (mAuthenticator != null) {
- mAuthenticator.resetCounter();
- }
- final String url = getUrl(command, parameters);
- Log.i(TAG, url);
- final DefaultHttpClient httpclient = new DefaultHttpClient();
-
- //httpclient.getCredentialsProvider().setCredentials(new AuthScope(mHost, mPort), new UsernamePasswordCredentials(mUser, mPass));
- final HttpResponse response = httpclient.execute(new HttpGet(url));
- final StatusLine statusLine = response.getStatusLine();
- responseCode = statusLine.getStatusCode();
- if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- response.getEntity().writeTo(out);
- out.close();
- responseString = out.toString();
- } else {
- response.getEntity().getContent().close();
- throw new IOException(statusLine.getReasonPhrase());
+ URL url = new URL(getUrl(command, parameters));
+ uc = getUrlConnection(url);
+
+ final String debugUrl = URLDecoder.decode(url.toString());
+ Log.i(TAG, debugUrl);
+
+ final BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()), 8192);
+ final StringBuilder response = new StringBuilder();
+ String line;
+
+ while((line = in.readLine()) != null) {
+ response.append(line);
}
-
- Log.d(TAG, "Returning: " + responseString);
- return responseString.toString().replace("<html>", "").replace("</html>", "");
-
+ in.close();
+ return response.toString().replace("<html>", "").replace("</html>", "");
} catch (MalformedURLException e) {
manager.onError(e);
} catch (IOException e) {
- if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
+ int responseCode = -1;
+ try {
+ if (uc != null) {
+ responseCode = ((HttpURLConnection)uc).getResponseCode();
+ }
+ } catch (IOException e1) { } // do nothing, getResponse code failed so treat as default i/o exception.
+ if (uc != null && responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
manager.onError(new HttpException(Integer.toString(HttpURLConnection.HTTP_UNAUTHORIZED)));
} else {
manager.onError(e);
@@ -319,7 +288,7 @@ public String query(String command, String parameters, INotifiableManager manage
}
return "";
}
-
+
/**
* Executes an HTTP API method and returns the result as string.
* @param method Name of the method to run
@@ -329,7 +298,7 @@ public String query(String command, String parameters, INotifiableManager manage
public String getString(INotifiableManager manager, String method, String parameters) {
return query(method, parameters, manager).replaceAll(LINE_SEP, "").trim();
}
-
+
/**
* Executes an HTTP API method and returns the result as string.
* @param method Name of the method to run
@@ -338,7 +307,7 @@ public String getString(INotifiableManager manager, String method, String parame
public String getString(INotifiableManager manager, String method) {
return getString(manager, method, "");
}
-
+
/**
* Executes an HTTP API method and returns the result as integer.
* @param method Name of the method to run
@@ -461,7 +430,27 @@ public boolean getBoolean(INotifiableManager manager, String method) {
public HashMap<String, String> getPairs(INotifiableManager manager, String method) {
return getPairs(manager, method, "");
}
-
+
+ /**
+ * Create a new URLConnection with the request headers set, including authentication.
+ *
+ * @param url The request url
+ * @return URLConnection
+ * @throws IOException
+ */
+ private URLConnection getUrlConnection(URL url) throws IOException {
+ final URLConnection uc = url.openConnection();
+ uc.setConnectTimeout(SOCKET_CONNECTION_TIMEOUT);
+ uc.setReadTimeout(mSocketReadTimeout);
+ uc.setRequestProperty("Connection", "close");
+
+ if (authEncoded != null) {
+ uc.setRequestProperty("Authorization", "Basic " + authEncoded);
+ }
+
+ return uc;
+ }
+
/**
* Removes the trailing "</field>" string from the value
* @param value
@@ -527,43 +516,7 @@ public static boolean trimBoolean(String value) {
}
return false;
}
-
- /**
- * HTTP Authenticator.
- *
- * @author Team XBMC
- */
- public class HttpAuthenticator extends Authenticator {
- public static final int MAX_RETRY = 5;
-
- private final String mUser;
- private final char[] mPass;
- private int mRetryCount = 0;
-
- public HttpAuthenticator(String user, String pass) {
- mUser = user;
- mPass = pass != null ? pass.toCharArray() : new char[0];
- }
- /**
- * This method is called when a password-protected URL is accessed
- */
- protected PasswordAuthentication getPasswordAuthentication() {
- if (mRetryCount < MAX_RETRY) {
- mRetryCount++;
- return new PasswordAuthentication(mUser, mPass);
- }
- return null;
- }
-
- /**
- * This method has to be called after each successful connection!!!
- */
- public void resetCounter() {
- mRetryCount = 0;
- }
- }
-
public static final String LINE_SEP = "<li>";
public static final String VALUE_SEP = ";";
public static final String PAIR_SEP = ":";
Please sign in to comment.
Something went wrong with that request. Please try again.