1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 19:42:17 +02:00

HttpConnection => HttpClient

This commit is contained in:
Nikolay Pultsin 2011-04-23 10:49:30 +01:00
parent 88b4f080c4
commit 5f8e454140
7 changed files with 101 additions and 208 deletions

View file

@ -1,8 +1,9 @@
* 'sign out' feature for basic-auth
DONE persistent cookie storage
* persistent cookie storage
DONE use expiration cookie info
* select best match cookie if several with the same name matches
* common auth dialog for basic auth & litres
* unencrypted protocol warning
DONE show 'empty basket' message without opening of catalog
* update basket view if basket content is changed

View file

@ -10,4 +10,4 @@
# Project target.
target=android-8
java.encoding=utf-8
proguard.config=proguard.cfg
#proguard.config=proguard.cfg

View file

@ -64,11 +64,11 @@ public class AuthenticationActivity extends Activity {
findTextView(R.id.authentication_subtitle).setVisibility(View.GONE);
}
final TextView warningView = findTextView(R.id.authentication_unencrypted_warning);
if ("https".equalsIgnoreCase(intent.getStringExtra(SCHEME_KEY))) {
//if ("https".equalsIgnoreCase(intent.getStringExtra(SCHEME_KEY))) {
warningView.setVisibility(View.GONE);
} else {
warningView.setText(myResource.getResource("unencryptedWarning").getValue());
}
//} else {
// warningView.setText(myResource.getResource("unencryptedWarning").getValue());
//}
findTextView(R.id.authentication_username_label).setText(
myResource.getResource("login").getValue()
);

View file

@ -21,6 +21,11 @@ package org.geometerplus.android.fbreader.network;
import java.net.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import android.app.*;
import android.os.Bundle;
import android.view.*;
@ -35,6 +40,7 @@ import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.image.ZLImage;
import org.geometerplus.zlibrary.core.image.ZLLoadableImage;
import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageManager;
import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageData;
@ -79,40 +85,45 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
NetworkView.Instance().addEventListener(this);
}
private final class MyAuthenticator extends Authenticator {
private class MyCredentialsProvider extends BasicCredentialsProvider {
private volatile String myUsername;
private volatile String myPassword;
@Override
protected PasswordAuthentication getPasswordAuthentication() {
public Credentials getCredentials(AuthScope scope) {
Credentials creds = super.getCredentials(scope);
if (creds == null) {
new Exception().printStackTrace();
final Intent intent = new Intent();
final String host = getRequestingSite().getHostName();
final String area = getRequestingPrompt();
final String host = scope.getHost();
final String area = scope.getRealm();
final ZLStringOption option = new ZLStringOption("username", host + ":" + area, "");
intent.setClass(NetworkBaseActivity.this, AuthenticationActivity.class);
intent.putExtra(AuthenticationActivity.HOST_KEY, host);
intent.putExtra(AuthenticationActivity.AREA_KEY, area);
intent.putExtra(AuthenticationActivity.SCHEME_KEY, getRequestingProtocol());
intent.putExtra(AuthenticationActivity.SCHEME_KEY, scope.getScheme());
intent.putExtra(AuthenticationActivity.USERNAME_KEY, option.getValue());
startActivityForResult(intent, AUTHENTICATION_CODE);
synchronized (this) {
try {
System.err.println("waiting in " + Thread.currentThread());
wait();
} catch (InterruptedException e) {
}
}
PasswordAuthentication result = null;
System.err.println("OK");
if (myUsername != null && myPassword != null) {
option.setValue(myUsername);
result = new PasswordAuthentication(myUsername, myPassword.toCharArray());
creds = new UsernamePasswordCredentials(myUsername, myPassword);
}
myUsername = null;
myPassword = null;
return result;
}
return creds;
}
}
private final MyAuthenticator myAuthenticator = new MyAuthenticator();
private final MyCredentialsProvider myCredentialsProvider = new MyCredentialsProvider();
@Override
public void onResume() {
@ -120,7 +131,7 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
getListView().setOnCreateContextMenuListener(this);
onModelChanged(); // do the same update actions as upon onModelChanged
Authenticator.setDefault(myAuthenticator);
ZLNetworkManager.Instance().setCredentialsProvider(myCredentialsProvider);
}
@Override
@ -140,13 +151,15 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
System.err.println("onActivityResult " + requestCode + " " + resultCode);
if (requestCode == AUTHENTICATION_CODE) {
synchronized (myAuthenticator) {
synchronized (myCredentialsProvider) {
if (data != null) {
myAuthenticator.myUsername = data.getStringExtra(AuthenticationActivity.USERNAME_KEY);
myAuthenticator.myPassword = data.getStringExtra(AuthenticationActivity.PASSWORD_KEY);
myCredentialsProvider.myUsername = data.getStringExtra(AuthenticationActivity.USERNAME_KEY);
myCredentialsProvider.myPassword = data.getStringExtra(AuthenticationActivity.PASSWORD_KEY);
}
myAuthenticator.notify();
myCredentialsProvider.notify();
System.err.println("notify");
}
}
}

View file

@ -91,6 +91,7 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
System.err.println("onActivityResult " + requestCode + " " + resultCode);
switch (requestCode) {
default:
super.onActivityResult(requestCode, resultCode, data);

View file

@ -24,8 +24,14 @@ import java.util.zip.GZIPInputStream;
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import java.security.cert.*;
import java.security.GeneralSecurityException;
import org.apache.http.*;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
@ -41,68 +47,32 @@ public class ZLNetworkManager {
return ourManager;
}
private static TrustManager[] getTrustManagers(String certificate) throws ZLNetworkException {
InputStream stream = null;
if (certificate != null) {
try {
final ZLResourceFile file = ZLResourceFile.createResourceFile(certificate);
stream = file.getInputStream();
} catch (IOException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_SSL_BAD_FILE, certificate, ex);
}
}
try {
return new TrustManager[] { new ZLX509TrustManager(stream) };
} catch (CertificateExpiredException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_SSL_EXPIRED, certificate, ex);
} catch (CertificateNotYetValidException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_SSL_NOT_YET_VALID, certificate, ex);
} catch (CertificateException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_SSL_BAD_FILE, certificate, ex);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
}
}
}
private CredentialsProvider myCredentialsProvider = new BasicCredentialsProvider();
private void setCommonHTTPOptions(HttpMessage request) throws ZLNetworkException {
//httpConnection.setInstanceFollowRedirects(true);
//httpConnection.setConnectTimeout(15000); // FIXME: hardcoded timeout value!!!
//httpConnection.setReadTimeout(30000); // FIXME: hardcoded timeout value!!!
request.setHeader("User-Agent", ZLNetworkUtil.getUserAgent());
request.setHeader("Accept-Language", Locale.getDefault().getLanguage());
//httpConnection.setAllowUserInteraction(true);
}
private void setCommonHTTPOptions(ZLNetworkRequest request, HttpURLConnection httpConnection) throws ZLNetworkException {
httpConnection.setInstanceFollowRedirects(true);
httpConnection.setConnectTimeout(15000); // FIXME: hardcoded timeout value!!!
httpConnection.setReadTimeout(30000); // FIXME: hardcoded timeout value!!!
//httpConnection.setRequestProperty("Connection", "Close");
httpConnection.setRequestProperty("User-Agent", ZLNetworkUtil.getUserAgent());
httpConnection.setRequestProperty("Accept-Language", Locale.getDefault().getLanguage());
httpConnection.setAllowUserInteraction(true);
if (httpConnection instanceof HttpsURLConnection) {
final HttpsURLConnection httpsConnection = (HttpsURLConnection)httpConnection;
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, getTrustManagers(request.SSLCertificate), null);
httpsConnection.setSSLSocketFactory(context.getSocketFactory());
} catch (GeneralSecurityException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_SSL_SUBSYSTEM, ex);
}
}
public void setCredentialsProvider(CredentialsProvider provider) {
myCredentialsProvider = provider;
}
public void perform(ZLNetworkRequest request) throws ZLNetworkException {
boolean success = false;
DefaultHttpClient httpClient = null;
HttpEntity entity = null;
try {
request.doBefore();
HttpURLConnection httpConnection = null;
int response = -1;
final int retryLimit = 6;
for (int retryCounter = 0; retryCounter < retryLimit && (response == -1 || response == 301 || response == 302); ++retryCounter) {
final URLConnection connection = new URL(request.URL).openConnection();
if (!(connection instanceof HttpURLConnection)) {
throw new ZLNetworkException(ZLNetworkException.ERROR_UNSUPPORTED_PROTOCOL);
}
httpConnection = (HttpURLConnection)connection;
setCommonHTTPOptions(request, httpConnection);
httpClient = new DefaultHttpClient();
httpClient.setCredentialsProvider(myCredentialsProvider);
final HttpGet getRequest = new HttpGet(request.URL);
setCommonHTTPOptions(getRequest);
/*
if (request.PostData != null) {
httpConnection.setRequestMethod("POST");
httpConnection.setRequestProperty(
@ -124,41 +94,38 @@ public class ZLNetworkManager {
} finally {
writer.close();
}
} else {
httpConnection.connect();
}
response = httpConnection.getResponseCode();
if (response == 301 || response == 302) {
request.URL = httpConnection.getHeaderField("Location");
}
*/
HttpResponse response = null;
for (int retryCounter = 0; retryCounter < 3 && entity == null; ++retryCounter) {
response = httpClient.execute(getRequest);
entity = response.getEntity();
}
final int responseCode = response.getStatusLine().getStatusCode();
InputStream stream = null;
if (response == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
} else if (500 <= response && response < 600) {
stream = httpConnection.getErrorStream();
if (entity != null && responseCode == HttpURLConnection.HTTP_OK) {
stream = entity.getContent();
}
System.err.println(request.URL);
System.err.println("RESPONSE: " + response.getStatusLine());
if (stream != null) {
try {
if ("gzip".equalsIgnoreCase(httpConnection.getContentEncoding())) {
final Header encoding = entity.getContentEncoding();
if (encoding != null && "gzip".equalsIgnoreCase(encoding.getValue())) {
stream = new GZIPInputStream(stream);
}
request.handleStream(stream, httpConnection.getContentLength());
request.handleStream(stream, (int)entity.getContentLength());
} finally {
stream.close();
}
success = true;
} else {
System.err.println(request.URL);
System.err.println("RESPONSE: " + response);
if (response == HttpURLConnection.HTTP_UNAUTHORIZED) {
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
throw new ZLNetworkException(ZLNetworkException.ERROR_AUTHENTICATION_FAILED);
} else if (response >= 400) {
throw new ZLNetworkException(true, httpConnection.getResponseMessage());
} else {
throw new ZLNetworkException(ZLNetworkException.ERROR_SOMETHING_WRONG, ZLNetworkUtil.hostFromUrl(request.URL));
throw new ZLNetworkException(true, response.getStatusLine().toString());
}
}
} catch (SSLHandshakeException ex) {
@ -177,8 +144,6 @@ public class ZLNetworkManager {
throw new ZLNetworkException(ZLNetworkException.ERROR_HOST_CANNOT_BE_REACHED, ZLNetworkUtil.hostFromUrl(request.URL), ex);
} catch (UnknownHostException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_RESOLVE_HOST, ZLNetworkUtil.hostFromUrl(request.URL), ex);
} catch (MalformedURLException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_INVALID_URL, ex);
} catch (SocketTimeoutException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_TIMEOUT, ex);
} catch (IOException ex) {
@ -186,6 +151,15 @@ public class ZLNetworkManager {
throw new ZLNetworkException(ZLNetworkException.ERROR_SOMETHING_WRONG, ZLNetworkUtil.hostFromUrl(request.URL), ex);
} finally {
request.doAfter(success);
if (httpClient != null) {
httpClient.getConnectionManager().shutdown();
}
if (entity != null) {
try {
entity.consumeContent();
} catch (IOException e) {
}
}
}
}

View file

@ -1,96 +0,0 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.zlibrary.core.network;
import java.io.*;
import javax.net.ssl.*;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
class ZLX509TrustManager implements X509TrustManager {
private final X509Certificate myCertificate;
private X509TrustManager myBase;
public ZLX509TrustManager(InputStream stream) throws CertificateException {
if (stream != null) {
final CertificateFactory factory = CertificateFactory.getInstance("X509");
Certificate cert = factory.generateCertificate(stream);
if (!(cert instanceof X509Certificate)) {
throw new CertificateException("That's impossible!!! Certificate with invalid type has been returned by X.509 certificate factory.");
}
myCertificate = (X509Certificate)cert;
myCertificate.checkValidity();
} else {
myCertificate = null;
}
myBase = null;
try {
final TrustManagerFactory factory = TrustManagerFactory.getInstance("X509");
factory.init((KeyStore)null);
final TrustManager[] managers = factory.getTrustManagers();
if (managers != null && managers.length > 0) {
myBase = (X509TrustManager)managers[0];
}
} catch (NoSuchAlgorithmException e) {
} catch (KeyStoreException e) {
}
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
if (myCertificate != null) {
final int lastCertificate = certs.length - 1;
for (int i = 0; i < lastCertificate; ++i) {
checkCertificate(certs[i], certs[i + 1].getPublicKey());
}
checkCertificate(certs[lastCertificate], myCertificate.getPublicKey());
} else {
throw new CertificateException("No certificate found");
}
} catch (CertificateException e) {
if (myBase != null) {
myBase.checkServerTrusted(certs, authType);
} else {
throw e;
}
}
}
private void checkCertificate(X509Certificate certificate, PublicKey publicKey) throws CertificateException {
certificate.checkValidity();
try {
certificate.verify(publicKey);
} catch (GeneralSecurityException e) {
throw new CertificateException(e);
}
}
}