diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/http')
3 files changed, 106 insertions, 60 deletions
diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java index 58a6d1e3..90fbadfe 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java @@ -38,9 +38,9 @@ public class HttpConnectionManager extends AbstractConnectionManager { return connection; } - public HttpUploadConnection createNewUploadConnection(Message message) { + public HttpUploadConnection createNewUploadConnection(Message message, boolean delay) { HttpUploadConnection connection = new HttpUploadConnection(this); - connection.init(message); + connection.init(message,delay); this.uploadConnections.add(connection); return connection; } diff --git a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java index 45f1e965..356f9417 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java @@ -2,11 +2,12 @@ package eu.siacs.conversations.http; import android.content.Intent; import android.net.Uri; -import android.os.SystemClock; +import android.os.PowerManager; import android.util.Log; import java.io.BufferedInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; @@ -18,9 +19,11 @@ import javax.net.ssl.SSLHandshakeException; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Transferable; +import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; @@ -35,7 +38,6 @@ public class HttpDownloadConnection implements Transferable { private int mStatus = Transferable.STATUS_UNKNOWN; private boolean acceptedAutomatically = false; private int mProgress = 0; - private long mLastGuiRefresh = 0; public HttpDownloadConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; @@ -70,7 +72,8 @@ public class HttpDownloadConnection implements Transferable { String secondToLast = parts.length >= 2 ? parts[parts.length -2] : null; if ("pgp".equals(lastPart) || "gpg".equals(lastPart)) { this.message.setEncryption(Message.ENCRYPTION_PGP); - } else if (message.getEncryption() != Message.ENCRYPTION_OTR) { + } else if (message.getEncryption() != Message.ENCRYPTION_OTR + && message.getEncryption() != Message.ENCRYPTION_AXOLOTL) { this.message.setEncryption(Message.ENCRYPTION_NONE); } String extension; @@ -83,10 +86,11 @@ public class HttpDownloadConnection implements Transferable { this.file = mXmppConnectionService.getFileBackend().getFile(message, false); String reference = mUrl.getRef(); if (reference != null && reference.length() == 96) { - this.file.setKey(CryptoHelper.hexToBytes(reference)); + this.file.setKeyAndIv(CryptoHelper.hexToBytes(reference)); } - if (this.message.getEncryption() == Message.ENCRYPTION_OTR + if ((this.message.getEncryption() == Message.ENCRYPTION_OTR + || this.message.getEncryption() == Message.ENCRYPTION_AXOLOTL) && this.file.getKey() == null) { this.message.setEncryption(Message.ENCRYPTION_NONE); } @@ -123,6 +127,17 @@ public class HttpDownloadConnection implements Transferable { mXmppConnectionService.updateConversationUi(); } + private void showToastForException(Exception e) { + e.printStackTrace(); + if (e instanceof java.net.UnknownHostException) { + mXmppConnectionService.showErrorToastInUi(R.string.download_failed_server_not_found); + } else if (e instanceof java.net.ConnectException) { + mXmppConnectionService.showErrorToastInUi(R.string.download_failed_could_not_connect); + } else { + mXmppConnectionService.showErrorToastInUi(R.string.download_failed_file_not_found); + } + } + private class FileSizeChecker implements Runnable { private boolean interactive = false; @@ -144,7 +159,7 @@ public class HttpDownloadConnection implements Transferable { } catch (IOException e) { Log.d(Config.LOGTAG, "io exception in http file size checker: " + e.getMessage()); if (interactive) { - mXmppConnectionService.showErrorToastInUi(R.string.file_not_found_on_remote_host); + showToastForException(e); } cancel(); return; @@ -186,6 +201,8 @@ public class HttpDownloadConnection implements Transferable { private boolean interactive = false; + private OutputStream os; + public FileDownloader(boolean interactive) { this.interactive = interactive; } @@ -200,36 +217,44 @@ public class HttpDownloadConnection implements Transferable { } catch (SSLHandshakeException e) { changeStatus(STATUS_OFFER); } catch (IOException e) { - mXmppConnectionService.showErrorToastInUi(R.string.file_not_found_on_remote_host); + if (interactive) { + showToastForException(e); + } cancel(); } } - private void download() throws SSLHandshakeException, IOException { - HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); - if (connection instanceof HttpsURLConnection) { - mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive); - } - connection.connect(); - BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); - file.getParentFile().mkdirs(); - file.createNewFile(); - OutputStream os = file.createOutputStream(); - if (os == null) { - throw new IOException(); - } - long transmitted = 0; - long expected = file.getExpectedSize(); - int count = -1; - byte[] buffer = new byte[1024]; - while ((count = is.read(buffer)) != -1) { - transmitted += count; - os.write(buffer, 0, count); - updateProgress((int) ((((double) transmitted) / expected) * 100)); + private void download() throws IOException { + InputStream is = null; + PowerManager.WakeLock wakeLock = mHttpConnectionManager.createWakeLock("http_download_"+message.getUuid()); + try { + wakeLock.acquire(); + HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); + if (connection instanceof HttpsURLConnection) { + mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive); + } + connection.connect(); + is = new BufferedInputStream(connection.getInputStream()); + file.getParentFile().mkdirs(); + file.createNewFile(); + os = AbstractConnectionManager.createOutputStream(file, true); + long transmitted = 0; + long expected = file.getExpectedSize(); + int count = -1; + byte[] buffer = new byte[1024]; + while ((count = is.read(buffer)) != -1) { + transmitted += count; + os.write(buffer, 0, count); + updateProgress((int) ((((double) transmitted) / expected) * 100)); + } + os.flush(); + } catch (IOException e) { + throw e; + } finally { + FileBackend.close(os); + FileBackend.close(is); + wakeLock.release(); } - os.flush(); - os.close(); - is.close(); } private void updateImageBounds() { @@ -242,10 +267,7 @@ public class HttpDownloadConnection implements Transferable { public void updateProgress(int i) { this.mProgress = i; - if (SystemClock.elapsedRealtime() - this.mLastGuiRefresh > Config.PROGRESS_UI_UPDATE_INTERVAL) { - this.mLastGuiRefresh = SystemClock.elapsedRealtime(); - mXmppConnectionService.updateConversationUi(); - } + mXmppConnectionService.updateConversationUi(); } @Override diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java index a3ab8dab..2e545842 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java @@ -1,8 +1,13 @@ package eu.siacs.conversations.http; import android.app.PendingIntent; +import android.content.Intent; +import android.net.Uri; +import android.os.PowerManager; import android.util.Log; +import android.util.Pair; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -14,10 +19,11 @@ import javax.net.ssl.HttpsURLConnection; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.UiCallback; import eu.siacs.conversations.utils.CryptoHelper; @@ -33,16 +39,19 @@ public class HttpUploadConnection implements Transferable { private XmppConnectionService mXmppConnectionService; private boolean canceled = false; + private boolean delayed = false; private Account account; private DownloadableFile file; private Message message; + private String mime; private URL mGetUrl; private URL mPutUrl; private byte[] key = null; private long transmitted = 0; - private long expected = 1; + + private InputStream mFileInputStream; public HttpUploadConnection(HttpConnectionManager httpConnectionManager) { this.mHttpConnectionManager = httpConnectionManager; @@ -66,7 +75,7 @@ public class HttpUploadConnection implements Transferable { @Override public int getProgress() { - return (int) ((((double) transmitted) / expected) * 100); + return (int) ((((double) transmitted) / file.getExpectedSize()) * 100); } @Override @@ -77,25 +86,36 @@ public class HttpUploadConnection implements Transferable { private void fail() { mHttpConnectionManager.finishUploadConnection(this); message.setTransferable(null); - mXmppConnectionService.markMessage(message,Message.STATUS_SEND_FAILED); + mXmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED); + FileBackend.close(mFileInputStream); } - public void init(Message message) { + public void init(Message message, boolean delay) { this.message = message; message.setTransferable(this); - mXmppConnectionService.markMessage(message,Message.STATUS_UNSEND); + mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND); this.account = message.getConversation().getAccount(); this.file = mXmppConnectionService.getFileBackend().getFile(message, false); - this.file.setExpectedSize(this.file.getSize()); - - if (Config.ENCRYPT_ON_HTTP_UPLOADED) { + this.mime = this.file.getMimeType(); + this.delayed = delay; + if (Config.ENCRYPT_ON_HTTP_UPLOADED + || message.getEncryption() == Message.ENCRYPTION_AXOLOTL + || message.getEncryption() == Message.ENCRYPTION_OTR) { this.key = new byte[48]; mXmppConnectionService.getRNG().nextBytes(this.key); - this.file.setKey(this.key); + this.file.setKeyAndIv(this.key); } - + Pair<InputStream,Integer> pair; + try { + pair = AbstractConnectionManager.createInputStream(file, true); + } catch (FileNotFoundException e) { + fail(); + return; + } + this.file.setExpectedSize(pair.second); + this.mFileInputStream = pair.first; Jid host = account.getXmppConnection().findDiscoItemByFeature(Xmlns.HTTP_UPLOAD); - IqPacket request = mXmppConnectionService.getIqGenerator().requestHttpUploadSlot(host,file); + IqPacket request = mXmppConnectionService.getIqGenerator().requestHttpUploadSlot(host,file,mime); mXmppConnectionService.sendIqPacket(account, request, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { @@ -130,9 +150,10 @@ public class HttpUploadConnection implements Transferable { private void upload() { OutputStream os = null; - InputStream is = null; HttpURLConnection connection = null; + PowerManager.WakeLock wakeLock = mHttpConnectionManager.createWakeLock("http_upload_"+message.getUuid()); try { + wakeLock.acquire(); Log.d(Config.LOGTAG, "uploading to " + mPutUrl.toString()); connection = (HttpURLConnection) mPutUrl.openConnection(); if (connection instanceof HttpsURLConnection) { @@ -140,37 +161,38 @@ public class HttpUploadConnection implements Transferable { } connection.setRequestMethod("PUT"); connection.setFixedLengthStreamingMode((int) file.getExpectedSize()); + connection.setRequestProperty("Content-Type", mime == null ? "application/octet-stream" : mime); connection.setDoOutput(true); connection.connect(); os = connection.getOutputStream(); - is = file.createInputStream(); transmitted = 0; - expected = file.getExpectedSize(); int count = -1; byte[] buffer = new byte[4096]; - while (((count = is.read(buffer)) != -1) && !canceled) { + while (((count = mFileInputStream.read(buffer)) != -1) && !canceled) { transmitted += count; os.write(buffer, 0, count); mXmppConnectionService.updateConversationUi(); } os.flush(); os.close(); - is.close(); + mFileInputStream.close(); int code = connection.getResponseCode(); if (code == 200 || code == 201) { Log.d(Config.LOGTAG, "finished uploading file"); - Message.FileParams params = message.getFileParams(); if (key != null) { mGetUrl = new URL(mGetUrl.toString() + "#" + CryptoHelper.bytesToHex(key)); } mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl); + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(Uri.fromFile(file)); + mXmppConnectionService.sendBroadcast(intent); message.setTransferable(null); message.setCounterpart(message.getConversation().getJid().toBareJid()); if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { mXmppConnectionService.getPgpEngine().encrypt(message, new UiCallback<Message>() { @Override public void success(Message message) { - mXmppConnectionService.resendMessage(message); + mXmppConnectionService.resendMessage(message,delayed); } @Override @@ -184,20 +206,22 @@ public class HttpUploadConnection implements Transferable { } }); } else { - mXmppConnectionService.resendMessage(message); + mXmppConnectionService.resendMessage(message, delayed); } } else { fail(); } } catch (IOException e) { - Log.d(Config.LOGTAG, e.getMessage()); + e.printStackTrace(); + Log.d(Config.LOGTAG,"http upload failed "+e.getMessage()); fail(); } finally { - FileBackend.close(is); + FileBackend.close(mFileInputStream); FileBackend.close(os); if (connection != null) { connection.disconnect(); } + wakeLock.release(); } } } |