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 * 'sign out' feature for basic-auth
DONE persistent cookie storage * persistent cookie storage
DONE use expiration cookie info DONE use expiration cookie info
* select best match cookie if several with the same name matches * select best match cookie if several with the same name matches
* common auth dialog for basic auth & litres * common auth dialog for basic auth & litres
* unencrypted protocol warning
DONE show 'empty basket' message without opening of catalog DONE show 'empty basket' message without opening of catalog
* update basket view if basket content is changed * update basket view if basket content is changed

View file

@ -10,4 +10,4 @@
# Project target. # Project target.
target=android-8 target=android-8
java.encoding=utf-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); findTextView(R.id.authentication_subtitle).setVisibility(View.GONE);
} }
final TextView warningView = findTextView(R.id.authentication_unencrypted_warning); 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); warningView.setVisibility(View.GONE);
} else { //} else {
warningView.setText(myResource.getResource("unencryptedWarning").getValue()); // warningView.setText(myResource.getResource("unencryptedWarning").getValue());
} //}
findTextView(R.id.authentication_username_label).setText( findTextView(R.id.authentication_username_label).setText(
myResource.getResource("login").getValue() myResource.getResource("login").getValue()
); );

View file

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

View file

@ -24,8 +24,14 @@ import java.util.zip.GZIPInputStream;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import javax.net.ssl.*; 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.util.ZLNetworkUtil;
import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile; import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
@ -41,68 +47,32 @@ public class ZLNetworkManager {
return ourManager; return ourManager;
} }
private static TrustManager[] getTrustManagers(String certificate) throws ZLNetworkException { private CredentialsProvider myCredentialsProvider = new BasicCredentialsProvider();
InputStream stream = null;
if (certificate != null) { private void setCommonHTTPOptions(HttpMessage request) throws ZLNetworkException {
try { //httpConnection.setInstanceFollowRedirects(true);
final ZLResourceFile file = ZLResourceFile.createResourceFile(certificate); //httpConnection.setConnectTimeout(15000); // FIXME: hardcoded timeout value!!!
stream = file.getInputStream(); //httpConnection.setReadTimeout(30000); // FIXME: hardcoded timeout value!!!
} catch (IOException ex) { request.setHeader("User-Agent", ZLNetworkUtil.getUserAgent());
throw new ZLNetworkException(ZLNetworkException.ERROR_SSL_BAD_FILE, certificate, ex); request.setHeader("Accept-Language", Locale.getDefault().getLanguage());
} //httpConnection.setAllowUserInteraction(true);
}
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 void setCommonHTTPOptions(ZLNetworkRequest request, HttpURLConnection httpConnection) throws ZLNetworkException { public void setCredentialsProvider(CredentialsProvider provider) {
httpConnection.setInstanceFollowRedirects(true); myCredentialsProvider = provider;
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 perform(ZLNetworkRequest request) throws ZLNetworkException { public void perform(ZLNetworkRequest request) throws ZLNetworkException {
boolean success = false; boolean success = false;
DefaultHttpClient httpClient = null;
HttpEntity entity = null;
try { try {
request.doBefore(); request.doBefore();
HttpURLConnection httpConnection = null; httpClient = new DefaultHttpClient();
int response = -1; httpClient.setCredentialsProvider(myCredentialsProvider);
final int retryLimit = 6; final HttpGet getRequest = new HttpGet(request.URL);
for (int retryCounter = 0; retryCounter < retryLimit && (response == -1 || response == 301 || response == 302); ++retryCounter) { setCommonHTTPOptions(getRequest);
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);
if (request.PostData != null) { if (request.PostData != null) {
httpConnection.setRequestMethod("POST"); httpConnection.setRequestMethod("POST");
httpConnection.setRequestProperty( httpConnection.setRequestProperty(
@ -124,41 +94,38 @@ public class ZLNetworkManager {
} finally { } finally {
writer.close(); 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; InputStream stream = null;
if (response == HttpURLConnection.HTTP_OK) { if (entity != null && responseCode == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream(); stream = entity.getContent();
} else if (500 <= response && response < 600) {
stream = httpConnection.getErrorStream();
} }
System.err.println(request.URL);
System.err.println("RESPONSE: " + response.getStatusLine());
if (stream != null) { if (stream != null) {
try { try {
if ("gzip".equalsIgnoreCase(httpConnection.getContentEncoding())) { final Header encoding = entity.getContentEncoding();
if (encoding != null && "gzip".equalsIgnoreCase(encoding.getValue())) {
stream = new GZIPInputStream(stream); stream = new GZIPInputStream(stream);
} }
request.handleStream(stream, httpConnection.getContentLength()); request.handleStream(stream, (int)entity.getContentLength());
} finally { } finally {
stream.close(); stream.close();
} }
success = true; success = true;
} else { } else {
System.err.println(request.URL); if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
System.err.println("RESPONSE: " + response);
if (response == HttpURLConnection.HTTP_UNAUTHORIZED) {
throw new ZLNetworkException(ZLNetworkException.ERROR_AUTHENTICATION_FAILED); throw new ZLNetworkException(ZLNetworkException.ERROR_AUTHENTICATION_FAILED);
} else if (response >= 400) {
throw new ZLNetworkException(true, httpConnection.getResponseMessage());
} else { } else {
throw new ZLNetworkException(ZLNetworkException.ERROR_SOMETHING_WRONG, ZLNetworkUtil.hostFromUrl(request.URL)); throw new ZLNetworkException(true, response.getStatusLine().toString());
} }
} }
} catch (SSLHandshakeException ex) { } catch (SSLHandshakeException ex) {
@ -177,8 +144,6 @@ public class ZLNetworkManager {
throw new ZLNetworkException(ZLNetworkException.ERROR_HOST_CANNOT_BE_REACHED, ZLNetworkUtil.hostFromUrl(request.URL), ex); throw new ZLNetworkException(ZLNetworkException.ERROR_HOST_CANNOT_BE_REACHED, ZLNetworkUtil.hostFromUrl(request.URL), ex);
} catch (UnknownHostException ex) { } catch (UnknownHostException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_RESOLVE_HOST, ZLNetworkUtil.hostFromUrl(request.URL), 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) { } catch (SocketTimeoutException ex) {
throw new ZLNetworkException(ZLNetworkException.ERROR_TIMEOUT, ex); throw new ZLNetworkException(ZLNetworkException.ERROR_TIMEOUT, ex);
} catch (IOException ex) { } catch (IOException ex) {
@ -186,6 +151,15 @@ public class ZLNetworkManager {
throw new ZLNetworkException(ZLNetworkException.ERROR_SOMETHING_WRONG, ZLNetworkUtil.hostFromUrl(request.URL), ex); throw new ZLNetworkException(ZLNetworkException.ERROR_SOMETHING_WRONG, ZLNetworkUtil.hostFromUrl(request.URL), ex);
} finally { } finally {
request.doAfter(success); 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);
}
}
}