mirror of
https://github.com/nerzhul/ownCloud-SMS-App.git
synced 2025-06-07 07:56:14 +00:00
SMS restore now used GoLang HTTP client. (#180)
This permits to remove the whole android HTTP client from source
This commit is contained in:
parent
8ad3b251b0
commit
61ed3d2791
@ -22,7 +22,7 @@ android {
|
||||
defaultConfig {
|
||||
applicationId "fr.unix_experience.owncloud_sms"
|
||||
versionCode 64
|
||||
versionName "2.0.0"
|
||||
versionName "2.0.1"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
maxSdkVersion 27
|
||||
|
@ -1,2 +1,2 @@
|
||||
configurations.maybeCreate("default")
|
||||
artifacts.add("default", file('ncsmsgo.aar'))
|
||||
artifacts.add("default", file('ncsmsgo.aar'))
|
||||
|
Binary file not shown.
@ -7,14 +7,11 @@ import android.os.AsyncTask;
|
||||
import android.provider.Telephony;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import fr.unix_experience.owncloud_sms.activities.remote_account.RestoreMessagesActivity;
|
||||
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||
import fr.unix_experience.owncloud_sms.providers.SmsDataProvider;
|
||||
import ncsmsgo.SmsMessage;
|
||||
import ncsmsgo.SmsMessagesResponse;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||
@ -60,81 +57,68 @@ public interface ASyncSMSRecovery {
|
||||
|
||||
OCSMSOwnCloudClient client = new OCSMSOwnCloudClient(_context, _account);
|
||||
SmsDataProvider smsDataProvider = new SmsDataProvider(_context);
|
||||
JSONObject obj = client.retrieveSomeMessages(start, 500);
|
||||
SmsMessagesResponse obj = client.retrieveSomeMessages(start, 500);
|
||||
if (obj == null) {
|
||||
Log.i(ASyncSMSRecovery.TAG, "Retrieved returns failure");
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer nb = 0;
|
||||
try {
|
||||
while ((obj != null) && (obj.getLong("last_id") != start)) {
|
||||
JSONObject messages = obj.getJSONObject("messages");
|
||||
Iterator<?> keys = messages.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = (String)keys.next();
|
||||
if (messages.get(key) instanceof JSONObject) {
|
||||
JSONObject msg = messages.getJSONObject(key);
|
||||
|
||||
int mbid = msg.getInt("mailbox");
|
||||
// Ignore invalid mailbox
|
||||
if (mbid > MailboxID.ALL.getId()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Invalid mailbox found: " + msg.getString("mailbox"));
|
||||
continue;
|
||||
}
|
||||
|
||||
String address;
|
||||
String body;
|
||||
int type;
|
||||
try {
|
||||
address = msg.getString("address");
|
||||
body = msg.getString("msg");
|
||||
type = msg.getInt("type");
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Invalid SMS data found: " + e.getMessage());
|
||||
continue;
|
||||
}
|
||||
MailboxID mailbox_id = MailboxID.fromInt(mbid);
|
||||
|
||||
// Ignore already existing messages
|
||||
if (smsDataProvider.messageExists(address, body, key, mailbox_id)) {
|
||||
publishProgress(nb);
|
||||
continue;
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Telephony.Sms.ADDRESS, address);
|
||||
values.put(Telephony.Sms.BODY, body);
|
||||
values.put(Telephony.Sms.DATE, key);
|
||||
values.put(Telephony.Sms.TYPE, type);
|
||||
values.put(Telephony.Sms.SEEN, 1);
|
||||
values.put(Telephony.Sms.READ, 1);
|
||||
|
||||
// @TODO verify message exists before inserting it
|
||||
_context.getContentResolver().insert(Uri.parse(mailbox_id.getURI()), values);
|
||||
|
||||
nb++;
|
||||
if ((nb % 5) == 0) {
|
||||
publishProgress(nb);
|
||||
}
|
||||
}
|
||||
while ((obj != null) && (obj.getLastID() != start)) {
|
||||
SmsMessage message;
|
||||
while ((message = obj.getNextMessage()) != null) {
|
||||
int mbid = (int) message.getMailbox();
|
||||
// Ignore invalid mailbox
|
||||
if (mbid > MailboxID.ALL.getId()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Invalid mailbox found: " + mbid);
|
||||
continue;
|
||||
}
|
||||
|
||||
start = obj.getLong("last_id");
|
||||
|
||||
if (!new ConnectivityMonitor(_context).isValid()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Restore connectivity problems, aborting");
|
||||
return null;
|
||||
String address = message.getAddress();
|
||||
String body = message.getMessage();
|
||||
int type = (int) message.getType();
|
||||
if (address.isEmpty() || body.isEmpty()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Invalid SMS message found: " + message.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
MailboxID mailbox_id = MailboxID.fromInt(mbid);
|
||||
|
||||
String date = Integer.toString((int) message.getDate());
|
||||
// Ignore already existing messages
|
||||
if (smsDataProvider.messageExists(address, body, date, mailbox_id)) {
|
||||
publishProgress(nb);
|
||||
continue;
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Telephony.Sms.ADDRESS, address);
|
||||
values.put(Telephony.Sms.BODY, body);
|
||||
values.put(Telephony.Sms.DATE, date);
|
||||
values.put(Telephony.Sms.TYPE, type);
|
||||
values.put(Telephony.Sms.SEEN, 1);
|
||||
values.put(Telephony.Sms.READ, 1);
|
||||
|
||||
_context.getContentResolver().insert(Uri.parse(mailbox_id.getURI()), values);
|
||||
|
||||
nb++;
|
||||
if ((nb % 10) == 0) {
|
||||
publishProgress(nb);
|
||||
}
|
||||
obj = client.retrieveSomeMessages(start, 500);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Missing last_id field!");
|
||||
|
||||
start = obj.getLastID();
|
||||
|
||||
if (!new ConnectivityMonitor(_context).isValid()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Restore connectivity problems, aborting");
|
||||
return null;
|
||||
}
|
||||
obj = client.retrieveSomeMessages(start, 500);
|
||||
}
|
||||
|
||||
// Force this refresh to fix dates
|
||||
_context.getContentResolver().delete(Uri.parse("content://sms/conversations/-1"), null, null);
|
||||
_context.getContentResolver().delete(Uri.parse("content://sms/conversations/-1"),
|
||||
null, null);
|
||||
|
||||
publishProgress(nb);
|
||||
|
||||
|
@ -18,28 +18,9 @@ package fr.unix_experience.owncloud_sms.engine;
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import fr.unix_experience.owncloud_sms.R;
|
||||
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
||||
@ -48,66 +29,18 @@ import fr.unix_experience.owncloud_sms.providers.AndroidVersionProvider;
|
||||
import ncsmsgo.SmsBuffer;
|
||||
import ncsmsgo.SmsHTTPClient;
|
||||
import ncsmsgo.SmsIDListResponse;
|
||||
import ncsmsgo.SmsMessagesResponse;
|
||||
import ncsmsgo.SmsPhoneListResponse;
|
||||
import ncsmsgo.SmsPushResponse;
|
||||
|
||||
public class OCHttpClient {
|
||||
private SmsHTTPClient _smsHttpClient;
|
||||
|
||||
private static final String TAG = OCHttpClient.class.getCanonicalName();
|
||||
private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
|
||||
private final URL _url;
|
||||
private final String _userAgent;
|
||||
private final String _username;
|
||||
private final String _password;
|
||||
|
||||
public OCHttpClient(Context context, URL serverURL, String accountName, String accountPassword) {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
new X509TrustManager() {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
public void checkClientTrusted(
|
||||
java.security.cert.X509Certificate[] certs, String authType) {
|
||||
}
|
||||
public void checkServerTrusted(
|
||||
java.security.cert.X509Certificate[] certs, String authType) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
try {
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
_url = serverURL;
|
||||
_username = accountName;
|
||||
_password = accountPassword;
|
||||
|
||||
_smsHttpClient = new SmsHTTPClient();
|
||||
// @TODO: at a point add a flag to permit insecure connections somewhere instead of trusting them
|
||||
_smsHttpClient.init(_url.toString(), new AndroidVersionProvider(context).getVersionCode(),
|
||||
_username, _password, false);
|
||||
|
||||
_userAgent = "nextcloud-phonesync (" + new AndroidVersionProvider(context).getVersionCode() + ")";
|
||||
}
|
||||
|
||||
private Pair<Integer, JSONObject> get(String oc_call, boolean skipError) throws OCSyncException {
|
||||
Log.i(OCHttpClient.TAG, "Perform GET " + _url + oc_call);
|
||||
try {
|
||||
return execute("GET",
|
||||
new URL(_url.toString() + oc_call), "", skipError);
|
||||
} catch (MalformedURLException e) {
|
||||
Log.e(OCHttpClient.TAG, "Malformed URL provided, aborting. URL was: "
|
||||
+ _url.toExternalForm() + oc_call);
|
||||
}
|
||||
|
||||
return new Pair<>(0, null);
|
||||
_smsHttpClient.init(serverURL.toString(), new AndroidVersionProvider(context).getVersionCode(),
|
||||
accountName, accountPassword, false);
|
||||
}
|
||||
|
||||
private void handleEarlyHTTPStatus(int httpStatus) throws OCSyncException {
|
||||
@ -168,120 +101,10 @@ public class OCHttpClient {
|
||||
return new Pair<>(httpStatus, splr);
|
||||
}
|
||||
|
||||
Pair<Integer, JSONObject> getMessages(Long start, Integer limit) throws OCSyncException {
|
||||
return get(_smsHttpClient.getMessagesCall()
|
||||
.replace("[START]", start.toString())
|
||||
.replace("[LIMIT]", limit.toString()), false);
|
||||
}
|
||||
|
||||
public Pair<Integer, JSONObject> execute(String method, URL url, String requestBody, boolean skipError) throws OCSyncException {
|
||||
Pair<Integer, JSONObject> response;
|
||||
HttpURLConnection urlConnection = null;
|
||||
|
||||
try {
|
||||
urlConnection = (HttpURLConnection) url.openConnection();
|
||||
} catch (IOException e) {
|
||||
Log.e(OCHttpClient.TAG, "Failed to open connection to server: " + e);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
if (urlConnection == null) {
|
||||
Log.e(OCHttpClient.TAG, "Failed to open connection to server: null urlConnection");
|
||||
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
||||
}
|
||||
|
||||
try {
|
||||
urlConnection.setRequestMethod(method);
|
||||
} catch (ProtocolException e) {
|
||||
Log.e(OCHttpClient.TAG, "Fatal error when setting request method: " + e);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_protocol_exception, OCSyncErrorType.IO);
|
||||
}
|
||||
urlConnection.setRequestProperty("User-Agent", _userAgent);
|
||||
urlConnection.setInstanceFollowRedirects(true);
|
||||
if (!"GET".equals(method)) {
|
||||
urlConnection.setDoOutput(true);
|
||||
}
|
||||
urlConnection.setRequestProperty("Content-Type", "application/json");
|
||||
urlConnection.setRequestProperty("Accept", "application/json");
|
||||
if (!"GET".equals(method)) {
|
||||
urlConnection.setRequestProperty("Transfer-Encoding", "chunked");
|
||||
}
|
||||
String basicAuth = "Basic " +
|
||||
Base64.encodeToString((_username + ":" + _password).getBytes(), Base64.NO_WRAP);
|
||||
urlConnection.setRequestProperty("Authorization", basicAuth);
|
||||
urlConnection.setChunkedStreamingMode(0);
|
||||
|
||||
if (!"GET".equals(method)) {
|
||||
try {
|
||||
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
|
||||
out.write(requestBody.getBytes(Charset.forName("UTF-8")));
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(OCHttpClient.TAG, "Failed to open connection to server: " + e);
|
||||
throw new OCSyncException(R.string.err_sync_http_write_failed, OCSyncErrorType.IO);
|
||||
}
|
||||
}
|
||||
|
||||
response = handleHTTPResponse(urlConnection, skipError);
|
||||
return response;
|
||||
}
|
||||
|
||||
private Pair<Integer, JSONObject> handleHTTPResponse(HttpURLConnection connection, Boolean skipError) throws OCSyncException {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line).append("\n");
|
||||
}
|
||||
|
||||
String response = stringBuilder.toString();
|
||||
int status = connection.getResponseCode();
|
||||
|
||||
switch (status) {
|
||||
case 200: {
|
||||
// Parse the response
|
||||
try {
|
||||
JSONObject jsonResponse = new JSONObject(response);
|
||||
return new Pair<>(status, jsonResponse);
|
||||
|
||||
} catch (JSONException e) {
|
||||
if (!skipError) {
|
||||
if (response.contains("ownCloud") && response.contains("DOCTYPE")) {
|
||||
Log.e(OCHttpClient.TAG, "OcSMS app not enabled or ownCloud upgrade is required");
|
||||
throw new OCSyncException(R.string.err_sync_ocsms_not_installed_or_oc_upgrade_required,
|
||||
OCSyncErrorType.SERVER_ERROR);
|
||||
} else {
|
||||
Log.e(OCHttpClient.TAG, "Unable to parse server response", e);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_parse_resp, OCSyncErrorType.PARSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 403: {
|
||||
// Authentication failed
|
||||
throw new OCSyncException(R.string.err_sync_auth_failed, OCSyncErrorType.AUTH);
|
||||
}
|
||||
default: {
|
||||
// Unk error
|
||||
Log.e(OCHttpClient.TAG, "Server set unhandled HTTP return code " + status);
|
||||
Log.e(OCHttpClient.TAG, "Status code: " + status + ". Response message: " + response);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_returncode_unhandled, OCSyncErrorType.SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
reader.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
||||
}
|
||||
|
||||
return new Pair<>(0, null);
|
||||
Pair<Integer, SmsMessagesResponse> getMessages(Long start, Integer limit) throws OCSyncException {
|
||||
SmsMessagesResponse smr = _smsHttpClient.doGetMessagesCall(start, limit);
|
||||
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||
handleEarlyHTTPStatus(httpStatus);
|
||||
return new Pair<>(httpStatus, smr);
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,6 @@ import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
@ -34,6 +32,7 @@ import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||
import ncsmsgo.SmsBuffer;
|
||||
import ncsmsgo.SmsIDListResponse;
|
||||
import ncsmsgo.SmsMessagesResponse;
|
||||
import ncsmsgo.SmsPhoneListResponse;
|
||||
import ncsmsgo.SmsPushResponse;
|
||||
|
||||
@ -57,8 +56,6 @@ public class OCSMSOwnCloudClient {
|
||||
_http = new OCHttpClient(context,
|
||||
serverURL, accountManager.getUserData(account, "ocLogin"),
|
||||
accountManager.getPassword(account));
|
||||
|
||||
_connectivityMonitor = new ConnectivityMonitor(_context);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalStateException(context.getString(R.string.err_sync_account_unparsable));
|
||||
}
|
||||
@ -124,14 +121,14 @@ public class OCSMSOwnCloudClient {
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "LastMessageDate set to: " + smsBuffer.getLastMessageDate());
|
||||
}
|
||||
|
||||
JSONObject retrieveSomeMessages(Long start, Integer limit) {
|
||||
SmsMessagesResponse retrieveSomeMessages(Long start, Integer limit) {
|
||||
// This is not allowed by server
|
||||
if (limit > OCSMSOwnCloudClient.SERVER_RECOVERY_MSG_LIMIT) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Message recovery limit exceeded");
|
||||
return null;
|
||||
}
|
||||
|
||||
Pair<Integer, JSONObject> response;
|
||||
Pair<Integer, SmsMessagesResponse> response;
|
||||
try {
|
||||
response = _http.getMessages(start, limit);
|
||||
} catch (OCSyncException e) {
|
||||
@ -139,8 +136,7 @@ public class OCSMSOwnCloudClient {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((response.second == null) || !response.second.has("messages")
|
||||
|| !response.second.has("last_id")) {
|
||||
if (response.second == null) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG,
|
||||
"Invalid response received from server, either messages or last_id field is missing.");
|
||||
return null;
|
||||
@ -151,7 +147,6 @@ public class OCSMSOwnCloudClient {
|
||||
|
||||
private final OCHttpClient _http;
|
||||
private final Context _context;
|
||||
private final ConnectivityMonitor _connectivityMonitor;
|
||||
|
||||
private Integer _serverAPIVersion;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user