1
0
mirror of https://github.com/nerzhul/ownCloud-SMS-App.git synced 2025-06-07 16:06:18 +00:00

Rewrite our HTTP Client to remove the owncloud library dependency and doing authentication ourselves

* Fixes issue #122
* Cleanup the code
* Drop owncloud library support, this will help the unofficial F-Droid build
This commit is contained in:
Loic Blot 2016-12-20 21:34:52 +01:00
parent f2082e5215
commit 25e2d13409
7 changed files with 69 additions and 176 deletions

View File

@ -33,7 +33,7 @@ To contribute please download `res/values/strings.xml` and `res/values/google_pl
You can also contribute by adding patches in Java code or cleanups. You can also contribute by adding patches in Java code or cleanups.
## Requirements ## Requirements
- A NextCloud or ownCloud instance with ocsms app - An Nextcloud or ownCloud instance with ocsms app
## Build requirements ## Build requirements
- nrz-androidlib (last version) - nrz-androidlib (last version)

View File

@ -13,7 +13,6 @@ apply plugin: 'com.android.application'
android { android {
compileSdkVersion 25 compileSdkVersion 25
buildToolsVersion "25.0.0" buildToolsVersion "25.0.0"
useLibrary 'org.apache.http.legacy'
lintOptions { lintOptions {
abortOnError false abortOnError false
@ -45,11 +44,11 @@ repositories {
} }
dependencies { dependencies {
compile project(':owncloudAndroidLibrary') compile files('libs/commons-httpclient-3.1.jar')
compile 'com.android.support:support-v13:25.0.1' compile 'com.android.support:support-v13:25.1.0'
compile 'com.android.support:appcompat-v7:25.0.1' compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.0.1' compile 'com.android.support:design:25.1.0'
compile 'in.srain.cube:ultra-ptr:1.0.11' compile 'in.srain.cube:ultra-ptr:1.0.11'
compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4' compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
compile 'com.android.support:support-v4:25.0.1' compile 'com.android.support:support-v4:25.1.0'
} }

Binary file not shown.

View File

@ -41,14 +41,14 @@ import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import com.dd.processbutton.iml.ActionProcessButton; import com.dd.processbutton.iml.ActionProcessButton;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import org.apache.commons.httpclient.methods.GetMethod;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import java.io.IOException;
import fr.unix_experience.owncloud_sms.R; import fr.unix_experience.owncloud_sms.R;
import fr.unix_experience.owncloud_sms.authenticators.OwnCloudAuthenticator;
import fr.unix_experience.owncloud_sms.defines.DefaultPrefs; import fr.unix_experience.owncloud_sms.defines.DefaultPrefs;
import fr.unix_experience.owncloud_sms.enums.LoginReturnCode; import fr.unix_experience.owncloud_sms.engine.HTTPRequestBuilder;
/** /**
* A login screen that offers login via email/password. * A login screen that offers login via email/password.
@ -240,25 +240,19 @@ public class LoginActivity extends AppCompatActivity {
@Override @Override
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
// Create client object to perform remote operations _returnCode = 0;
OwnCloudClient ocClient = OwnCloudClientFactory.createOwnCloudClient( HTTPRequestBuilder http = new HTTPRequestBuilder(_serverURI, _login, _password);
_serverURI, getBaseContext(), GetMethod testMethod = http.getVersion();
// Activity or Service context try {
true _returnCode = http.execute(testMethod);
); } catch (IOException e) {
Log.w(TAG, "Failed to login, IOException occured: " + e.getMessage());
// Set basic credentials _returnCode = 599;
ocClient.setCredentials( }
OwnCloudCredentialsFactory.newBasicCredentials(_login, _password)
); testMethod.releaseConnection();
// Send an authentication test to ownCloud return (_returnCode == 200);
OwnCloudAuthenticator at = new OwnCloudAuthenticator(getBaseContext());
at.setClient(ocClient);
_returnCode = at.testCredentials();
return (_returnCode == LoginReturnCode.OK);
} }
@Override @Override
@ -304,26 +298,25 @@ public class LoginActivity extends AppCompatActivity {
} else { } else {
boolean serverViewRequestFocus = true; boolean serverViewRequestFocus = true;
switch (_returnCode) { switch (_returnCode) {
case INVALID_ADDR: case 0:
_serverView.setError(getString(R.string.error_invalid_server_address));
break;
case HTTP_CONN_FAILED:
_serverView.setError(getString(R.string.error_http_connection_failed));
break;
case CONN_FAILED:
_serverView.setError(getString(R.string.error_connection_failed));
break;
case CONN_FAILED_NOT_FOUND:
_serverView.setError(getString(R.string.error_connection_failed_not_found));
break;
case UNKNOWN_ERROR:
_serverView.setError("UNK"); _serverView.setError("UNK");
break; break;
case INVALID_LOGIN: case 404:
_serverView.setError(getString(R.string.error_connection_failed_not_found));
break;
case 400:
case 598:
_serverView.setError(getString(R.string.error_connection_failed));
break;
case 599:
_serverView.setError(getString(R.string.error_http_connection_failed));
break;
case 401:
case 403:
_passwordView.setError(getString(R.string.error_invalid_login)); _passwordView.setError(getString(R.string.error_invalid_login));
_passwordView.requestFocus(); _passwordView.requestFocus();
// Warning, there is no break here to disable serverViewRequestFocus too // Warning, there is no break here to disable serverViewRequestFocus too
case OK: case 200:
default: default:
serverViewRequestFocus = false; serverViewRequestFocus = false;
break; break;
@ -334,7 +327,7 @@ public class LoginActivity extends AppCompatActivity {
} }
// If not ok, reset the progress // If not ok, reset the progress
if (_returnCode != LoginReturnCode.OK) { if (_returnCode != 200) {
_signInButton.setProgress(0); _signInButton.setProgress(0);
} }
} }
@ -345,13 +338,13 @@ public class LoginActivity extends AppCompatActivity {
mAuthTask = null; mAuthTask = null;
showProgress(false); showProgress(false);
} }
private final Uri _serverURI; private final Uri _serverURI;
private final String _login; private final String _login;
private final String _password; private final String _password;
private LoginReturnCode _returnCode; private int _returnCode;
public static final String PARAM_AUTHTOKEN_TYPE = "auth.token"; static final String PARAM_AUTHTOKEN_TYPE = "auth.token";
private final String TAG = UserLoginTask.class.getCanonicalName(); private final String TAG = UserLoginTask.class.getCanonicalName();
} }
} }

View File

@ -25,19 +25,8 @@ import android.accounts.NetworkErrorException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.http.HttpStatus;
import org.json.JSONObject;
import java.io.IOException;
import fr.unix_experience.owncloud_sms.activities.LoginActivity; import fr.unix_experience.owncloud_sms.activities.LoginActivity;
import fr.unix_experience.owncloud_sms.enums.LoginReturnCode;
public class OwnCloudAuthenticator extends AbstractAccountAuthenticator { public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
// Simple constructor // Simple constructor
@ -103,95 +92,8 @@ public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
/*
* Return codes
* 1: invalid address
* 2: HTTP failed
* 3: connexion failed
* 4: invalid login
* 5: unknown error
*/
public LoginReturnCode testCredentials() {
LoginReturnCode bRet = LoginReturnCode.OK;
GetMethod get;
int status;
try {
get = new GetMethod(_client.getBaseUri() + "/index.php/ocs/cloud/user?format=json");
} catch (IllegalArgumentException e) {
return LoginReturnCode.INVALID_ADDR;
}
get.addRequestHeader("OCS-APIREQUEST", "true");
try {
status = _client.executeMethod(get);
} catch (IllegalArgumentException e) {
return LoginReturnCode.INVALID_ADDR;
} catch (HttpException e) {
return LoginReturnCode.HTTP_CONN_FAILED;
} catch (IOException e) {
return LoginReturnCode.CONN_FAILED;
}
try {
if(OwnCloudAuthenticator.isSuccess(status)) {
String response = get.getResponseBodyAsString();
Log.i(OwnCloudAuthenticator.TAG, "Successful response: " + response);
// Parse the response
JSONObject respJSON = new JSONObject(response);
JSONObject respOCS = respJSON.getJSONObject(OwnCloudAuthenticator.NODE_OCS);
JSONObject respData = respOCS.getJSONObject(OwnCloudAuthenticator.NODE_DATA);
String id = respData.getString(OwnCloudAuthenticator.NODE_ID);
String displayName = respData.getString(OwnCloudAuthenticator.NODE_DISPLAY_NAME);
String email = respData.getString(OwnCloudAuthenticator.NODE_EMAIL);
Log.i(OwnCloudAuthenticator.TAG, "*** Parsed user information: " + id + " - " + displayName + " - " + email);
} else {
String response = get.getResponseBodyAsString();
Log.e(OwnCloudAuthenticator.TAG, "Failed response while getting user information ");
if (response != null) {
Log.e(OwnCloudAuthenticator.TAG, "*** status code: " + status + " ; response message: " + response);
} else {
Log.e(OwnCloudAuthenticator.TAG, "*** status code: " + status);
}
switch (status) {
case 401: bRet = LoginReturnCode.INVALID_LOGIN; break;
case 404: bRet = LoginReturnCode.CONN_FAILED_NOT_FOUND; break;
default: bRet = LoginReturnCode.UNKNOWN_ERROR; break;
}
}
} catch (Exception e) {
Log.e(OwnCloudAuthenticator.TAG, "Exception while getting OC user information", e);
bRet = LoginReturnCode.UNKNOWN_ERROR;
} finally {
get.releaseConnection();
}
return bRet;
}
private static boolean isSuccess(int status) {
return (status == HttpStatus.SC_OK);
}
public void setClient(OwnCloudClient oc) {
_client = oc;
}
private final Context _context; private final Context _context;
private OwnCloudClient _client;
private static final String TAG = OwnCloudAuthenticator.class.getSimpleName(); private static final String TAG = OwnCloudAuthenticator.class.getSimpleName();
private static final String NODE_OCS = "ocs";
private static final String NODE_DATA = "data";
private static final String NODE_ID = "id";
private static final String NODE_DISPLAY_NAME= "display-name";
private static final String NODE_EMAIL= "email";
} }

View File

@ -17,13 +17,11 @@ package fr.unix_experience.owncloud_sms.engine;
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.util.Base64;
import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient; import org.apache.commons.httpclient.HttpClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PostMethod;
@ -31,9 +29,12 @@ import org.apache.commons.httpclient.methods.StringRequestEntity;
import java.io.IOException; import java.io.IOException;
class HTTPRequestBuilder { public class HTTPRequestBuilder {
private final OwnCloudClient _ocClient; private static final String TAG = HTTPRequestBuilder.class.getCanonicalName();
private final Uri _serverURI;
private final String _username;
private final String _password;
// API v1 calls // API v1 calls
private static final String OC_GET_VERSION = "/index.php/apps/ocsms/get/apiversion?format=json"; private static final String OC_GET_VERSION = "/index.php/apps/ocsms/get/apiversion?format=json";
@ -47,20 +48,15 @@ class HTTPRequestBuilder {
private static final String OC_V2_GET_MESSAGES_PHONE ="/index.php/apps/ocsms/api/v2/messages/[PHONENUMBER]/[START]/[LIMIT]?format=json"; private static final String OC_V2_GET_MESSAGES_PHONE ="/index.php/apps/ocsms/api/v2/messages/[PHONENUMBER]/[START]/[LIMIT]?format=json";
private static final String OC_V2_GET_MESSAGES_SENDQUEUE = "/index.php/apps/ocsms/api/v2/messages/sendqueue?format=json"; private static final String OC_V2_GET_MESSAGES_SENDQUEUE = "/index.php/apps/ocsms/api/v2/messages/sendqueue?format=json";
HTTPRequestBuilder(Context context, Uri serverURI, String accountName, String accountPassword) { public HTTPRequestBuilder(Uri serverURI, String accountName, String accountPassword) {
_ocClient = OwnCloudClientFactory.createOwnCloudClient( _serverURI = serverURI;
serverURI, context, true); _username = accountName;
_password = accountPassword;
// Set basic credentials
_ocClient.setCredentials(
OwnCloudCredentialsFactory.newBasicCredentials(accountName, accountPassword)
);
} }
private GetMethod get(String oc_call) { private GetMethod get(String oc_call) {
GetMethod get = new GetMethod(_ocClient.getBaseUri() + oc_call); Log.i(HTTPRequestBuilder.TAG, "Create GET " + _serverURI + oc_call);
get.addRequestHeader("OCS-APIREQUEST", "true"); return new GetMethod(_serverURI.toString() + oc_call);
return get;
} }
GetMethod getAllSmsIds() { GetMethod getAllSmsIds() {
@ -72,8 +68,7 @@ class HTTPRequestBuilder {
} }
PostMethod pushSms(StringRequestEntity ent) { PostMethod pushSms(StringRequestEntity ent) {
PostMethod post = new PostMethod(_ocClient.getBaseUri() + HTTPRequestBuilder.OC_PUSH_ROUTE); PostMethod post = new PostMethod(_serverURI.toString() + HTTPRequestBuilder.OC_PUSH_ROUTE);
post.addRequestHeader("OCS-APIREQUEST", "true");
post.setRequestEntity(ent); post.setRequestEntity(ent);
return post; return post;
} }
@ -87,7 +82,13 @@ class HTTPRequestBuilder {
replace("[START]", start.toString()).replace("[LIMIT]", limit.toString())); replace("[START]", start.toString()).replace("[LIMIT]", limit.toString()));
} }
int execute(HttpMethod req) throws IOException { public int execute(HttpMethod req) throws IOException {
return _ocClient.executeMethod(req); HttpClient http = new HttpClient();
String basicAuth = "Basic " +
Base64.encodeToString((_username + ":" + _password).getBytes(), Base64.NO_WRAP);
//req.setFollowRedirects(true); // App is SIGKILLED by android when doing this... WTF
req.setDoAuthentication(true);
req.addRequestHeader("Authorization", basicAuth);
return http.executeMethod(req);
} }
} }

View File

@ -27,7 +27,6 @@ import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.HttpStatus;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -57,8 +56,7 @@ public class OCSMSOwnCloudClient {
} }
Uri serverURI = Uri.parse(ocURI); Uri serverURI = Uri.parse(ocURI);
_http = new HTTPRequestBuilder(context, serverURI, _http = new HTTPRequestBuilder(serverURI, accountManager.getUserData(account, "ocLogin"),
accountManager.getUserData(account, "ocLogin"),
accountManager.getPassword(account)); accountManager.getPassword(account));
_connectivityMonitor = new ConnectivityMonitor(_context); _connectivityMonitor = new ConnectivityMonitor(_context);
} }
@ -321,7 +319,7 @@ public class OCSMSOwnCloudClient {
} }
} }
if (status == HttpStatus.SC_OK) { if (status == 200) {
String response; String response;
try { try {
response = req.getResponseBodyAsString(); response = req.getResponseBodyAsString();
@ -346,7 +344,7 @@ public class OCSMSOwnCloudClient {
} }
} }
} }
} else if (status == HttpStatus.SC_FORBIDDEN) { } else if (status == 403) {
// Authentication failed // Authentication failed
throw new OCSyncException(R.string.err_sync_auth_failed, OCSyncErrorType.AUTH); throw new OCSyncException(R.string.err_sync_auth_failed, OCSyncErrorType.AUTH);
} else { } else {