From 2ec021a42629120e8b4f1ae5a95027ec414b2b5c Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 13 Oct 2014 12:36:41 +0200 Subject: redesigned contact details a bit --- src/eu/siacs/conversations/ui/ContactDetailsActivity.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java index 9926e126..394aab6e 100644 --- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -309,7 +309,7 @@ public class ContactDetailsActivity extends XmppActivity { } else { contactJidTv.setText(contact.getJid()); } - accountJidTv.setText(contact.getAccount().getJid()); + accountJidTv.setText(getString(R.string.using_account,contact.getAccount().getJid())); UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext()); @@ -319,9 +319,11 @@ public class ContactDetailsActivity extends XmppActivity { } keys.removeAllViews(); + boolean hasKeys = false; LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); for (Iterator iterator = contact.getOtrFingerprints() .iterator(); iterator.hasNext();) { + hasKeys = true; final String otrFingerprint = iterator.next(); View view = (View) inflater.inflate(R.layout.contact_key, keys, false); @@ -342,6 +344,7 @@ public class ContactDetailsActivity extends XmppActivity { }); } if (contact.getPgpKeyId() != 0) { + hasKeys = true; View view = (View) inflater.inflate(R.layout.contact_key, keys, false); TextView key = (TextView) view.findViewById(R.id.key); @@ -370,6 +373,11 @@ public class ContactDetailsActivity extends XmppActivity { }); keys.addView(view); } + if (hasKeys) { + keys.setVisibility(View.VISIBLE); + } else { + keys.setVisibility(View.GONE); + } } protected void confirmToDeleteFingerprint(final String fingerprint) { -- cgit v1.2.3 From a42f0dd3bc08308e4035ce42c7fbc11f1824d329 Mon Sep 17 00:00:00 2001 From: "M. Dietrich" Date: Wed, 8 Oct 2014 23:24:36 +0200 Subject: use setAlpha(float) method, not the depricated one --- src/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 2671cf50..dbf2184b 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -390,7 +390,7 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.contact_picture.setImageBitmap(mBitmapCache.get( item.getConversation().getContact(), getContext())); - viewHolder.contact_picture.setAlpha(128); + viewHolder.contact_picture.setAlpha(0.5f); viewHolder.contact_picture .setOnClickListener(new OnClickListener() { -- cgit v1.2.3 From d61e4cce1075e3561406be96b402def5f90dcd58 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 13 Oct 2014 14:36:19 +0200 Subject: reworked muc details and contact details a bit --- src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java | 3 +++ src/eu/siacs/conversations/ui/EditAccountActivity.java | 12 +++++------- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 04059d52..589268ee 100644 --- a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -41,6 +41,7 @@ public class ConferenceDetailsActivity extends XmppActivity { private ImageButton mEditNickButton; private TextView mRoleAffiliaton; private TextView mFullJid; + private TextView mAccountJid; private LinearLayout membersView; private LinearLayout mMoreDetails; private Button mInviteButton; @@ -78,6 +79,7 @@ public class ConferenceDetailsActivity extends XmppActivity { mEditNickButton = (ImageButton) findViewById(R.id.edit_nick_button); mFullJid = (TextView) findViewById(R.id.muc_jabberid); membersView = (LinearLayout) findViewById(R.id.muc_members); + mAccountJid = (TextView) findViewById(R.id.details_account); mMoreDetails = (LinearLayout) findViewById(R.id.muc_more_details); mMoreDetails.setVisibility(View.GONE); mInviteButton = (Button) findViewById(R.id.invite); @@ -199,6 +201,7 @@ public class ConferenceDetailsActivity extends XmppActivity { } private void populateView() { + mAccountJid.setText(getString(R.string.using_account,conversation.getAccount().getJid())); mYourPhoto.setImageBitmap(conversation.getAccount().getImage(this, 48)); setTitle(conversation.getName()); mFullJid.setText(conversation.getContactJid().split("/", 2)[0]); diff --git a/src/eu/siacs/conversations/ui/EditAccountActivity.java b/src/eu/siacs/conversations/ui/EditAccountActivity.java index 0ec38547..1543d740 100644 --- a/src/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/eu/siacs/conversations/ui/EditAccountActivity.java @@ -17,6 +17,7 @@ import android.widget.EditText; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import eu.siacs.conversations.R; @@ -43,7 +44,7 @@ public class EditAccountActivity extends XmppActivity { private TextView mServerInfoPep; private TextView mSessionEst; private TextView mOtrFingerprint; - private TextView mOtrFingerprintHeadline; + private RelativeLayout mOtrFingerprintBox; private ImageButton mOtrFingerprintToClipboardButton; private String jidToEdit; @@ -277,7 +278,7 @@ public class EditAccountActivity extends XmppActivity { this.mServerInfoSm = (TextView) findViewById(R.id.server_info_sm); this.mServerInfoPep = (TextView) findViewById(R.id.server_info_pep); this.mOtrFingerprint = (TextView) findViewById(R.id.otr_fingerprint); - this.mOtrFingerprintHeadline = (TextView) findViewById(R.id.otr_fingerprint_headline); + this.mOtrFingerprintBox = (RelativeLayout) findViewById(R.id.otr_fingerprint_box); this.mOtrFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_to_clipboard); this.mSaveButton = (Button) findViewById(R.id.save_button); this.mCancelButton = (Button) findViewById(R.id.cancel_button); @@ -378,8 +379,7 @@ public class EditAccountActivity extends XmppActivity { final String fingerprint = this.mAccount .getOtrFingerprint(xmppConnectionService); if (fingerprint != null) { - this.mOtrFingerprintHeadline.setVisibility(View.VISIBLE); - this.mOtrFingerprint.setVisibility(View.VISIBLE); + this.mOtrFingerprintBox.setVisibility(View.VISIBLE); this.mOtrFingerprint.setText(fingerprint); this.mOtrFingerprintToClipboardButton .setVisibility(View.VISIBLE); @@ -398,9 +398,7 @@ public class EditAccountActivity extends XmppActivity { } }); } else { - this.mOtrFingerprintToClipboardButton.setVisibility(View.GONE); - this.mOtrFingerprint.setVisibility(View.GONE); - this.mOtrFingerprintHeadline.setVisibility(View.GONE); + this.mOtrFingerprintBox.setVisibility(View.GONE); } } else { if (this.mAccount.errorStatus()) { -- cgit v1.2.3 From bbb0693f4a9a62a872b61b12a5118b01c7ca9450 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 01:06:45 +0200 Subject: basic image over http downloading --- .../conversations/AbstractConnectionManager.java | 25 ++++ src/eu/siacs/conversations/DownloadableFile.java | 148 +++++++++++++++++++++ src/eu/siacs/conversations/crypto/PgpEngine.java | 18 +-- src/eu/siacs/conversations/entities/Contact.java | 4 + .../siacs/conversations/entities/Downloadable.java | 4 + src/eu/siacs/conversations/entities/Message.java | 41 +++++- src/eu/siacs/conversations/entities/Roster.java | 2 +- .../siacs/conversations/http/HttpConnection.java | 129 ++++++++++++++++++ .../conversations/http/HttpConnectionManager.java | 27 ++++ .../siacs/conversations/parser/MessageParser.java | 3 + .../conversations/persistance/FileBackend.java | 22 +-- .../services/XmppConnectionService.java | 8 +- .../xmpp/jingle/JingleConnection.java | 9 +- .../xmpp/jingle/JingleConnectionManager.java | 22 +-- .../conversations/xmpp/jingle/JingleFile.java | 68 ---------- .../xmpp/jingle/JingleInbandTransport.java | 14 +- .../xmpp/jingle/JingleSocks5Transport.java | 9 +- .../conversations/xmpp/jingle/JingleTransport.java | 81 +---------- .../jingle/OnFileTransmissionStatusChanged.java | 4 +- .../conversations/xmpp/jingle/stanzas/Content.java | 4 +- 20 files changed, 429 insertions(+), 213 deletions(-) create mode 100644 src/eu/siacs/conversations/AbstractConnectionManager.java create mode 100644 src/eu/siacs/conversations/DownloadableFile.java create mode 100644 src/eu/siacs/conversations/http/HttpConnection.java create mode 100644 src/eu/siacs/conversations/http/HttpConnectionManager.java delete mode 100644 src/eu/siacs/conversations/xmpp/jingle/JingleFile.java (limited to 'src') diff --git a/src/eu/siacs/conversations/AbstractConnectionManager.java b/src/eu/siacs/conversations/AbstractConnectionManager.java new file mode 100644 index 00000000..f2c937ab --- /dev/null +++ b/src/eu/siacs/conversations/AbstractConnectionManager.java @@ -0,0 +1,25 @@ +package eu.siacs.conversations; + +import eu.siacs.conversations.services.XmppConnectionService; + +public class AbstractConnectionManager { + protected XmppConnectionService mXmppConnectionService; + + public AbstractConnectionManager(XmppConnectionService service) { + this.mXmppConnectionService = service; + } + + public XmppConnectionService getXmppConnectionService() { + return this.mXmppConnectionService; + } + + public long getAutoAcceptFileSize() { + String config = this.mXmppConnectionService.getPreferences().getString( + "auto_accept_file_size", "524288"); + try { + return Long.parseLong(config); + } catch (NumberFormatException e) { + return 524288; + } + } +} diff --git a/src/eu/siacs/conversations/DownloadableFile.java b/src/eu/siacs/conversations/DownloadableFile.java new file mode 100644 index 00000000..c8097df8 --- /dev/null +++ b/src/eu/siacs/conversations/DownloadableFile.java @@ -0,0 +1,148 @@ +package eu.siacs.conversations; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import eu.siacs.conversations.utils.CryptoHelper; +import android.util.Log; + +public class DownloadableFile extends File { + + private static final long serialVersionUID = 2247012619505115863L; + + private long expectedSize = 0; + private String sha1sum; + private Key aeskey; + + private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; + + public DownloadableFile(String path) { + super(path); + } + + public long getSize() { + return super.length(); + } + + public long getExpectedSize() { + if (this.aeskey != null) { + return (this.expectedSize / 16 + 1) * 16; + } else { + return this.expectedSize; + } + } + + public void setExpectedSize(long size) { + this.expectedSize = size; + } + + public String getSha1Sum() { + return this.sha1sum; + } + + public void setSha1Sum(String sum) { + this.sha1sum = sum; + } + + public void setKey(byte[] key) { + if (key.length >= 32) { + byte[] secretKey = new byte[32]; + System.arraycopy(key, 0, secretKey, 0, 32); + this.aeskey = new SecretKeySpec(secretKey, "AES"); + } else if (key.length >= 16) { + byte[] secretKey = new byte[16]; + System.arraycopy(key, 0, secretKey, 0, 16); + this.aeskey = new SecretKeySpec(secretKey, "AES"); + } else { + Log.d(Config.LOGTAG, "weird key"); + } + Log.d(Config.LOGTAG, + "using aes key " + + CryptoHelper.bytesToHex(this.aeskey.getEncoded())); + } + + public Key getKey() { + return this.aeskey; + } + + public InputStream createInputStream() { + if (this.getKey() == null) { + try { + return new FileInputStream(this); + } catch (FileNotFoundException e) { + return null; + } + } else { + try { + IvParameterSpec ips = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, this.getKey(), ips); + Log.d(Config.LOGTAG, "opening encrypted input stream"); + return new CipherInputStream(new FileInputStream(this), cipher); + } catch (NoSuchAlgorithmException e) { + Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); + return null; + } catch (NoSuchPaddingException e) { + Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); + return null; + } catch (InvalidKeyException e) { + Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); + return null; + } catch (InvalidAlgorithmParameterException e) { + Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); + return null; + } catch (FileNotFoundException e) { + return null; + } + } + } + + public OutputStream createOutputStream() { + if (this.getKey() == null) { + try { + return new FileOutputStream(this); + } catch (FileNotFoundException e) { + return null; + } + } else { + try { + IvParameterSpec ips = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, this.getKey(), ips); + Log.d(Config.LOGTAG, "opening encrypted output stream"); + return new CipherOutputStream(new FileOutputStream(this), + cipher); + } catch (NoSuchAlgorithmException e) { + Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); + return null; + } catch (NoSuchPaddingException e) { + Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); + return null; + } catch (InvalidKeyException e) { + Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); + return null; + } catch (InvalidAlgorithmParameterException e) { + Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); + return null; + } catch (FileNotFoundException e) { + return null; + } + } + } +} diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index e7058a68..d83a210d 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -15,6 +15,7 @@ import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback; import eu.siacs.conversations.Config; +import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; @@ -22,7 +23,6 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.UiCallback; -import eu.siacs.conversations.xmpp.jingle.JingleFile; import android.app.PendingIntent; import android.content.Intent; import android.graphics.BitmapFactory; @@ -86,10 +86,10 @@ public class PgpEngine { }); } else if (message.getType() == Message.TYPE_IMAGE) { try { - final JingleFile inputFile = this.mXmppConnectionService - .getFileBackend().getJingleFile(message, false); - final JingleFile outputFile = this.mXmppConnectionService - .getFileBackend().getJingleFile(message, true); + final DownloadableFile inputFile = this.mXmppConnectionService + .getFileBackend().getConversationsFile(message, false); + final DownloadableFile outputFile = this.mXmppConnectionService + .getFileBackend().getConversationsFile(message, true); outputFile.createNewFile(); InputStream is = new FileInputStream(inputFile); OutputStream os = new FileOutputStream(outputFile); @@ -197,10 +197,10 @@ public class PgpEngine { }); } else if (message.getType() == Message.TYPE_IMAGE) { try { - JingleFile inputFile = this.mXmppConnectionService - .getFileBackend().getJingleFile(message, true); - JingleFile outputFile = this.mXmppConnectionService - .getFileBackend().getJingleFile(message, false); + DownloadableFile inputFile = this.mXmppConnectionService + .getFileBackend().getConversationsFile(message, true); + DownloadableFile outputFile = this.mXmppConnectionService + .getFileBackend().getConversationsFile(message, false); outputFile.createNewFile(); InputStream is = new FileInputStream(inputFile); OutputStream os = new FileOutputStream(outputFile); diff --git a/src/eu/siacs/conversations/entities/Contact.java b/src/eu/siacs/conversations/entities/Contact.java index b1ebe662..40eee73d 100644 --- a/src/eu/siacs/conversations/entities/Contact.java +++ b/src/eu/siacs/conversations/entities/Contact.java @@ -374,4 +374,8 @@ public class Contact implements ListItem { return false; } } + + public boolean trusted() { + return getOption(Options.FROM) && getOption(Options.TO); + } } diff --git a/src/eu/siacs/conversations/entities/Downloadable.java b/src/eu/siacs/conversations/entities/Downloadable.java index 8fb4977e..c8ee357d 100644 --- a/src/eu/siacs/conversations/entities/Downloadable.java +++ b/src/eu/siacs/conversations/entities/Downloadable.java @@ -1,5 +1,9 @@ package eu.siacs.conversations.entities; public interface Downloadable { + + public final String[] VALID_EXTENSIONS = { "webp", "jpeg", "jpg", "png" }; + public final String[] VALID_CRYPTO_EXTENSIONS = { "pgp", "gpg", "otr" }; + public void start(); } diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index 49482bbc..b459510c 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -1,10 +1,15 @@ package eu.siacs.conversations.entities; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; + import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; +import android.text.InputFilter.LengthFilter; public class Message extends AbstractEntity { @@ -131,14 +136,8 @@ public class Message extends AbstractEntity { if (this.trueCounterpart == null) { return null; } else { - Account account = this.conversation.getAccount(); - Contact contact = account.getRoster().getContact( + return this.conversation.getAccount().getRoster().getContactFromRoster( this.trueCounterpart); - if (contact.showInRoster()) { - return contact; - } else { - return null; - } } } } @@ -369,4 +368,32 @@ public class Message extends AbstractEntity { return prev.mergable(this); } } + + public boolean bodyContainsDownloadable() { + Contact contact = this.getContact(); + if (contact == null || !contact.trusted()) { + return false; + } + try { + URL url = new URL(this.getBody()); + if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { + return false; + } + if (url.getPath()==null) { + return false; + } + String[] pathParts = url.getPath().split("/"); + String filename = pathParts[pathParts.length - 1]; + String[] extensionParts = filename.split("\\."); + if (extensionParts.length == 2 && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains(extensionParts[extensionParts.length -1])) { + return true; + } else if (extensionParts.length == 3 && Arrays.asList(Downloadable.VALID_CRYPTO_EXTENSIONS).contains(extensionParts.length -1) && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains(extensionParts[extensionParts.length -2])) { + return true; + } else { + return false; + } + } catch (MalformedURLException e) { + return false; + } + } } diff --git a/src/eu/siacs/conversations/entities/Roster.java b/src/eu/siacs/conversations/entities/Roster.java index b6908793..ef47c577 100644 --- a/src/eu/siacs/conversations/entities/Roster.java +++ b/src/eu/siacs/conversations/entities/Roster.java @@ -14,7 +14,7 @@ public class Roster { this.account = account; } - public Contact getContactAsShownInRoster(String jid) { + public Contact getContactFromRoster(String jid) { String cleanJid = jid.split("/", 2)[0]; Contact contact = contacts.get(cleanJid); if (contact != null && contact.showInRoster()) { diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java new file mode 100644 index 00000000..d3b1700b --- /dev/null +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -0,0 +1,129 @@ +package eu.siacs.conversations.http; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; + +import android.util.Log; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.DownloadableFile; +import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.services.XmppConnectionService; + +public class HttpConnection implements Downloadable { + + private HttpConnectionManager mHttpConnectionManager; + private XmppConnectionService mXmppConnectionService; + + private URL mUrl; + private Message message; + private DownloadableFile file; + + public HttpConnection(HttpConnectionManager manager) { + this.mHttpConnectionManager = manager; + this.mXmppConnectionService = manager.getXmppConnectionService(); + } + + @Override + public void start() { + new Thread(new FileDownloader()).start(); + } + + public void init(Message message) { + this.message = message; + this.message.setDownloadable(this); + try { + mUrl = new URL(message.getBody()); + this.file = mXmppConnectionService.getFileBackend().getConversationsFile(message,false); + message.setType(Message.TYPE_IMAGE); + mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED_OFFER); + checkFileSize(); + } catch (MalformedURLException e) { + this.cancel(); + } + } + + private void checkFileSize() { + new Thread(new FileSizeChecker()).start(); + } + + public void cancel() { + mXmppConnectionService.markMessage(message, Message.STATUS_RECEPTION_FAILED); + Log.d(Config.LOGTAG,"canceled download"); + } + + private class FileSizeChecker implements Runnable { + + @Override + public void run() { + try { + long size = retrieveFileSize(); + file.setExpectedSize(size); + if (size <= mHttpConnectionManager.getAutoAcceptFileSize()) { + start(); + } + Log.d(Config.LOGTAG,"file size: "+size); + } catch (IOException e) { + cancel(); + } + } + + private long retrieveFileSize() throws IOException { + HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); + connection.setRequestMethod("HEAD"); + if (connection instanceof HttpsURLConnection) { + + } + String contentLength = connection.getHeaderField("Content-Length"); + if (contentLength == null) { + throw new IOException(); + } + try { + return Long.parseLong(contentLength, 10); + } catch (NumberFormatException e) { + throw new IOException(); + } + } + + } + + private class FileDownloader implements Runnable { + + @Override + public void run() { + try { + mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVING); + download(); + mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED); + } catch (IOException e) { + cancel(); + } + } + + private void download() throws IOException { + HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); + if (connection instanceof HttpsURLConnection) { + + } + BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); + OutputStream os = file.createOutputStream(); + int count = -1; + byte[] buffer = new byte[1024]; + while ((count = is.read(buffer)) != -1) { + os.write(buffer, 0, count); + } + os.flush(); + os.close(); + is.close(); + Log.d(Config.LOGTAG,"finished downloading "+file.getAbsolutePath().toString()); + } + + } +} \ No newline at end of file diff --git a/src/eu/siacs/conversations/http/HttpConnectionManager.java b/src/eu/siacs/conversations/http/HttpConnectionManager.java new file mode 100644 index 00000000..ee50ef7e --- /dev/null +++ b/src/eu/siacs/conversations/http/HttpConnectionManager.java @@ -0,0 +1,27 @@ +package eu.siacs.conversations.http; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import eu.siacs.conversations.AbstractConnectionManager; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.services.XmppConnectionService; + +public class HttpConnectionManager extends AbstractConnectionManager { + + public HttpConnectionManager(XmppConnectionService service) { + super(service); + } + + private XmppConnectionService mXmppConnectionService; + + private List connections = new CopyOnWriteArrayList(); + + + public HttpConnection createNewConnection(Message message) { + HttpConnection connection = new HttpConnection(this); + connection.init(message); + this.connections.add(connection); + return connection; + } +} diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index f8329037..71346c7a 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -478,6 +478,9 @@ public class MessageParser extends AbstractParser implements mXmppConnectionService.databaseBackend.createMessage(message); } } + if (message.getStatus() == Message.STATUS_RECEIVED && message.bodyContainsDownloadable()) { + this.mXmppConnectionService.getHttpConnectionManager().createNewConnection(message); + } notify = notify && !conversation.isMuted(); if (notify) { mXmppConnectionService.getNotificationService().push(message); diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index d86c0ee1..8d5046ab 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -30,13 +30,13 @@ import android.util.Base64OutputStream; import android.util.Log; import android.util.LruCache; import eu.siacs.conversations.Config; +import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.ImageProvider; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.UIHelper; -import eu.siacs.conversations.xmpp.jingle.JingleFile; import eu.siacs.conversations.xmpp.pep.Avatar; public class FileBackend { @@ -66,11 +66,11 @@ public class FileBackend { return thumbnailCache; } - public JingleFile getJingleFileLegacy(Message message) { + public DownloadableFile getJingleFileLegacy(Message message) { return getJingleFileLegacy(message, true); } - public JingleFile getJingleFileLegacy(Message message, boolean decrypted) { + public DownloadableFile getJingleFileLegacy(Message message, boolean decrypted) { Conversation conversation = message.getConversation(); String prefix = context.getFilesDir().getAbsolutePath(); String path = prefix + "/" + conversation.getAccount().getJid() + "/" @@ -85,14 +85,14 @@ public class FileBackend { filename = message.getUuid() + ".webp.pgp"; } } - return new JingleFile(path + "/" + filename); + return new DownloadableFile(path + "/" + filename); } - public JingleFile getJingleFile(Message message) { - return getJingleFile(message, true); + public DownloadableFile getJingleFile(Message message) { + return getConversationsFile(message, true); } - public JingleFile getJingleFile(Message message, boolean decrypted) { + public DownloadableFile getConversationsFile(Message message, boolean decrypted) { StringBuilder filename = new StringBuilder(); filename.append(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath()); @@ -107,7 +107,7 @@ public class FileBackend { filename.append(".webp.pgp"); } } - return new JingleFile(filename.toString()); + return new DownloadableFile(filename.toString()); } public Bitmap resize(Bitmap originalBitmap, int size) { @@ -139,17 +139,17 @@ public class FileBackend { return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); } - public JingleFile copyImageToPrivateStorage(Message message, Uri image) + public DownloadableFile copyImageToPrivateStorage(Message message, Uri image) throws ImageCopyException { return this.copyImageToPrivateStorage(message, image, 0); } - private JingleFile copyImageToPrivateStorage(Message message, Uri image, + private DownloadableFile copyImageToPrivateStorage(Message message, Uri image, int sampleSize) throws ImageCopyException { try { InputStream is = context.getContentResolver() .openInputStream(image); - JingleFile file = getJingleFile(message); + DownloadableFile file = getJingleFile(message); file.getParentFile().mkdirs(); file.createNewFile(); Bitmap originalBitmap; diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index e6297f4f..3549ce0a 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -34,6 +34,7 @@ import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.generator.IqGenerator; import eu.siacs.conversations.generator.MessageGenerator; import eu.siacs.conversations.generator.PresenceGenerator; +import eu.siacs.conversations.http.HttpConnectionManager; import eu.siacs.conversations.parser.IqParser; import eu.siacs.conversations.parser.MessageParser; import eu.siacs.conversations.parser.PresenceParser; @@ -106,6 +107,7 @@ public class XmppConnectionService extends Service { private CopyOnWriteArrayList conversations = null; private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager( this); + private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(this); private OnConversationUpdate mOnConversationUpdate = null; private int convChangedListenerCount = 0; @@ -1780,7 +1782,7 @@ public class XmppConnectionService extends Service { for (Account account : getAccounts()) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { Contact contact = account.getRoster() - .getContactAsShownInRoster(jid); + .getContactFromRoster(jid); if (contact != null) { contacts.add(contact); } @@ -1792,4 +1794,8 @@ public class XmppConnectionService extends Service { public NotificationService getNotificationService() { return this.mNotificationService; } + + public HttpConnectionManager getHttpConnectionManager() { + return this.mHttpConnectionManager; + } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 92fdbe0b..4dac54f6 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -13,6 +13,7 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.util.Log; import eu.siacs.conversations.Config; +import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Downloadable; @@ -54,7 +55,7 @@ public class JingleConnection implements Downloadable { private String transportId; private Element fileOffer; - private JingleFile file = null; + private DownloadableFile file = null; private String contentName; private String contentCreator; @@ -83,7 +84,7 @@ public class JingleConnection implements Downloadable { final OnFileTransmissionStatusChanged onFileTransmissionSatusChanged = new OnFileTransmissionStatusChanged() { @Override - public void onFileTransmitted(JingleFile file) { + public void onFileTransmitted(DownloadableFile file) { if (responder.equals(account.getFullJid())) { sendSuccess(); if (acceptedAutomatically) { @@ -323,7 +324,7 @@ public class JingleConnection implements Downloadable { .push(message); } this.file = this.mXmppConnectionService.getFileBackend() - .getJingleFile(message, false); + .getConversationsFile(message, false); if (message.getEncryption() == Message.ENCRYPTION_OTR) { byte[] key = conversation.getSymmetricKey(); if (key == null) { @@ -355,7 +356,7 @@ public class JingleConnection implements Downloadable { if (message.getType() == Message.TYPE_IMAGE) { content.setTransportId(this.transportId); this.file = this.mXmppConnectionService.getFileBackend() - .getJingleFile(message, false); + .getConversationsFile(message, false); if (message.getEncryption() == Message.ENCRYPTION_OTR) { Conversation conversation = this.message.getConversation(); this.mXmppConnectionService.renewSymmetricKey(conversation); diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 79090af6..93b03ff8 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import android.annotation.SuppressLint; import android.util.Log; +import eu.siacs.conversations.AbstractConnectionManager; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Message; @@ -16,10 +17,7 @@ import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket; -public class JingleConnectionManager { - - private XmppConnectionService xmppConnectionService; - +public class JingleConnectionManager extends AbstractConnectionManager { private List connections = new CopyOnWriteArrayList(); private HashMap primaryCandidates = new HashMap(); @@ -28,7 +26,7 @@ public class JingleConnectionManager { private SecureRandom random = new SecureRandom(); public JingleConnectionManager(XmppConnectionService service) { - this.xmppConnectionService = service; + super(service); } public void deliverPacket(Account account, JinglePacket packet) { @@ -68,10 +66,6 @@ public class JingleConnectionManager { this.connections.remove(connection); } - public XmppConnectionService getXmppConnectionService() { - return this.xmppConnectionService; - } - public void getPrimaryCandidate(Account account, final OnPrimaryCandidateFound listener) { if (!this.primaryCandidates.containsKey(account.getJid())) { @@ -128,16 +122,6 @@ public class JingleConnectionManager { return new BigInteger(50, random).toString(32); } - public long getAutoAcceptFileSize() { - String config = this.xmppConnectionService.getPreferences().getString( - "auto_accept_file_size", "524288"); - try { - return Long.parseLong(config); - } catch (NumberFormatException e) { - return 524288; - } - } - public void deliverIbbPacket(Account account, IqPacket packet) { String sid = null; Element payload = null; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java b/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java deleted file mode 100644 index 9253814b..00000000 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java +++ /dev/null @@ -1,68 +0,0 @@ -package eu.siacs.conversations.xmpp.jingle; - -import java.io.File; -import java.security.Key; - -import javax.crypto.spec.SecretKeySpec; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.utils.CryptoHelper; -import android.util.Log; - -public class JingleFile extends File { - - private static final long serialVersionUID = 2247012619505115863L; - - private long expectedSize = 0; - private String sha1sum; - private Key aeskey; - - public JingleFile(String path) { - super(path); - } - - public long getSize() { - return super.length(); - } - - public long getExpectedSize() { - if (this.aeskey != null) { - return (this.expectedSize / 16 + 1) * 16; - } else { - return this.expectedSize; - } - } - - public void setExpectedSize(long size) { - this.expectedSize = size; - } - - public String getSha1Sum() { - return this.sha1sum; - } - - public void setSha1Sum(String sum) { - this.sha1sum = sum; - } - - public void setKey(byte[] key) { - if (key.length >= 32) { - byte[] secretKey = new byte[32]; - System.arraycopy(key, 0, secretKey, 0, 32); - this.aeskey = new SecretKeySpec(secretKey, "AES"); - } else if (key.length >= 16) { - byte[] secretKey = new byte[16]; - System.arraycopy(key, 0, secretKey, 0, 16); - this.aeskey = new SecretKeySpec(secretKey, "AES"); - } else { - Log.d(Config.LOGTAG, "weird key"); - } - Log.d(Config.LOGTAG, - "using aes key " - + CryptoHelper.bytesToHex(this.aeskey.getEncoded())); - } - - public Key getKey() { - return this.aeskey; - } -} diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java index c5498075..ed64c24a 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.xmpp.jingle; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -9,6 +8,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import android.util.Base64; +import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xml.Element; @@ -26,7 +26,7 @@ public class JingleInbandTransport extends JingleTransport { private boolean established = false; - private JingleFile file; + private DownloadableFile file; private InputStream fileInputStream = null; private OutputStream fileOutputStream; @@ -77,7 +77,7 @@ public class JingleInbandTransport extends JingleTransport { } @Override - public void receive(JingleFile file, + public void receive(DownloadableFile file, OnFileTransmissionStatusChanged callback) { this.onFileTransmissionStatusChanged = callback; this.file = file; @@ -86,7 +86,7 @@ public class JingleInbandTransport extends JingleTransport { digest.reset(); file.getParentFile().mkdirs(); file.createNewFile(); - this.fileOutputStream = getOutputStream(file); + this.fileOutputStream = file.createOutputStream(); if (this.fileOutputStream == null) { callback.onFileTransferAborted(); return; @@ -100,20 +100,18 @@ public class JingleInbandTransport extends JingleTransport { } @Override - public void send(JingleFile file, OnFileTransmissionStatusChanged callback) { + public void send(DownloadableFile file, OnFileTransmissionStatusChanged callback) { this.onFileTransmissionStatusChanged = callback; this.file = file; try { this.digest = MessageDigest.getInstance("SHA-1"); this.digest.reset(); - fileInputStream = this.getInputStream(file); + fileInputStream = this.file.createInputStream(); if (fileInputStream == null) { callback.onFileTransferAborted(); return; } this.sendNextBlock(); - } catch (FileNotFoundException e) { - callback.onFileTransferAborted(); } catch (NoSuchAlgorithmException e) { callback.onFileTransferAborted(); } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java index 63f5a507..ec6b2c24 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -10,6 +10,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; +import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.utils.CryptoHelper; public class JingleSocks5Transport extends JingleTransport { @@ -86,7 +87,7 @@ public class JingleSocks5Transport extends JingleTransport { } - public void send(final JingleFile file, + public void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) { new Thread(new Runnable() { @@ -96,7 +97,7 @@ public class JingleSocks5Transport extends JingleTransport { try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.reset(); - fileInputStream = getInputStream(file); + fileInputStream = file.createInputStream(); if (fileInputStream == null) { callback.onFileTransferAborted(); return; @@ -132,7 +133,7 @@ public class JingleSocks5Transport extends JingleTransport { } - public void receive(final JingleFile file, + public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) { new Thread(new Runnable() { @@ -145,7 +146,7 @@ public class JingleSocks5Transport extends JingleTransport { socket.setSoTimeout(30000); file.getParentFile().mkdirs(); file.createNewFile(); - OutputStream fileOutputStream = getOutputStream(file); + OutputStream fileOutputStream = file.createOutputStream(); if (fileOutputStream == null) { callback.onFileTransferAborted(); return; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java index 07dc8ecc..185018e6 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java @@ -1,88 +1,13 @@ package eu.siacs.conversations.xmpp.jingle; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.Cipher; -import javax.crypto.CipherOutputStream; -import javax.crypto.CipherInputStream; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; - -import eu.siacs.conversations.Config; - -import android.util.Log; +import eu.siacs.conversations.DownloadableFile; public abstract class JingleTransport { public abstract void connect(final OnTransportConnected callback); - public abstract void receive(final JingleFile file, + public abstract void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback); - public abstract void send(final JingleFile file, + public abstract void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback); - - private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; - - protected InputStream getInputStream(JingleFile file) - throws FileNotFoundException { - if (file.getKey() == null) { - return new FileInputStream(file); - } else { - try { - IvParameterSpec ips = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.ENCRYPT_MODE, file.getKey(), ips); - Log.d(Config.LOGTAG, "opening encrypted input stream"); - return new CipherInputStream(new FileInputStream(file), cipher); - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); - return null; - } catch (NoSuchPaddingException e) { - Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); - return null; - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); - return null; - } catch (InvalidAlgorithmParameterException e) { - Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); - return null; - } - } - } - - protected OutputStream getOutputStream(JingleFile file) - throws FileNotFoundException { - if (file.getKey() == null) { - return new FileOutputStream(file); - } else { - try { - IvParameterSpec ips = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.DECRYPT_MODE, file.getKey(), ips); - Log.d(Config.LOGTAG, "opening encrypted output stream"); - return new CipherOutputStream(new FileOutputStream(file), - cipher); - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); - return null; - } catch (NoSuchPaddingException e) { - Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); - return null; - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); - return null; - } catch (InvalidAlgorithmParameterException e) { - Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); - return null; - } - } - } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java b/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java index 19fd4d97..a6df50a5 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java +++ b/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java @@ -1,7 +1,9 @@ package eu.siacs.conversations.xmpp.jingle; +import eu.siacs.conversations.DownloadableFile; + public interface OnFileTransmissionStatusChanged { - public void onFileTransmitted(JingleFile file); + public void onFileTransmitted(DownloadableFile file); public void onFileTransferAborted(); } diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java index d19e6dfd..e74d8965 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java +++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java @@ -1,7 +1,7 @@ package eu.siacs.conversations.xmpp.jingle.stanzas; +import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.jingle.JingleFile; public class Content extends Element { @@ -25,7 +25,7 @@ public class Content extends Element { this.transportId = sid; } - public void setFileOffer(JingleFile actualFile, boolean otr) { + public void setFileOffer(DownloadableFile actualFile, boolean otr) { Element description = this.addChild("description", "urn:xmpp:jingle:apps:file-transfer:3"); Element offer = description.addChild("offer"); -- cgit v1.2.3 From 4fdc6b2eac103183f452269ec028bc44b3dce6f6 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 12:02:48 +0200 Subject: renaming --- .../conversations/AbstractConnectionManager.java | 25 ---- src/eu/siacs/conversations/DownloadableFile.java | 148 -------------------- src/eu/siacs/conversations/crypto/PgpEngine.java | 2 +- .../conversations/entities/DownloadableFile.java | 149 +++++++++++++++++++++ .../siacs/conversations/http/HttpConnection.java | 2 +- .../conversations/http/HttpConnectionManager.java | 2 +- .../conversations/persistance/FileBackend.java | 2 +- .../services/AbstractConnectionManager.java | 24 ++++ .../ui/ConferenceDetailsActivity.java | 46 +++---- .../conversations/ui/ConversationActivity.java | 8 +- .../xmpp/jingle/JingleConnection.java | 2 +- .../xmpp/jingle/JingleConnectionManager.java | 2 +- .../xmpp/jingle/JingleInbandTransport.java | 2 +- .../xmpp/jingle/JingleSocks5Transport.java | 2 +- .../conversations/xmpp/jingle/JingleTransport.java | 2 +- .../jingle/OnFileTransmissionStatusChanged.java | 2 +- .../conversations/xmpp/jingle/stanzas/Content.java | 2 +- 17 files changed, 209 insertions(+), 213 deletions(-) delete mode 100644 src/eu/siacs/conversations/AbstractConnectionManager.java delete mode 100644 src/eu/siacs/conversations/DownloadableFile.java create mode 100644 src/eu/siacs/conversations/entities/DownloadableFile.java create mode 100644 src/eu/siacs/conversations/services/AbstractConnectionManager.java (limited to 'src') diff --git a/src/eu/siacs/conversations/AbstractConnectionManager.java b/src/eu/siacs/conversations/AbstractConnectionManager.java deleted file mode 100644 index f2c937ab..00000000 --- a/src/eu/siacs/conversations/AbstractConnectionManager.java +++ /dev/null @@ -1,25 +0,0 @@ -package eu.siacs.conversations; - -import eu.siacs.conversations.services.XmppConnectionService; - -public class AbstractConnectionManager { - protected XmppConnectionService mXmppConnectionService; - - public AbstractConnectionManager(XmppConnectionService service) { - this.mXmppConnectionService = service; - } - - public XmppConnectionService getXmppConnectionService() { - return this.mXmppConnectionService; - } - - public long getAutoAcceptFileSize() { - String config = this.mXmppConnectionService.getPreferences().getString( - "auto_accept_file_size", "524288"); - try { - return Long.parseLong(config); - } catch (NumberFormatException e) { - return 524288; - } - } -} diff --git a/src/eu/siacs/conversations/DownloadableFile.java b/src/eu/siacs/conversations/DownloadableFile.java deleted file mode 100644 index c8097df8..00000000 --- a/src/eu/siacs/conversations/DownloadableFile.java +++ /dev/null @@ -1,148 +0,0 @@ -package eu.siacs.conversations; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import eu.siacs.conversations.utils.CryptoHelper; -import android.util.Log; - -public class DownloadableFile extends File { - - private static final long serialVersionUID = 2247012619505115863L; - - private long expectedSize = 0; - private String sha1sum; - private Key aeskey; - - private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; - - public DownloadableFile(String path) { - super(path); - } - - public long getSize() { - return super.length(); - } - - public long getExpectedSize() { - if (this.aeskey != null) { - return (this.expectedSize / 16 + 1) * 16; - } else { - return this.expectedSize; - } - } - - public void setExpectedSize(long size) { - this.expectedSize = size; - } - - public String getSha1Sum() { - return this.sha1sum; - } - - public void setSha1Sum(String sum) { - this.sha1sum = sum; - } - - public void setKey(byte[] key) { - if (key.length >= 32) { - byte[] secretKey = new byte[32]; - System.arraycopy(key, 0, secretKey, 0, 32); - this.aeskey = new SecretKeySpec(secretKey, "AES"); - } else if (key.length >= 16) { - byte[] secretKey = new byte[16]; - System.arraycopy(key, 0, secretKey, 0, 16); - this.aeskey = new SecretKeySpec(secretKey, "AES"); - } else { - Log.d(Config.LOGTAG, "weird key"); - } - Log.d(Config.LOGTAG, - "using aes key " - + CryptoHelper.bytesToHex(this.aeskey.getEncoded())); - } - - public Key getKey() { - return this.aeskey; - } - - public InputStream createInputStream() { - if (this.getKey() == null) { - try { - return new FileInputStream(this); - } catch (FileNotFoundException e) { - return null; - } - } else { - try { - IvParameterSpec ips = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.ENCRYPT_MODE, this.getKey(), ips); - Log.d(Config.LOGTAG, "opening encrypted input stream"); - return new CipherInputStream(new FileInputStream(this), cipher); - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); - return null; - } catch (NoSuchPaddingException e) { - Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); - return null; - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); - return null; - } catch (InvalidAlgorithmParameterException e) { - Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); - return null; - } catch (FileNotFoundException e) { - return null; - } - } - } - - public OutputStream createOutputStream() { - if (this.getKey() == null) { - try { - return new FileOutputStream(this); - } catch (FileNotFoundException e) { - return null; - } - } else { - try { - IvParameterSpec ips = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.DECRYPT_MODE, this.getKey(), ips); - Log.d(Config.LOGTAG, "opening encrypted output stream"); - return new CipherOutputStream(new FileOutputStream(this), - cipher); - } catch (NoSuchAlgorithmException e) { - Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); - return null; - } catch (NoSuchPaddingException e) { - Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); - return null; - } catch (InvalidKeyException e) { - Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); - return null; - } catch (InvalidAlgorithmParameterException e) { - Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); - return null; - } catch (FileNotFoundException e) { - return null; - } - } - } -} diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index d83a210d..9eab7b6d 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -15,11 +15,11 @@ import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback; import eu.siacs.conversations.Config; -import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.UiCallback; diff --git a/src/eu/siacs/conversations/entities/DownloadableFile.java b/src/eu/siacs/conversations/entities/DownloadableFile.java new file mode 100644 index 00000000..14afc826 --- /dev/null +++ b/src/eu/siacs/conversations/entities/DownloadableFile.java @@ -0,0 +1,149 @@ +package eu.siacs.conversations.entities; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.CryptoHelper; +import android.util.Log; + +public class DownloadableFile extends File { + + private static final long serialVersionUID = 2247012619505115863L; + + private long expectedSize = 0; + private String sha1sum; + private Key aeskey; + + private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; + + public DownloadableFile(String path) { + super(path); + } + + public long getSize() { + return super.length(); + } + + public long getExpectedSize() { + if (this.aeskey != null) { + return (this.expectedSize / 16 + 1) * 16; + } else { + return this.expectedSize; + } + } + + public void setExpectedSize(long size) { + this.expectedSize = size; + } + + public String getSha1Sum() { + return this.sha1sum; + } + + public void setSha1Sum(String sum) { + this.sha1sum = sum; + } + + public void setKey(byte[] key) { + if (key.length >= 32) { + byte[] secretKey = new byte[32]; + System.arraycopy(key, 0, secretKey, 0, 32); + this.aeskey = new SecretKeySpec(secretKey, "AES"); + } else if (key.length >= 16) { + byte[] secretKey = new byte[16]; + System.arraycopy(key, 0, secretKey, 0, 16); + this.aeskey = new SecretKeySpec(secretKey, "AES"); + } else { + Log.d(Config.LOGTAG, "weird key"); + } + Log.d(Config.LOGTAG, + "using aes key " + + CryptoHelper.bytesToHex(this.aeskey.getEncoded())); + } + + public Key getKey() { + return this.aeskey; + } + + public InputStream createInputStream() { + if (this.getKey() == null) { + try { + return new FileInputStream(this); + } catch (FileNotFoundException e) { + return null; + } + } else { + try { + IvParameterSpec ips = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, this.getKey(), ips); + Log.d(Config.LOGTAG, "opening encrypted input stream"); + return new CipherInputStream(new FileInputStream(this), cipher); + } catch (NoSuchAlgorithmException e) { + Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); + return null; + } catch (NoSuchPaddingException e) { + Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); + return null; + } catch (InvalidKeyException e) { + Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); + return null; + } catch (InvalidAlgorithmParameterException e) { + Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); + return null; + } catch (FileNotFoundException e) { + return null; + } + } + } + + public OutputStream createOutputStream() { + if (this.getKey() == null) { + try { + return new FileOutputStream(this); + } catch (FileNotFoundException e) { + return null; + } + } else { + try { + IvParameterSpec ips = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, this.getKey(), ips); + Log.d(Config.LOGTAG, "opening encrypted output stream"); + return new CipherOutputStream(new FileOutputStream(this), + cipher); + } catch (NoSuchAlgorithmException e) { + Log.d(Config.LOGTAG, "no such algo: " + e.getMessage()); + return null; + } catch (NoSuchPaddingException e) { + Log.d(Config.LOGTAG, "no such padding: " + e.getMessage()); + return null; + } catch (InvalidKeyException e) { + Log.d(Config.LOGTAG, "invalid key: " + e.getMessage()); + return null; + } catch (InvalidAlgorithmParameterException e) { + Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage()); + return null; + } catch (FileNotFoundException e) { + return null; + } + } + } +} diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index d3b1700b..003007d8 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -12,8 +12,8 @@ import javax.net.ssl.HttpsURLConnection; import android.util.Log; import eu.siacs.conversations.Config; -import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; diff --git a/src/eu/siacs/conversations/http/HttpConnectionManager.java b/src/eu/siacs/conversations/http/HttpConnectionManager.java index ee50ef7e..4d6dce12 100644 --- a/src/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/eu/siacs/conversations/http/HttpConnectionManager.java @@ -3,8 +3,8 @@ package eu.siacs.conversations.http; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import eu.siacs.conversations.AbstractConnectionManager; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; public class HttpConnectionManager extends AbstractConnectionManager { diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 8d5046ab..c8ae657d 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -30,9 +30,9 @@ import android.util.Base64OutputStream; import android.util.Log; import android.util.LruCache; import eu.siacs.conversations.Config; -import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.ImageProvider; import eu.siacs.conversations.utils.CryptoHelper; diff --git a/src/eu/siacs/conversations/services/AbstractConnectionManager.java b/src/eu/siacs/conversations/services/AbstractConnectionManager.java new file mode 100644 index 00000000..a06be826 --- /dev/null +++ b/src/eu/siacs/conversations/services/AbstractConnectionManager.java @@ -0,0 +1,24 @@ +package eu.siacs.conversations.services; + + +public class AbstractConnectionManager { + protected XmppConnectionService mXmppConnectionService; + + public AbstractConnectionManager(XmppConnectionService service) { + this.mXmppConnectionService = service; + } + + public XmppConnectionService getXmppConnectionService() { + return this.mXmppConnectionService; + } + + public long getAutoAcceptFileSize() { + String config = this.mXmppConnectionService.getPreferences().getString( + "auto_accept_file_size", "524288"); + try { + return Long.parseLong(config); + } catch (NumberFormatException e) { + return 524288; + } + } +} diff --git a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 589268ee..deddcad7 100644 --- a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -171,33 +171,31 @@ public class ConferenceDetailsActivity extends XmppActivity { } protected void registerListener() { - if (xmppConnectionServiceBound) { - xmppConnectionService - .setOnConversationListChangedListener(this.onConvChanged); - xmppConnectionService.setOnRenameListener(new OnRenameListener() { + xmppConnectionService + .setOnConversationListChangedListener(this.onConvChanged); + xmppConnectionService.setOnRenameListener(new OnRenameListener() { - @Override - public void onRename(final boolean success) { - runOnUiThread(new Runnable() { + @Override + public void onRename(final boolean success) { + runOnUiThread(new Runnable() { - @Override - public void run() { - populateView(); - if (success) { - Toast.makeText( - ConferenceDetailsActivity.this, - getString(R.string.your_nick_has_been_changed), - Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(ConferenceDetailsActivity.this, - getString(R.string.nick_in_use), - Toast.LENGTH_SHORT).show(); - } + @Override + public void run() { + populateView(); + if (success) { + Toast.makeText( + ConferenceDetailsActivity.this, + getString(R.string.your_nick_has_been_changed), + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(ConferenceDetailsActivity.this, + getString(R.string.nick_in_use), + Toast.LENGTH_SHORT).show(); } - }); - } - }); - } + } + }); + } + }); } private void populateView() { diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index ad1cd283..3d4cffee 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -736,11 +736,9 @@ public class ConversationActivity extends XmppActivity implements } public void registerListener() { - if (xmppConnectionServiceBound) { - xmppConnectionService.setOnConversationListChangedListener(this); - xmppConnectionService.setOnAccountListChangedListener(this); - xmppConnectionService.setOnRosterUpdateListener(this); - } + xmppConnectionService.setOnConversationListChangedListener(this); + xmppConnectionService.setOnAccountListChangedListener(this); + xmppConnectionService.setOnRosterUpdateListener(this); } @Override diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 4dac54f6..4853d75c 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -13,10 +13,10 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.util.Log; import eu.siacs.conversations.Config; -import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 93b03ff8..bb360204 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -7,10 +7,10 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import android.annotation.SuppressLint; import android.util.Log; -import eu.siacs.conversations.AbstractConnectionManager; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java index ed64c24a..e5016935 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java @@ -8,8 +8,8 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import android.util.Base64; -import eu.siacs.conversations.DownloadableFile; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java index ec6b2c24..f1dd1e51 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -10,7 +10,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import eu.siacs.conversations.DownloadableFile; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.utils.CryptoHelper; public class JingleSocks5Transport extends JingleTransport { diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java index 185018e6..1374e61c 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java @@ -1,6 +1,6 @@ package eu.siacs.conversations.xmpp.jingle; -import eu.siacs.conversations.DownloadableFile; +import eu.siacs.conversations.entities.DownloadableFile; public abstract class JingleTransport { public abstract void connect(final OnTransportConnected callback); diff --git a/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java b/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java index a6df50a5..e45e7441 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java +++ b/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java @@ -1,6 +1,6 @@ package eu.siacs.conversations.xmpp.jingle; -import eu.siacs.conversations.DownloadableFile; +import eu.siacs.conversations.entities.DownloadableFile; public interface OnFileTransmissionStatusChanged { public void onFileTransmitted(DownloadableFile file); diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java index e74d8965..bcadbe77 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java +++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java @@ -1,6 +1,6 @@ package eu.siacs.conversations.xmpp.jingle.stanzas; -import eu.siacs.conversations.DownloadableFile; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.xml.Element; public class Content extends Element { -- cgit v1.2.3 From c18e986a93d7a36769b6fdecdcea154c7b3d2024 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 16:25:59 +0200 Subject: fixed rare npe --- src/eu/siacs/conversations/entities/Account.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java index eacd172c..9b1cbcab 100644 --- a/src/eu/siacs/conversations/entities/Account.java +++ b/src/eu/siacs/conversations/entities/Account.java @@ -160,8 +160,12 @@ public class Account extends AbstractEntity { } public boolean hasErrorStatus() { - return getStatus() > STATUS_NO_INTERNET - && (getXmppConnection().getAttempt() >= 2); + if (getXmppConnection() == null) { + return false; + } else { + return getStatus() > STATUS_NO_INTERNET + && (getXmppConnection().getAttempt() >= 2); + } } public void setResource(String resource) { -- cgit v1.2.3 From 470410b389bc38ab22fe5f877149c93795c5b0fb Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 17:14:07 +0200 Subject: possible work around for notification bug --- .../conversations/services/XmppConnectionService.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 3549ce0a..0dda4b31 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -975,6 +975,10 @@ public class XmppConnectionService extends Service { public void setOnConversationListChangedListener( OnConversationUpdate listener) { + if (!isScreenOn()) { + Log.d(Config.LOGTAG,"ignoring setOnConversationListChangedListener"); + return; + } this.mNotificationService.deactivateGracePeriod(); if (checkListeners()) { switchToForeground(); @@ -996,6 +1000,10 @@ public class XmppConnectionService extends Service { } public void setOnAccountListChangedListener(OnAccountUpdate listener) { + if (!isScreenOn()) { + Log.d(Config.LOGTAG,"ignoring setOnAccountListChangedListener"); + return; + } this.mNotificationService.deactivateGracePeriod(); if (checkListeners()) { switchToForeground(); @@ -1015,6 +1023,10 @@ public class XmppConnectionService extends Service { } public void setOnRosterUpdateListener(OnRosterUpdate listener) { + if (!isScreenOn()) { + Log.d(Config.LOGTAG,"ignoring setOnRosterUpdateListener"); + return; + } this.mNotificationService.deactivateGracePeriod(); if (checkListeners()) { switchToForeground(); @@ -1063,6 +1075,11 @@ public class XmppConnectionService extends Service { } } } + + private boolean isScreenOn() { + PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE); + return pm.isScreenOn(); + } public void connectMultiModeConversations(Account account) { List conversations = getConversations(); -- cgit v1.2.3 From e98460771bac4e2252556ea6cf483c93a1ecf176 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 18:16:03 +0200 Subject: read image bounds on downloaded image --- src/eu/siacs/conversations/crypto/PgpEngine.java | 4 +- src/eu/siacs/conversations/entities/Message.java | 65 +++++++++++++++++++++- .../siacs/conversations/http/HttpConnection.java | 25 +++++++-- .../services/XmppConnectionService.java | 1 + .../conversations/ui/adapter/MessageAdapter.java | 39 ++++++------- 5 files changed, 103 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index 9eab7b6d..c70f0907 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -110,9 +110,7 @@ public class PgpEngine { + ',' + imageWidth + ',' + imageHeight); message.setEncryption(Message.ENCRYPTION_DECRYPTED); PgpEngine.this.mXmppConnectionService - .updateMessage(message); - PgpEngine.this.mXmppConnectionService - .updateConversationUi(); + .updateMessage(message);; callback.success(message); return; case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index b459510c..863288bb 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -9,12 +9,12 @@ import eu.siacs.conversations.R; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; -import android.text.InputFilter.LengthFilter; public class Message extends AbstractEntity { public static final String TABLENAME = "messages"; + public static final int STATUS_RECEIVED_CHECKING = -4; public static final int STATUS_RECEPTION_FAILED = -3; public static final int STATUS_RECEIVED_OFFER = -2; public static final int STATUS_RECEIVING = -1; @@ -396,4 +396,67 @@ public class Message extends AbstractEntity { return false; } } + + public ImageParams getImageParams() { + ImageParams params = new ImageParams(); + if (body==null) { + return params; + } + String parts[] = body.split(","); + if (parts.length==1) { + try { + params.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + params.origin = parts[0]; + } + } else if (parts.length == 2) { + params.origin = parts[0]; + try { + params.size = Long.parseLong(parts[1]); + } catch (NumberFormatException e) { + params.size = 0; + } + } else if (parts.length==3) { + try { + params.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + params.size = 0; + } + try { + params.width = Integer.parseInt(parts[1]); + } catch (NumberFormatException e) { + params.width = 0; + } + try { + params.height = Integer.parseInt(parts[2]); + } catch (NumberFormatException e) { + params.height = 0; + } + } else if (parts.length == 4) { + params.origin = parts[0]; + try { + params.size = Long.parseLong(parts[1]); + } catch (NumberFormatException e) { + params.size = 0; + } + try { + params.width = Integer.parseInt(parts[2]); + } catch (NumberFormatException e) { + params.width = 0; + } + try { + params.height = Integer.parseInt(parts[3]); + } catch (NumberFormatException e) { + params.height = 0; + } + } + return params; + } + + public class ImageParams { + public long size = 0; + public int width = 0; + public int height = 0; + public String origin; + } } diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 003007d8..7ed98136 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -9,6 +9,7 @@ import java.net.URL; import javax.net.ssl.HttpsURLConnection; +import android.graphics.BitmapFactory; import android.util.Log; import eu.siacs.conversations.Config; @@ -43,7 +44,7 @@ public class HttpConnection implements Downloadable { mUrl = new URL(message.getBody()); this.file = mXmppConnectionService.getFileBackend().getConversationsFile(message,false); message.setType(Message.TYPE_IMAGE); - mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED_OFFER); + mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED_CHECKING); checkFileSize(); } catch (MalformedURLException e) { this.cancel(); @@ -66,10 +67,14 @@ public class HttpConnection implements Downloadable { try { long size = retrieveFileSize(); file.setExpectedSize(size); + message.setBody(mUrl.toString()+","+String.valueOf(size)); if (size <= mHttpConnectionManager.getAutoAcceptFileSize()) { + mXmppConnectionService.updateMessage(message); start(); + } else { + message.setStatus(Message.STATUS_RECEIVED_OFFER); + mXmppConnectionService.updateMessage(message); } - Log.d(Config.LOGTAG,"file size: "+size); } catch (IOException e) { cancel(); } @@ -101,7 +106,9 @@ public class HttpConnection implements Downloadable { try { mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVING); download(); - mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED); + updateImageBounds(); + message.setStatus(Message.STATUS_RECEIVED); + mXmppConnectionService.updateMessage(message); } catch (IOException e) { cancel(); } @@ -122,7 +129,17 @@ public class HttpConnection implements Downloadable { os.flush(); os.close(); is.close(); - Log.d(Config.LOGTAG,"finished downloading "+file.getAbsolutePath().toString()); + } + + private void updateImageBounds() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + int imageHeight = options.outHeight; + int imageWidth = options.outWidth; + message.setBody(mUrl.toString()+","+file.getSize() + ',' + + imageWidth + ',' + imageHeight); + } } diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 0dda4b31..5b0d9ea5 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1249,6 +1249,7 @@ public class XmppConnectionService extends Service { public void updateMessage(Message message) { databaseBackend.updateMessage(message); + updateConversationUi(); } protected void syncDirtyContacts(Account account) { diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index dbf2184b..581a410c 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -9,6 +9,7 @@ import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.utils.UIHelper; import android.content.Context; @@ -102,13 +103,7 @@ public class MessageAdapter extends ArrayAdapter { boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI && message.getMergedStatus() <= Message.STATUS_RECEIVED; if (message.getType() == Message.TYPE_IMAGE) { - String[] fileParams = message.getBody().split(","); - try { - long size = Long.parseLong(fileParams[0]); - filesize = size / 1024 + " KB"; - } catch (NumberFormatException e) { - filesize = "0 KB"; - } + filesize = message.getImageParams().size / 1024 + " KB"; } switch (message.getMergedStatus()) { case Message.STATUS_WAITING: @@ -275,23 +270,19 @@ public class MessageAdapter extends ArrayAdapter { } viewHolder.messageBody.setVisibility(View.GONE); viewHolder.image.setVisibility(View.VISIBLE); - String[] fileParams = message.getBody().split(","); - if (fileParams.length == 3) { - double target = metrics.density * 288; - int w = Integer.parseInt(fileParams[1]); - int h = Integer.parseInt(fileParams[2]); - int scalledW; - int scalledH; - if (w <= h) { - scalledW = (int) (w / ((double) h / target)); - scalledH = (int) target; - } else { - scalledW = (int) target; - scalledH = (int) (h / ((double) w / target)); - } - viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams( - scalledW, scalledH)); + ImageParams params = message.getImageParams(); + double target = metrics.density * 288; + int scalledW; + int scalledH; + if (params.width <= params.height) { + scalledW = (int) (params.width / ((double) params.height / target)); + scalledH = (int) target; + } else { + scalledW = (int) target; + scalledH = (int) (params.height / ((double) params.width / target)); } + viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams( + scalledW, scalledH)); activity.loadBitmap(message, viewHolder.image); viewHolder.image.setOnClickListener(new OnClickListener() { @@ -481,6 +472,8 @@ public class MessageAdapter extends ArrayAdapter { if (item.getType() == Message.TYPE_IMAGE) { if (item.getStatus() == Message.STATUS_RECEIVING) { displayInfoMessage(viewHolder, R.string.receiving_image); + } else if (item.getStatus() == Message.STATUS_RECEIVED_CHECKING) { + displayInfoMessage(viewHolder, R.string.checking_image); } else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) { viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); -- cgit v1.2.3 From 031b739af8122e0c6a2926c3f9db78e207560f64 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 18:26:45 +0200 Subject: catch can't open database exception --- src/eu/siacs/conversations/persistance/DatabaseBackend.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java index 0991dd2d..091c00bd 100644 --- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -11,6 +11,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Roster; import android.content.Context; import android.database.Cursor; +import android.database.sqlite.SQLiteCantOpenDatabaseException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; @@ -231,10 +232,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("select count(" + Account.UUID + ") from " + Account.TABLENAME + " where not options & (1 <<1)", null); - cursor.moveToFirst(); - int count = cursor.getInt(0); - cursor.close(); - return (count > 0); + try { + cursor.moveToFirst(); + int count = cursor.getInt(0); + cursor.close(); + return (count > 0); + } catch (SQLiteCantOpenDatabaseException e) { + return true; //better safe than sorry + } } @Override -- cgit v1.2.3 From 262128c8f9152330b61bc5b4358337ff2fd0fdcf Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 19:27:49 +0200 Subject: recreate http connection after restart. fixes stale download button. better failing --- .../siacs/conversations/http/HttpConnection.java | 51 +++++++++++++++------- .../conversations/http/HttpConnectionManager.java | 14 +++++- .../conversations/ui/ConversationActivity.java | 5 +++ .../conversations/ui/adapter/MessageAdapter.java | 51 ++++++++++++++++++---- 4 files changed, 95 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 7ed98136..ff8037fb 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -10,9 +10,7 @@ import java.net.URL; import javax.net.ssl.HttpsURLConnection; import android.graphics.BitmapFactory; -import android.util.Log; -import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; @@ -26,6 +24,7 @@ public class HttpConnection implements Downloadable { private URL mUrl; private Message message; private DownloadableFile file; + private long mPreviousFileSize = Long.MIN_VALUE; public HttpConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; @@ -44,39 +43,60 @@ public class HttpConnection implements Downloadable { mUrl = new URL(message.getBody()); this.file = mXmppConnectionService.getFileBackend().getConversationsFile(message,false); message.setType(Message.TYPE_IMAGE); - mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED_CHECKING); + message.setStatus(Message.STATUS_RECEIVED_CHECKING); + mXmppConnectionService.updateConversationUi(); checkFileSize(); } catch (MalformedURLException e) { this.cancel(); } } + public void init(Message message, URL url) { + this.message = message; + this.message.setDownloadable(this); + this.mUrl = url; + this.file = mXmppConnectionService.getFileBackend().getConversationsFile(message,false); + this.mPreviousFileSize = message.getImageParams().size; + message.setType(Message.TYPE_IMAGE); + message.setStatus(Message.STATUS_RECEIVED_CHECKING); + mXmppConnectionService.updateConversationUi(); + checkFileSize(); + } + private void checkFileSize() { new Thread(new FileSizeChecker()).start(); } public void cancel() { mXmppConnectionService.markMessage(message, Message.STATUS_RECEPTION_FAILED); - Log.d(Config.LOGTAG,"canceled download"); + mHttpConnectionManager.finishConnection(this); + } + + private void finish() { + message.setStatus(Message.STATUS_RECEIVED); + mXmppConnectionService.updateMessage(message); + mHttpConnectionManager.finishConnection(this); } private class FileSizeChecker implements Runnable { @Override public void run() { + long size; try { - long size = retrieveFileSize(); - file.setExpectedSize(size); - message.setBody(mUrl.toString()+","+String.valueOf(size)); - if (size <= mHttpConnectionManager.getAutoAcceptFileSize()) { - mXmppConnectionService.updateMessage(message); - start(); - } else { - message.setStatus(Message.STATUS_RECEIVED_OFFER); - mXmppConnectionService.updateMessage(message); - } + size = retrieveFileSize(); } catch (IOException e) { cancel(); + return; + } + file.setExpectedSize(size); + message.setBody(mUrl.toString()+","+String.valueOf(size)); + if (size <= mHttpConnectionManager.getAutoAcceptFileSize() || size == mPreviousFileSize) { + mXmppConnectionService.updateMessage(message); + start(); + } else { + message.setStatus(Message.STATUS_RECEIVED_OFFER); + mXmppConnectionService.updateMessage(message); } } @@ -107,8 +127,7 @@ public class HttpConnection implements Downloadable { mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVING); download(); updateImageBounds(); - message.setStatus(Message.STATUS_RECEIVED); - mXmppConnectionService.updateMessage(message); + finish(); } catch (IOException e) { cancel(); } diff --git a/src/eu/siacs/conversations/http/HttpConnectionManager.java b/src/eu/siacs/conversations/http/HttpConnectionManager.java index 4d6dce12..7393cf36 100644 --- a/src/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/eu/siacs/conversations/http/HttpConnectionManager.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.http; +import java.net.URL; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -12,8 +13,6 @@ public class HttpConnectionManager extends AbstractConnectionManager { public HttpConnectionManager(XmppConnectionService service) { super(service); } - - private XmppConnectionService mXmppConnectionService; private List connections = new CopyOnWriteArrayList(); @@ -24,4 +23,15 @@ public class HttpConnectionManager extends AbstractConnectionManager { this.connections.add(connection); return connection; } + + public HttpConnection createNewConnection(Message message, URL url) { + HttpConnection connection = new HttpConnection(this); + connection.init(message,url); + this.connections.add(connection); + return connection; + } + + public void finishConnection(HttpConnection connection) { + this.connections.remove(connection); + } } diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 3d4cffee..984bf7c9 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -1,12 +1,17 @@ package eu.siacs.conversations.ui; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; import java.util.ArrayList; import java.util.List; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 581a410c..028ab002 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.ui.adapter; +import java.net.MalformedURLException; +import java.net.URL; import java.util.HashMap; import java.util.List; @@ -225,10 +227,19 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.messageBody.setVisibility(View.VISIBLE); if (message.getBody() != null) { if (message.getType() != Message.TYPE_PRIVATE) { - String body = Config.PARSE_EMOTICONS ? UIHelper - .transformAsciiEmoticons(message.getMergedBody()) - : message.getMergedBody(); - viewHolder.messageBody.setText(body); + if (message.getType() == Message.TYPE_IMAGE) { + String orign = message.getImageParams().origin; + if (orign!=null) { + viewHolder.messageBody.setText(orign); + } else { + viewHolder.messageBody.setText(message.getBody()); + } + } else { + String body = Config.PARSE_EMOTICONS ? UIHelper + .transformAsciiEmoticons(message.getMergedBody()) + : message.getMergedBody(); + viewHolder.messageBody.setText(body); + } } else { String privateMarker; if (message.getStatus() <= Message.STATUS_RECEIVED) { @@ -474,6 +485,8 @@ public class MessageAdapter extends ArrayAdapter { displayInfoMessage(viewHolder, R.string.receiving_image); } else if (item.getStatus() == Message.STATUS_RECEIVED_CHECKING) { displayInfoMessage(viewHolder, R.string.checking_image); + } else if (item.getStatus() == Message.STATUS_RECEPTION_FAILED) { + displayTextMessage(viewHolder, item); } else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) { viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); @@ -483,10 +496,10 @@ public class MessageAdapter extends ArrayAdapter { @Override public void onClick(View v) { - Downloadable downloadable = item - .getDownloadable(); - if (downloadable != null) { - downloadable.start(); + if (!startDonwloadable(item)) { + activity.xmppConnectionService.markMessage( + item, + Message.STATUS_RECEPTION_FAILED); } } }); @@ -527,6 +540,28 @@ public class MessageAdapter extends ArrayAdapter { return view; } + public boolean startDonwloadable(Message message) { + Downloadable downloadable = message.getDownloadable(); + if (downloadable != null) { + downloadable.start(); + return true; + } else { + ImageParams params = message.getImageParams(); + if (params.origin != null) { + try { + URL url = new URL(params.origin); + activity.xmppConnectionService.getHttpConnectionManager() + .createNewConnection(message, url); + return true; + } catch (MalformedURLException e) { + return false; + } + } else { + return false; + } + } + } + private static class ViewHolder { protected LinearLayout message_box; -- cgit v1.2.3 From 3c557a1bb409649bfa5b07cbb4f549d92e312c32 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 14 Oct 2014 19:33:35 +0200 Subject: don't show invalid file size --- src/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 028ab002..b09f97fc 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -105,7 +105,10 @@ public class MessageAdapter extends ArrayAdapter { boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI && message.getMergedStatus() <= Message.STATUS_RECEIVED; if (message.getType() == Message.TYPE_IMAGE) { - filesize = message.getImageParams().size / 1024 + " KB"; + ImageParams params = message.getImageParams(); + if (params.size != 0) { + filesize = params.size / 1024 + " KB"; + } } switch (message.getMergedStatus()) { case Message.STATUS_WAITING: -- cgit v1.2.3 From d09739d1660efb6da17b47e94ca7cc667a4a1ba5 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 15 Oct 2014 02:09:20 +0200 Subject: changed pgp decoding mechanism --- src/eu/siacs/conversations/crypto/PgpEngine.java | 2 +- .../conversations/ui/ConversationActivity.java | 6 +- .../conversations/ui/ConversationFragment.java | 75 +++++++++++++--------- 3 files changed, 47 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index c70f0907..07e8e472 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -76,7 +76,7 @@ public class PgpEngine { case OpenPgpApi.RESULT_CODE_ERROR: OpenPgpError error = result .getParcelableExtra(OpenPgpApi.RESULT_ERROR); - Log.d(Config.LOGTAG, error.getMessage()); + Log.d(Config.LOGTAG,"openpgp error: "+error.getMessage()); callback.error(R.string.openpgp_error, message); return; default: diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 984bf7c9..40739387 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -1,17 +1,12 @@ package eu.siacs.conversations.ui; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; import java.util.ArrayList; import java.util.List; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; @@ -756,6 +751,7 @@ public class ConversationActivity extends XmppActivity implements .findFragmentByTag("conversation"); if (selectedFragment != null) { selectedFragment.hideSnackbar(); + selectedFragment.updateMessages(); } } else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) { pendingImageUri = data.getData(); diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index cdaa7152..75f1dac8 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.ui; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; import net.java.otr4j.session.SessionStatus; import eu.siacs.conversations.R; @@ -71,6 +72,10 @@ public class ConversationFragment extends Fragment { private boolean messagesLoaded = false; private IntentSender askForPassphraseIntent = null; + + + private ConcurrentLinkedQueue mEncryptedMessages = new ConcurrentLinkedQueue(); + private boolean mDecryptJobRunning = false; private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() { @@ -356,6 +361,7 @@ public class ConversationFragment extends Fragment { @Override public void onStop() { + mDecryptJobRunning = false; super.onStop(); if (this.conversation != null) { this.conversation.setNextMessage(mEditMessage.getText().toString()); @@ -395,34 +401,6 @@ public class ConversationFragment extends Fragment { updateMessages(); } - private void decryptMessage(Message message) { - PgpEngine engine = activity.xmppConnectionService.getPgpEngine(); - if (engine != null) { - engine.decrypt(message, new UiCallback() { - - @Override - public void userInputRequried(PendingIntent pi, Message message) { - askForPassphraseIntent = pi.getIntentSender(); - showSnackbar(R.string.openpgp_messages_found, - R.string.decrypt, clickToDecryptListener); - } - - @Override - public void success(Message message) { - activity.xmppConnectionService.databaseBackend - .updateMessage(message); - updateMessages(); - } - - @Override - public void error(int error, Message message) { - message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED); - // updateMessages(); - } - }); - } - } - public void updateMessages() { if (getView() == null) { return; @@ -461,10 +439,12 @@ public class ConversationFragment extends Fragment { if ((message.getEncryption() == Message.ENCRYPTION_PGP) && ((message.getStatus() == Message.STATUS_RECEIVED) || (message .getStatus() == Message.STATUS_SEND))) { - decryptMessage(message); - break; + if (!mEncryptedMessages.contains(message)) { + mEncryptedMessages.add(message); + } } } + decryptNext(); this.messageList.clear(); if (this.conversation.getMessages().size() == 0) { messagesLoaded = false; @@ -522,6 +502,41 @@ public class ConversationFragment extends Fragment { } } + private void decryptNext() { + Message next = this.mEncryptedMessages.peek(); + PgpEngine engine = activity.xmppConnectionService.getPgpEngine(); + + if (next!=null && engine != null && !mDecryptJobRunning) { + mDecryptJobRunning = true; + engine.decrypt(next, new UiCallback() { + + @Override + public void userInputRequried(PendingIntent pi, Message message) { + mDecryptJobRunning = false; + askForPassphraseIntent = pi.getIntentSender(); + showSnackbar(R.string.openpgp_messages_found, + R.string.decrypt, clickToDecryptListener); + } + + @Override + public void success(Message message) { + mDecryptJobRunning = false; + mEncryptedMessages.remove(); + activity.xmppConnectionService.updateMessage(message); + } + + @Override + public void error(int error, Message message) { + message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED); + mDecryptJobRunning = false; + mEncryptedMessages.remove(); + activity.updateConversationList(); + activity.xmppConnectionService.updateConversationUi(); + } + }); + } + } + private void messageSent() { int size = this.messageList.size(); messagesView.setSelection(size - 1); -- cgit v1.2.3 From 1428628a5d2f619ef3c92659395e6c5e117eb098 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 15 Oct 2014 14:32:37 +0200 Subject: removed unecessary update --- src/eu/siacs/conversations/ui/ConversationFragment.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 75f1dac8..4835636d 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -530,7 +530,6 @@ public class ConversationFragment extends Fragment { message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED); mDecryptJobRunning = false; mEncryptedMessages.remove(); - activity.updateConversationList(); activity.xmppConnectionService.updateConversationUi(); } }); -- cgit v1.2.3 From f063b1c063ec25698a2406233e742a1c7b0d9a93 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 15 Oct 2014 14:33:13 +0200 Subject: synchronization for notification --- .../services/NotificationService.java | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 41656707..e65085fb 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -43,34 +43,40 @@ public class NotificationService { .getSystemService(Context.NOTIFICATION_SERVICE); } - public synchronized void push(Message message) { - + public void push(Message message) { PowerManager pm = (PowerManager) mXmppConnectionService .getSystemService(Context.POWER_SERVICE); boolean isScreenOn = pm.isScreenOn(); + if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) { return; } - String conversationUuid = message.getConversationUuid(); - if (notifications.containsKey(conversationUuid)) { - notifications.get(conversationUuid).add(message); - } else { - ArrayList mList = new ArrayList(); - mList.add(message); - notifications.put(conversationUuid, mList); + synchronized (notifications) { + String conversationUuid = message.getConversationUuid(); + if (notifications.containsKey(conversationUuid)) { + notifications.get(conversationUuid).add(message); + } else { + ArrayList mList = new ArrayList(); + mList.add(message); + notifications.put(conversationUuid, mList); + } } updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) && !inGracePeriod()); } public void clear() { - notifications.clear(); + synchronized (notifications) { + notifications.clear(); + } updateNotification(false); } public void clear(Conversation conversation) { - notifications.remove(conversation.getUuid()); + synchronized (notifications) { + notifications.remove(conversation.getUuid()); + } updateNotification(false); } -- cgit v1.2.3 From 9d960f27415c009db0549f309c3e847d9570e1d5 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 15 Oct 2014 14:41:27 +0200 Subject: synchronization for listeners --- .../services/XmppConnectionService.java | 103 ++++++++++++--------- 1 file changed, 60 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 5b0d9ea5..07897f8c 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -107,14 +107,15 @@ public class XmppConnectionService extends Service { private CopyOnWriteArrayList conversations = null; private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager( this); - private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(this); + private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager( + this); private OnConversationUpdate mOnConversationUpdate = null; - private int convChangedListenerCount = 0; + private Integer convChangedListenerCount = 0; private OnAccountUpdate mOnAccountUpdate = null; - private int accountChangedListenerCount = 0; + private Integer accountChangedListenerCount = 0; private OnRosterUpdate mOnRosterUpdate = null; - private int rosterChangedListenerCount = 0; + private Integer rosterChangedListenerCount = 0; public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() { @Override @@ -976,71 +977,87 @@ public class XmppConnectionService extends Service { public void setOnConversationListChangedListener( OnConversationUpdate listener) { if (!isScreenOn()) { - Log.d(Config.LOGTAG,"ignoring setOnConversationListChangedListener"); + Log.d(Config.LOGTAG, + "ignoring setOnConversationListChangedListener"); return; } - this.mNotificationService.deactivateGracePeriod(); - if (checkListeners()) { - switchToForeground(); + synchronized (this.convChangedListenerCount) { + this.mNotificationService.deactivateGracePeriod(); + if (checkListeners()) { + switchToForeground(); + } + this.mOnConversationUpdate = listener; + this.mNotificationService.setIsInForeground(true); + this.convChangedListenerCount++; } - this.mOnConversationUpdate = listener; - this.mNotificationService.setIsInForeground(true); - this.convChangedListenerCount++; } public void removeOnConversationListChangedListener() { - this.convChangedListenerCount--; - if (this.convChangedListenerCount == 0) { - this.mOnConversationUpdate = null; - this.mNotificationService.setIsInForeground(false); - if (checkListeners()) { - switchToBackground(); + synchronized (this.convChangedListenerCount) { + this.convChangedListenerCount--; + if (this.convChangedListenerCount <= 0) { + this.convChangedListenerCount = 0; + this.mOnConversationUpdate = null; + this.mNotificationService.setIsInForeground(false); + if (checkListeners()) { + switchToBackground(); + } } } } public void setOnAccountListChangedListener(OnAccountUpdate listener) { if (!isScreenOn()) { - Log.d(Config.LOGTAG,"ignoring setOnAccountListChangedListener"); + Log.d(Config.LOGTAG, "ignoring setOnAccountListChangedListener"); return; } - this.mNotificationService.deactivateGracePeriod(); - if (checkListeners()) { - switchToForeground(); + synchronized (this.accountChangedListenerCount) { + this.mNotificationService.deactivateGracePeriod(); + if (checkListeners()) { + switchToForeground(); + } + this.mOnAccountUpdate = listener; + this.accountChangedListenerCount++; } - this.mOnAccountUpdate = listener; - this.accountChangedListenerCount++; } public void removeOnAccountListChangedListener() { - this.accountChangedListenerCount--; - if (this.accountChangedListenerCount == 0) { - this.mOnAccountUpdate = null; - if (checkListeners()) { - switchToBackground(); + synchronized (this.accountChangedListenerCount) { + this.accountChangedListenerCount--; + if (this.accountChangedListenerCount <= 0) { + this.mOnAccountUpdate = null; + this.accountChangedListenerCount = 0; + if (checkListeners()) { + switchToBackground(); + } } } } public void setOnRosterUpdateListener(OnRosterUpdate listener) { if (!isScreenOn()) { - Log.d(Config.LOGTAG,"ignoring setOnRosterUpdateListener"); + Log.d(Config.LOGTAG, "ignoring setOnRosterUpdateListener"); return; } - this.mNotificationService.deactivateGracePeriod(); - if (checkListeners()) { - switchToForeground(); + synchronized (this.rosterChangedListenerCount) { + this.mNotificationService.deactivateGracePeriod(); + if (checkListeners()) { + switchToForeground(); + } + this.mOnRosterUpdate = listener; + this.rosterChangedListenerCount++; } - this.mOnRosterUpdate = listener; - this.rosterChangedListenerCount++; } public void removeOnRosterUpdateListener() { - this.rosterChangedListenerCount--; - if (this.rosterChangedListenerCount == 0) { - this.mOnRosterUpdate = null; - if (checkListeners()) { - switchToBackground(); + synchronized (this.rosterChangedListenerCount) { + this.rosterChangedListenerCount--; + if (this.rosterChangedListenerCount <= 0) { + this.rosterChangedListenerCount = 0; + this.mOnRosterUpdate = null; + if (checkListeners()) { + switchToBackground(); + } } } } @@ -1075,9 +1092,10 @@ public class XmppConnectionService extends Service { } } } - + private boolean isScreenOn() { - PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager) this + .getSystemService(Context.POWER_SERVICE); return pm.isScreenOn(); } @@ -1799,8 +1817,7 @@ public class XmppConnectionService extends Service { ArrayList contacts = new ArrayList(); for (Account account : getAccounts()) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { - Contact contact = account.getRoster() - .getContactFromRoster(jid); + Contact contact = account.getRoster().getContactFromRoster(jid); if (contact != null) { contacts.add(contact); } -- cgit v1.2.3 From f021ee85628260b0445f40900415e48d030471b2 Mon Sep 17 00:00:00 2001 From: "M. Dietrich" Date: Wed, 8 Oct 2014 23:23:18 +0200 Subject: remove warning about <> cast --- src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java b/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java index 0534bc25..2b8ee048 100644 --- a/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java @@ -47,11 +47,11 @@ public class KnownHostsAdapter extends ArrayAdapter { @Override protected void publishResults(CharSequence constraint, FilterResults results) { - ArrayList filteredList = (ArrayList) results.values; + ArrayList filteredList = (ArrayList)results.values; if (results != null && results.count > 0) { clear(); - for (String c : filteredList) { - add(c); + for (Object c : filteredList) { + add((String)c); } notifyDataSetChanged(); } @@ -71,4 +71,4 @@ public class KnownHostsAdapter extends ArrayAdapter { public Filter getFilter() { return domainFilter; } -} \ No newline at end of file +} -- cgit v1.2.3 From cb4069f0f213ed1a38ce074d981b0c367dc2cdfd Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 15 Oct 2014 19:32:12 +0200 Subject: refactored file download status. make image http download available for carbon copied (sent) messages as well --- src/eu/siacs/conversations/crypto/PgpEngine.java | 6 +- .../siacs/conversations/entities/Conversation.java | 7 +- .../siacs/conversations/entities/Downloadable.java | 14 ++- .../conversations/entities/DownloadableFile.java | 4 +- src/eu/siacs/conversations/entities/Message.java | 55 ++++++------ .../siacs/conversations/http/HttpConnection.java | 84 ++++++++++------- .../conversations/http/HttpConnectionManager.java | 11 ++- .../siacs/conversations/parser/MessageParser.java | 5 +- .../conversations/persistance/DatabaseBackend.java | 2 +- .../conversations/persistance/FileBackend.java | 10 ++- .../services/AbstractConnectionManager.java | 5 +- .../ui/ConferenceDetailsActivity.java | 3 +- .../conversations/ui/ContactDetailsActivity.java | 9 +- .../conversations/ui/ConversationActivity.java | 3 +- .../conversations/ui/ConversationFragment.java | 9 +- .../conversations/ui/ManageAccountActivity.java | 6 +- .../ui/adapter/ConversationAdapter.java | 100 ++++++++++++--------- .../ui/adapter/KnownHostsAdapter.java | 4 +- .../conversations/ui/adapter/MessageAdapter.java | 46 +++------- .../siacs/conversations/xmpp/XmppConnection.java | 2 +- .../xmpp/jingle/JingleConnection.java | 85 +++++++++++------- .../xmpp/jingle/JingleConnectionManager.java | 2 +- .../xmpp/jingle/JingleInbandTransport.java | 3 +- 23 files changed, 265 insertions(+), 210 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index 07e8e472..e5524df5 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -76,7 +76,8 @@ public class PgpEngine { case OpenPgpApi.RESULT_CODE_ERROR: OpenPgpError error = result .getParcelableExtra(OpenPgpApi.RESULT_ERROR); - Log.d(Config.LOGTAG,"openpgp error: "+error.getMessage()); + Log.d(Config.LOGTAG, + "openpgp error: " + error.getMessage()); callback.error(R.string.openpgp_error, message); return; default: @@ -110,7 +111,8 @@ public class PgpEngine { + ',' + imageWidth + ',' + imageHeight); message.setEncryption(Message.ENCRYPTION_DECRYPTED); PgpEngine.this.mXmppConnectionService - .updateMessage(message);; + .updateMessage(message); + ; callback.success(message); return; case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index b4c99dc1..5f204ec2 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -68,7 +68,7 @@ public class Conversation extends AbstractEntity { private transient MucOptions mucOptions = null; - //private transient String latestMarkableMessageId; + // private transient String latestMarkableMessageId; private byte[] symmetricKey; @@ -142,8 +142,9 @@ public class Conversation extends AbstractEntity { if (this.messages == null) { return null; } - for(int i = this.messages.size() - 1; i >= 0; --i) { - if (this.messages.get(i).getStatus() <= Message.STATUS_RECEIVED && this.messages.get(i).markable) { + for (int i = this.messages.size() - 1; i >= 0; --i) { + if (this.messages.get(i).getStatus() <= Message.STATUS_RECEIVED + && this.messages.get(i).markable) { if (this.messages.get(i).isRead()) { return null; } else { diff --git a/src/eu/siacs/conversations/entities/Downloadable.java b/src/eu/siacs/conversations/entities/Downloadable.java index c8ee357d..3fc94c58 100644 --- a/src/eu/siacs/conversations/entities/Downloadable.java +++ b/src/eu/siacs/conversations/entities/Downloadable.java @@ -1,9 +1,19 @@ package eu.siacs.conversations.entities; public interface Downloadable { - + public final String[] VALID_EXTENSIONS = { "webp", "jpeg", "jpg", "png" }; public final String[] VALID_CRYPTO_EXTENSIONS = { "pgp", "gpg", "otr" }; - + + public static final int STATUS_UNKNOWN = 0x200; + public static final int STATUS_CHECKING = 0x201; + public static final int STATUS_FAILED = 0x202; + public static final int STATUS_OFFER = 0x203; + public static final int STATUS_DOWNLOADING = 0x204; + public void start(); + + public int getStatus(); + + public long getFileSize(); } diff --git a/src/eu/siacs/conversations/entities/DownloadableFile.java b/src/eu/siacs/conversations/entities/DownloadableFile.java index 14afc826..50b00fb8 100644 --- a/src/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/eu/siacs/conversations/entities/DownloadableFile.java @@ -29,7 +29,7 @@ public class DownloadableFile extends File { private long expectedSize = 0; private String sha1sum; private Key aeskey; - + private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf }; @@ -81,7 +81,7 @@ public class DownloadableFile extends File { public Key getKey() { return this.aeskey; } - + public InputStream createInputStream() { if (this.getKey() == null) { try { diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index 863288bb..a256d515 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -14,10 +14,6 @@ public class Message extends AbstractEntity { public static final String TABLENAME = "messages"; - public static final int STATUS_RECEIVED_CHECKING = -4; - public static final int STATUS_RECEPTION_FAILED = -3; - public static final int STATUS_RECEIVED_OFFER = -2; - public static final int STATUS_RECEIVING = -1; public static final int STATUS_RECEIVED = 0; public static final int STATUS_UNSEND = 1; public static final int STATUS_SEND = 2; @@ -136,8 +132,8 @@ public class Message extends AbstractEntity { if (this.trueCounterpart == null) { return null; } else { - return this.conversation.getAccount().getRoster().getContactFromRoster( - this.trueCounterpart); + return this.conversation.getAccount().getRoster() + .getContactFromRoster(this.trueCounterpart); } } } @@ -147,12 +143,9 @@ public class Message extends AbstractEntity { } public String getReadableBody(Context context) { - if ((encryption == ENCRYPTION_PGP) && (type == TYPE_TEXT)) { + if (encryption == ENCRYPTION_PGP) { return context.getText(R.string.encrypted_message_received) .toString(); - } else if ((encryption == ENCRYPTION_OTR) && (type == TYPE_IMAGE)) { - return context.getText(R.string.encrypted_image_received) - .toString(); } else if (encryption == ENCRYPTION_DECRYPTION_FAILED) { return context.getText(R.string.decryption_failed).toString(); } else if (type == TYPE_IMAGE) { @@ -322,6 +315,8 @@ public class Message extends AbstractEntity { return false; } return (message.getType() == Message.TYPE_TEXT + && this.getDownloadable() == null + && message.getDownloadable() == null && message.getEncryption() != Message.ENCRYPTION_PGP && this.getType() == message.getType() && this.getEncryption() == message.getEncryption() @@ -368,26 +363,34 @@ public class Message extends AbstractEntity { return prev.mergable(this); } } - + public boolean bodyContainsDownloadable() { Contact contact = this.getContact(); - if (contact == null || !contact.trusted()) { + if (status <= STATUS_RECEIVED + && (contact == null || !contact.trusted())) { return false; } try { URL url = new URL(this.getBody()); - if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { + if (!url.getProtocol().equalsIgnoreCase("http") + && !url.getProtocol().equalsIgnoreCase("https")) { return false; } - if (url.getPath()==null) { + if (url.getPath() == null) { return false; } String[] pathParts = url.getPath().split("/"); String filename = pathParts[pathParts.length - 1]; String[] extensionParts = filename.split("\\."); - if (extensionParts.length == 2 && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains(extensionParts[extensionParts.length -1])) { + if (extensionParts.length == 2 + && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains( + extensionParts[extensionParts.length - 1])) { return true; - } else if (extensionParts.length == 3 && Arrays.asList(Downloadable.VALID_CRYPTO_EXTENSIONS).contains(extensionParts.length -1) && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains(extensionParts[extensionParts.length -2])) { + } else if (extensionParts.length == 3 + && Arrays.asList(Downloadable.VALID_CRYPTO_EXTENSIONS) + .contains(extensionParts.length - 1) + && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains( + extensionParts[extensionParts.length - 2])) { return true; } else { return false; @@ -396,27 +399,23 @@ public class Message extends AbstractEntity { return false; } } - + public ImageParams getImageParams() { ImageParams params = new ImageParams(); - if (body==null) { + if (this.downloadable != null) { + params.size = this.downloadable.getFileSize(); + } + if (body == null) { return params; } String parts[] = body.split(","); - if (parts.length==1) { + if (parts.length == 1) { try { params.size = Long.parseLong(parts[0]); } catch (NumberFormatException e) { params.origin = parts[0]; } - } else if (parts.length == 2) { - params.origin = parts[0]; - try { - params.size = Long.parseLong(parts[1]); - } catch (NumberFormatException e) { - params.size = 0; - } - } else if (parts.length==3) { + } else if (parts.length == 3) { try { params.size = Long.parseLong(parts[0]); } catch (NumberFormatException e) { @@ -452,7 +451,7 @@ public class Message extends AbstractEntity { } return params; } - + public class ImageParams { public long size = 0; public int width = 0; diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index ff8037fb..c53b9fd5 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -24,7 +24,8 @@ public class HttpConnection implements Downloadable { private URL mUrl; private Message message; private DownloadableFile file; - private long mPreviousFileSize = Long.MIN_VALUE; + private long mPreviousFileSize = 0; + private int mStatus = Downloadable.STATUS_UNKNOWN; public HttpConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; @@ -33,6 +34,7 @@ public class HttpConnection implements Downloadable { @Override public void start() { + changeStatus(STATUS_DOWNLOADING); new Thread(new FileDownloader()).start(); } @@ -41,43 +43,46 @@ public class HttpConnection implements Downloadable { this.message.setDownloadable(this); try { mUrl = new URL(message.getBody()); - this.file = mXmppConnectionService.getFileBackend().getConversationsFile(message,false); - message.setType(Message.TYPE_IMAGE); - message.setStatus(Message.STATUS_RECEIVED_CHECKING); - mXmppConnectionService.updateConversationUi(); + this.file = mXmppConnectionService.getFileBackend() + .getConversationsFile(message, false); checkFileSize(); } catch (MalformedURLException e) { this.cancel(); } } - + public void init(Message message, URL url) { this.message = message; this.message.setDownloadable(this); this.mUrl = url; - this.file = mXmppConnectionService.getFileBackend().getConversationsFile(message,false); + this.file = mXmppConnectionService.getFileBackend() + .getConversationsFile(message, false); this.mPreviousFileSize = message.getImageParams().size; - message.setType(Message.TYPE_IMAGE); - message.setStatus(Message.STATUS_RECEIVED_CHECKING); - mXmppConnectionService.updateConversationUi(); checkFileSize(); } - + private void checkFileSize() { + changeStatus(STATUS_CHECKING); new Thread(new FileSizeChecker()).start(); } public void cancel() { - mXmppConnectionService.markMessage(message, Message.STATUS_RECEPTION_FAILED); mHttpConnectionManager.finishConnection(this); + message.setDownloadable(null); + message.setBody(mUrl.toString()); + mXmppConnectionService.updateMessage(message); } - + private void finish() { - message.setStatus(Message.STATUS_RECEIVED); - mXmppConnectionService.updateMessage(message); + message.setDownloadable(null); mHttpConnectionManager.finishConnection(this); } + private void changeStatus(int status) { + this.mStatus = status; + mXmppConnectionService.updateConversationUi(); + } + private class FileSizeChecker implements Runnable { @Override @@ -90,21 +95,21 @@ public class HttpConnection implements Downloadable { return; } file.setExpectedSize(size); - message.setBody(mUrl.toString()+","+String.valueOf(size)); - if (size <= mHttpConnectionManager.getAutoAcceptFileSize() || size == mPreviousFileSize) { - mXmppConnectionService.updateMessage(message); + message.setType(Message.TYPE_IMAGE); + if (size <= mHttpConnectionManager.getAutoAcceptFileSize() + || size == mPreviousFileSize) { start(); } else { - message.setStatus(Message.STATUS_RECEIVED_OFFER); - mXmppConnectionService.updateMessage(message); + changeStatus(STATUS_OFFER); } } private long retrieveFileSize() throws IOException { - HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); + HttpURLConnection connection = (HttpURLConnection) mUrl + .openConnection(); connection.setRequestMethod("HEAD"); if (connection instanceof HttpsURLConnection) { - + } String contentLength = connection.getHeaderField("Content-Length"); if (contentLength == null) { @@ -118,13 +123,12 @@ public class HttpConnection implements Downloadable { } } - + private class FileDownloader implements Runnable { @Override public void run() { try { - mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVING); download(); updateImageBounds(); finish(); @@ -132,13 +136,15 @@ public class HttpConnection implements Downloadable { cancel(); } } - + private void download() throws IOException { - HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); + HttpURLConnection connection = (HttpURLConnection) mUrl + .openConnection(); if (connection instanceof HttpsURLConnection) { - + } - BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); + BufferedInputStream is = new BufferedInputStream( + connection.getInputStream()); OutputStream os = file.createOutputStream(); int count = -1; byte[] buffer = new byte[1024]; @@ -149,17 +155,31 @@ public class HttpConnection implements Downloadable { os.close(); is.close(); } - + private void updateImageBounds() { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(file.getAbsolutePath(), options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; - message.setBody(mUrl.toString()+","+file.getSize() + ',' + message.setBody(mUrl.toString() + "," + file.getSize() + ',' + imageWidth + ',' + imageHeight); - + mXmppConnectionService.updateMessage(message); + } + + } + + @Override + public int getStatus() { + return this.mStatus; + } + + @Override + public long getFileSize() { + if (this.file != null) { + return this.file.getExpectedSize(); + } else { + return 0; } - } } \ No newline at end of file diff --git a/src/eu/siacs/conversations/http/HttpConnectionManager.java b/src/eu/siacs/conversations/http/HttpConnectionManager.java index 7393cf36..011ecc3f 100644 --- a/src/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/eu/siacs/conversations/http/HttpConnectionManager.java @@ -13,24 +13,23 @@ public class HttpConnectionManager extends AbstractConnectionManager { public HttpConnectionManager(XmppConnectionService service) { super(service); } - + private List connections = new CopyOnWriteArrayList(); - - + public HttpConnection createNewConnection(Message message) { HttpConnection connection = new HttpConnection(this); connection.init(message); this.connections.add(connection); return connection; } - + public HttpConnection createNewConnection(Message message, URL url) { HttpConnection connection = new HttpConnection(this); - connection.init(message,url); + connection.init(message, url); this.connections.add(connection); return connection; } - + public void finishConnection(HttpConnection connection) { this.connections.remove(connection); } diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index 71346c7a..486dd389 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -478,8 +478,9 @@ public class MessageParser extends AbstractParser implements mXmppConnectionService.databaseBackend.createMessage(message); } } - if (message.getStatus() == Message.STATUS_RECEIVED && message.bodyContainsDownloadable()) { - this.mXmppConnectionService.getHttpConnectionManager().createNewConnection(message); + if (message.bodyContainsDownloadable()) { + this.mXmppConnectionService.getHttpConnectionManager() + .createNewConnection(message); } notify = notify && !conversation.isMuted(); if (notify) { diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java index 091c00bd..d90b5c62 100644 --- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -238,7 +238,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { cursor.close(); return (count > 0); } catch (SQLiteCantOpenDatabaseException e) { - return true; //better safe than sorry + return true; // better safe than sorry } } diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index c8ae657d..35aa9042 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -70,7 +70,8 @@ public class FileBackend { return getJingleFileLegacy(message, true); } - public DownloadableFile getJingleFileLegacy(Message message, boolean decrypted) { + public DownloadableFile getJingleFileLegacy(Message message, + boolean decrypted) { Conversation conversation = message.getConversation(); String prefix = context.getFilesDir().getAbsolutePath(); String path = prefix + "/" + conversation.getAccount().getJid() + "/" @@ -92,7 +93,8 @@ public class FileBackend { return getConversationsFile(message, true); } - public DownloadableFile getConversationsFile(Message message, boolean decrypted) { + public DownloadableFile getConversationsFile(Message message, + boolean decrypted) { StringBuilder filename = new StringBuilder(); filename.append(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath()); @@ -144,8 +146,8 @@ public class FileBackend { return this.copyImageToPrivateStorage(message, image, 0); } - private DownloadableFile copyImageToPrivateStorage(Message message, Uri image, - int sampleSize) throws ImageCopyException { + private DownloadableFile copyImageToPrivateStorage(Message message, + Uri image, int sampleSize) throws ImageCopyException { try { InputStream is = context.getContentResolver() .openInputStream(image); diff --git a/src/eu/siacs/conversations/services/AbstractConnectionManager.java b/src/eu/siacs/conversations/services/AbstractConnectionManager.java index a06be826..676a09c9 100644 --- a/src/eu/siacs/conversations/services/AbstractConnectionManager.java +++ b/src/eu/siacs/conversations/services/AbstractConnectionManager.java @@ -1,17 +1,16 @@ package eu.siacs.conversations.services; - public class AbstractConnectionManager { protected XmppConnectionService mXmppConnectionService; public AbstractConnectionManager(XmppConnectionService service) { this.mXmppConnectionService = service; } - + public XmppConnectionService getXmppConnectionService() { return this.mXmppConnectionService; } - + public long getAutoAcceptFileSize() { String config = this.mXmppConnectionService.getPreferences().getString( "auto_accept_file_size", "524288"); diff --git a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index deddcad7..ca3bb4a2 100644 --- a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -199,7 +199,8 @@ public class ConferenceDetailsActivity extends XmppActivity { } private void populateView() { - mAccountJid.setText(getString(R.string.using_account,conversation.getAccount().getJid())); + mAccountJid.setText(getString(R.string.using_account, conversation + .getAccount().getJid())); mYourPhoto.setImageBitmap(conversation.getAccount().getImage(this, 48)); setTitle(conversation.getName()); mFullJid.setText(conversation.getContactJid().split("/", 2)[0]); diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java index 394aab6e..65bd5cbf 100644 --- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -56,7 +56,8 @@ public class ContactDetailsActivity extends XmppActivity { @Override public void onClick(DialogInterface dialog, int which) { - ContactDetailsActivity.this.xmppConnectionService.deleteContactOnServer(contact); + ContactDetailsActivity.this.xmppConnectionService + .deleteContactOnServer(contact); ContactDetailsActivity.this.finish(); } }; @@ -78,7 +79,8 @@ public class ContactDetailsActivity extends XmppActivity { @Override public void onClick(View v) { - AlertDialog.Builder builder = new AlertDialog.Builder(ContactDetailsActivity.this); + AlertDialog.Builder builder = new AlertDialog.Builder( + ContactDetailsActivity.this); builder.setTitle(getString(R.string.action_add_phone_book)); builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid())); @@ -309,7 +311,8 @@ public class ContactDetailsActivity extends XmppActivity { } else { contactJidTv.setText(contact.getJid()); } - accountJidTv.setText(getString(R.string.using_account,contact.getAccount().getJid())); + accountJidTv.setText(getString(R.string.using_account, contact + .getAccount().getJid())); UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext()); diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 40739387..24ef9a6f 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -222,7 +222,8 @@ public class ConversationActivity extends XmppActivity implements ab.setDisplayHomeAsUpEnabled(true); ab.setHomeButtonEnabled(true); if (getSelectedConversation().getMode() == Conversation.MODE_SINGLE - || ConversationActivity.this.useSubjectToIdentifyConference()) { + || ConversationActivity.this + .useSubjectToIdentifyConference()) { ab.setTitle(getSelectedConversation().getName()); } else { ab.setTitle(getSelectedConversation().getContactJid() diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 4835636d..0e71801b 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -72,8 +72,7 @@ public class ConversationFragment extends Fragment { private boolean messagesLoaded = false; private IntentSender askForPassphraseIntent = null; - - + private ConcurrentLinkedQueue mEncryptedMessages = new ConcurrentLinkedQueue(); private boolean mDecryptJobRunning = false; @@ -505,8 +504,8 @@ public class ConversationFragment extends Fragment { private void decryptNext() { Message next = this.mEncryptedMessages.peek(); PgpEngine engine = activity.xmppConnectionService.getPgpEngine(); - - if (next!=null && engine != null && !mDecryptJobRunning) { + + if (next != null && engine != null && !mDecryptJobRunning) { mDecryptJobRunning = true; engine.decrypt(next, new UiCallback() { @@ -535,7 +534,7 @@ public class ConversationFragment extends Fragment { }); } } - + private void messageSent() { int size = this.messageList.size(); messagesView.setSelection(size - 1); diff --git a/src/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/eu/siacs/conversations/ui/ManageAccountActivity.java index afe9e06e..5b5b0608 100644 --- a/src/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -70,7 +70,8 @@ public class ManageAccountActivity extends XmppActivity { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); - ManageAccountActivity.this.getMenuInflater().inflate(R.menu.manageaccounts_context, menu); + ManageAccountActivity.this.getMenuInflater().inflate( + R.menu.manageaccounts_context, menu); AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; this.selectedAccount = accountList.get(acmi.position); if (this.selectedAccount.isOptionSet(Account.OPTION_DISABLED)) { @@ -187,7 +188,8 @@ public class ManageAccountActivity extends XmppActivity { } private void deleteAccount(final Account account) { - AlertDialog.Builder builder = new AlertDialog.Builder(ManageAccountActivity.this); + AlertDialog.Builder builder = new AlertDialog.Builder( + ManageAccountActivity.this); builder.setTitle(getString(R.string.mgmt_account_are_you_sure)); builder.setIconAttribute(android.R.attr.alertDialogIcon); builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text)); diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index f74856b0..6943a85c 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -5,6 +5,7 @@ import java.util.List; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.XmppActivity; @@ -37,11 +38,11 @@ public class ConversationAdapter extends ArrayAdapter { view = (View) inflater.inflate(R.layout.conversation_list_row, parent, false); } - Conversation conv = getItem(position); + Conversation conversation = getItem(position); if (this.activity instanceof ConversationActivity) { ConversationActivity activity = (ConversationActivity) this.activity; if (!activity.isConversationsOverviewHideable()) { - if (conv == activity.getSelectedConversation()) { + if (conversation == activity.getSelectedConversation()) { view.setBackgroundColor(activity .getSecondaryBackgroundColor()); } else { @@ -53,65 +54,76 @@ public class ConversationAdapter extends ArrayAdapter { } TextView convName = (TextView) view .findViewById(R.id.conversation_name); - if (conv.getMode() == Conversation.MODE_SINGLE + if (conversation.getMode() == Conversation.MODE_SINGLE || activity.useSubjectToIdentifyConference()) { - convName.setText(conv.getName()); + convName.setText(conversation.getName()); } else { - convName.setText(conv.getContactJid().split("/")[0]); + convName.setText(conversation.getContactJid().split("/")[0]); } - TextView convLastMsg = (TextView) view + TextView mLastMessage = (TextView) view .findViewById(R.id.conversation_lastmsg); + TextView mTimestamp = (TextView) view + .findViewById(R.id.conversation_lastupdate); ImageView imagePreview = (ImageView) view .findViewById(R.id.conversation_lastimage); - Message latestMessage = conv.getLatestMessage(); + Message message = conversation.getLatestMessage(); - if (latestMessage.getType() == Message.TYPE_TEXT - || latestMessage.getType() == Message.TYPE_PRIVATE) { - if ((latestMessage.getEncryption() != Message.ENCRYPTION_PGP) - && (latestMessage.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED)) { - String body = Config.PARSE_EMOTICONS ? UIHelper - .transformAsciiEmoticons(latestMessage.getBody()) - : latestMessage.getBody(); - convLastMsg.setText(body); - } else { - convLastMsg.setText(R.string.encrypted_message_received); - } - convLastMsg.setVisibility(View.VISIBLE); - imagePreview.setVisibility(View.GONE); - } else if (latestMessage.getType() == Message.TYPE_IMAGE) { - if (latestMessage.getStatus() >= Message.STATUS_RECEIVED) { - convLastMsg.setVisibility(View.GONE); - imagePreview.setVisibility(View.VISIBLE); - activity.loadBitmap(latestMessage, imagePreview); - } else { - convLastMsg.setVisibility(View.VISIBLE); + if (!conversation.isRead()) { + convName.setTypeface(null, Typeface.BOLD); + } else { + convName.setTypeface(null, Typeface.NORMAL); + } + + if (message.getType() == Message.TYPE_IMAGE + || message.getDownloadable() != null) { + Downloadable d = message.getDownloadable(); + if (d != null) { + mLastMessage.setVisibility(View.VISIBLE); imagePreview.setVisibility(View.GONE); - if (latestMessage.getStatus() == Message.STATUS_RECEIVED_OFFER) { - convLastMsg.setText(R.string.image_offered_for_download); - } else if (latestMessage.getStatus() == Message.STATUS_RECEIVING) { - convLastMsg.setText(R.string.receiving_image); + if (conversation.isRead()) { + mLastMessage.setTypeface(null, Typeface.ITALIC); + } else { + mLastMessage.setTypeface(null, Typeface.BOLD_ITALIC); + } + if (d.getStatus() == Downloadable.STATUS_CHECKING) { + mLastMessage.setText(R.string.checking_image); + } else if (d.getStatus() == Downloadable.STATUS_DOWNLOADING) { + mLastMessage.setText(R.string.receiving_image); + } else if (d.getStatus() == Downloadable.STATUS_OFFER) { + mLastMessage.setText(R.string.image_offered_for_download); } else { - convLastMsg.setText(""); + mLastMessage.setText(""); } + } else { + mLastMessage.setVisibility(View.GONE); + imagePreview.setVisibility(View.VISIBLE); + activity.loadBitmap(message, imagePreview); } - } - - if (!conv.isRead()) { - convName.setTypeface(null, Typeface.BOLD); - convLastMsg.setTypeface(null, Typeface.BOLD); } else { - convName.setTypeface(null, Typeface.NORMAL); - convLastMsg.setTypeface(null, Typeface.NORMAL); + if ((message.getEncryption() != Message.ENCRYPTION_PGP) + && (message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED)) { + String body = Config.PARSE_EMOTICONS ? UIHelper + .transformAsciiEmoticons(message.getBody()) : message + .getBody(); + mLastMessage.setText(body); + } else { + mLastMessage.setText(R.string.encrypted_message_received); + } + if (!conversation.isRead()) { + mLastMessage.setTypeface(null, Typeface.BOLD); + } else { + mLastMessage.setTypeface(null, Typeface.NORMAL); + } + mLastMessage.setVisibility(View.VISIBLE); + imagePreview.setVisibility(View.GONE); } - - ((TextView) view.findViewById(R.id.conversation_lastupdate)) - .setText(UIHelper.readableTimeDifference(getContext(), conv - .getLatestMessage().getTimeSent())); + mTimestamp.setText(UIHelper.readableTimeDifference(getContext(), + conversation.getLatestMessage().getTimeSent())); ImageView profilePicture = (ImageView) view .findViewById(R.id.conversation_image); - profilePicture.setImageBitmap(conv.getImage(activity, 56)); + profilePicture.setImageBitmap(conversation.getImage(activity, 56)); return view; } diff --git a/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java b/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java index 2b8ee048..143dfda1 100644 --- a/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java @@ -47,11 +47,11 @@ public class KnownHostsAdapter extends ArrayAdapter { @Override protected void publishResults(CharSequence constraint, FilterResults results) { - ArrayList filteredList = (ArrayList)results.values; + ArrayList filteredList = (ArrayList) results.values; if (results != null && results.count > 0) { clear(); for (Object c : filteredList) { - add((String)c); + add((String) c); } notifyDataSetChanged(); } diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index b09f97fc..efb07292 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -138,10 +138,6 @@ public class MessageAdapter extends ArrayAdapter { info = getContext().getString(R.string.send_rejected); error = true; break; - case Message.STATUS_RECEPTION_FAILED: - info = getContext().getString(R.string.reception_failed); - error = true; - break; default: if (multiReceived) { Contact contact = message.getContact(); @@ -230,19 +226,10 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.messageBody.setVisibility(View.VISIBLE); if (message.getBody() != null) { if (message.getType() != Message.TYPE_PRIVATE) { - if (message.getType() == Message.TYPE_IMAGE) { - String orign = message.getImageParams().origin; - if (orign!=null) { - viewHolder.messageBody.setText(orign); - } else { - viewHolder.messageBody.setText(message.getBody()); - } - } else { - String body = Config.PARSE_EMOTICONS ? UIHelper - .transformAsciiEmoticons(message.getMergedBody()) - : message.getMergedBody(); - viewHolder.messageBody.setText(body); - } + String body = Config.PARSE_EMOTICONS ? UIHelper + .transformAsciiEmoticons(message.getMergedBody()) + : message.getMergedBody(); + viewHolder.messageBody.setText(body); } else { String privateMarker; if (message.getStatus() <= Message.STATUS_RECEIVED) { @@ -347,6 +334,8 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.contact_picture = (ImageView) view .findViewById(R.id.message_photo); viewHolder.contact_picture.setImageBitmap(getSelfBitmap()); + viewHolder.download_button = (Button) view + .findViewById(R.id.download_button); viewHolder.indicator = (ImageView) view .findViewById(R.id.security_indicator); viewHolder.image = (ImageView) view @@ -366,15 +355,11 @@ public class MessageAdapter extends ArrayAdapter { .findViewById(R.id.message_box); viewHolder.contact_picture = (ImageView) view .findViewById(R.id.message_photo); - viewHolder.download_button = (Button) view .findViewById(R.id.download_button); - if (item.getConversation().getMode() == Conversation.MODE_SINGLE) { - viewHolder.contact_picture.setImageBitmap(mBitmapCache.get( item.getConversation().getContact(), getContext())); - } viewHolder.indicator = (ImageView) view .findViewById(R.id.security_indicator); @@ -483,14 +468,15 @@ public class MessageAdapter extends ArrayAdapter { } } - if (item.getType() == Message.TYPE_IMAGE) { - if (item.getStatus() == Message.STATUS_RECEIVING) { + if (item.getType() == Message.TYPE_IMAGE + || item.getDownloadable() != null) { + Downloadable d = item.getDownloadable(); + if (d != null && d.getStatus() == Downloadable.STATUS_DOWNLOADING) { displayInfoMessage(viewHolder, R.string.receiving_image); - } else if (item.getStatus() == Message.STATUS_RECEIVED_CHECKING) { + } else if (d != null + && d.getStatus() == Downloadable.STATUS_CHECKING) { displayInfoMessage(viewHolder, R.string.checking_image); - } else if (item.getStatus() == Message.STATUS_RECEPTION_FAILED) { - displayTextMessage(viewHolder, item); - } else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) { + } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER) { viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); viewHolder.download_button.setVisibility(View.VISIBLE); @@ -499,11 +485,7 @@ public class MessageAdapter extends ArrayAdapter { @Override public void onClick(View v) { - if (!startDonwloadable(item)) { - activity.xmppConnectionService.markMessage( - item, - Message.STATUS_RECEPTION_FAILED); - } + startDonwloadable(item); } }); } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED) diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 54409be4..43614f50 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -910,7 +910,7 @@ public class XmppConnection implements Runnable { } public void disconnect(boolean force) { - Log.d(Config.LOGTAG, account.getJid()+": disconnecting"); + Log.d(Config.LOGTAG, account.getJid() + ": disconnecting"); try { if (force) { socket.close(); diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 4853d75c..8e4714f4 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -34,17 +34,18 @@ public class JingleConnection implements Downloadable { private JingleConnectionManager mJingleConnectionManager; private XmppConnectionService mXmppConnectionService; - public static final int STATUS_INITIATED = 0; - public static final int STATUS_ACCEPTED = 1; - public static final int STATUS_TERMINATED = 2; - public static final int STATUS_CANCELED = 3; - public static final int STATUS_FINISHED = 4; - public static final int STATUS_TRANSMITTING = 5; - public static final int STATUS_FAILED = 99; + protected static final int JINGLE_STATUS_INITIATED = 0; + protected static final int JINGLE_STATUS_ACCEPTED = 1; + protected static final int JINGLE_STATUS_TERMINATED = 2; + protected static final int JINGLE_STATUS_CANCELED = 3; + protected static final int JINGLE_STATUS_FINISHED = 4; + protected static final int JINGLE_STATUS_TRANSMITTING = 5; + protected static final int JINGLE_STATUS_FAILED = 99; private int ibbBlockSize = 4096; - private int status = -1; + private int mJingleStatus = -1; + private int mStatus = -1; private Message message; private String sessionId; private Account account; @@ -76,7 +77,7 @@ public class JingleConnection implements Downloadable { mXmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED); } - status = STATUS_FAILED; + mJingleStatus = JINGLE_STATUS_FAILED; } } }; @@ -254,13 +255,14 @@ public class JingleConnection implements Downloadable { } public void init(Account account, JinglePacket packet) { - this.status = STATUS_INITIATED; + this.mJingleStatus = JINGLE_STATUS_INITIATED; Conversation conversation = this.mXmppConnectionService .findOrCreateConversation(account, packet.getFrom().split("/", 2)[0], false); this.message = new Message(conversation, "", Message.ENCRYPTION_NONE); + this.message.setStatus(Message.STATUS_RECEIVED); this.message.setType(Message.TYPE_IMAGE); - this.message.setStatus(Message.STATUS_RECEIVED_OFFER); + this.mStatus = Downloadable.STATUS_OFFER; this.message.setDownloadable(this); String[] fromParts = packet.getFrom().split("/", 2); this.message.setPresence(fromParts[1]); @@ -306,6 +308,7 @@ public class JingleConnection implements Downloadable { long size = Long.parseLong(fileSize.getContent()); message.setBody(Long.toString(size)); conversation.getMessages().add(message); + mXmppConnectionService.updateConversationUi(); if (size <= this.mJingleConnectionManager .getAutoAcceptFileSize()) { Log.d(Config.LOGTAG, "auto accepting file from " @@ -370,7 +373,7 @@ public class JingleConnection implements Downloadable { content.socks5transport().setChildren(getCandidatesAsElements()); packet.setContent(content); this.sendJinglePacket(packet); - this.status = STATUS_INITIATED; + this.mJingleStatus = JINGLE_STATUS_INITIATED; } } @@ -383,8 +386,9 @@ public class JingleConnection implements Downloadable { } private void sendAccept() { - status = STATUS_ACCEPTED; - mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVING); + mJingleStatus = JINGLE_STATUS_ACCEPTED; + this.mStatus = Downloadable.STATUS_DOWNLOADING; + mXmppConnectionService.updateConversationUi(); this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() { @@ -458,7 +462,7 @@ public class JingleConnection implements Downloadable { Content content = packet.getJingleContent(); mergeCandidates(JingleCandidate.parse(content.socks5transport() .getChildren())); - this.status = STATUS_ACCEPTED; + this.mJingleStatus = JINGLE_STATUS_ACCEPTED; mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND); this.connectNextCandidate(); return true; @@ -493,7 +497,8 @@ public class JingleConnection implements Downloadable { } else if (content.socks5transport().hasChild("candidate-error")) { Log.d(Config.LOGTAG, "received candidate error"); this.receivedCandidate = true; - if ((status == STATUS_ACCEPTED) && (this.sentCandidate)) { + if ((mJingleStatus == JINGLE_STATUS_ACCEPTED) + && (this.sentCandidate)) { this.connect(); } return true; @@ -505,7 +510,8 @@ public class JingleConnection implements Downloadable { JingleCandidate candidate = getCandidate(cid); candidate.flagAsUsedByCounterpart(); this.receivedCandidate = true; - if ((status == STATUS_ACCEPTED) && (this.sentCandidate)) { + if ((mJingleStatus == JINGLE_STATUS_ACCEPTED) + && (this.sentCandidate)) { this.connect(); } else { Log.d(Config.LOGTAG, @@ -533,7 +539,7 @@ public class JingleConnection implements Downloadable { this.sendFallbackToIbb(); } } else { - this.status = STATUS_TRANSMITTING; + this.mJingleStatus = JINGLE_STATUS_TRANSMITTING; if (connection.needsActivation()) { if (connection.getCandidate().isOurs()) { Log.d(Config.LOGTAG, "candidate " @@ -620,9 +626,10 @@ public class JingleConnection implements Downloadable { packet.setReason(reason); this.sendJinglePacket(packet); this.disconnect(); - this.status = STATUS_FINISHED; - this.mXmppConnectionService.markMessage(this.message, - Message.STATUS_RECEIVED); + this.mJingleStatus = JINGLE_STATUS_FINISHED; + this.message.setStatus(Message.STATUS_RECEIVED); + this.message.setDownloadable(null); + this.mXmppConnectionService.updateMessage(message); this.mJingleConnectionManager.finishConnection(this); } @@ -692,7 +699,7 @@ public class JingleConnection implements Downloadable { } private void receiveSuccess() { - this.status = STATUS_FINISHED; + this.mJingleStatus = JINGLE_STATUS_FINISHED; this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND); this.disconnect(); @@ -700,14 +707,14 @@ public class JingleConnection implements Downloadable { } public void cancel() { - this.status = STATUS_CANCELED; + this.mJingleStatus = JINGLE_STATUS_CANCELED; this.disconnect(); if (this.message != null) { if (this.responder.equals(account.getFullJid())) { - this.mXmppConnectionService.markMessage(this.message, - Message.STATUS_RECEPTION_FAILED); + this.mStatus = Downloadable.STATUS_FAILED; + this.mXmppConnectionService.updateConversationUi(); } else { - if (this.status == STATUS_INITIATED) { + if (this.mJingleStatus == JINGLE_STATUS_INITIATED) { this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED); } else { @@ -790,7 +797,7 @@ public class JingleConnection implements Downloadable { .setAttribute("cid", cid); packet.setContent(content); this.sentCandidate = true; - if ((receivedCandidate) && (status == STATUS_ACCEPTED)) { + if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) { connect(); } this.sendJinglePacket(packet); @@ -803,7 +810,7 @@ public class JingleConnection implements Downloadable { content.socks5transport().addChild("candidate-error"); packet.setContent(content); this.sentCandidate = true; - if ((receivedCandidate) && (status == STATUS_ACCEPTED)) { + if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) { connect(); } this.sendJinglePacket(packet); @@ -817,8 +824,8 @@ public class JingleConnection implements Downloadable { return this.responder; } - public int getStatus() { - return this.status; + public int getJingleStatus() { + return this.mJingleStatus; } private boolean equalCandidateExists(JingleCandidate candidate) { @@ -869,7 +876,7 @@ public class JingleConnection implements Downloadable { } public void start() { - if (status == STATUS_INITIATED) { + if (mJingleStatus == JINGLE_STATUS_INITIATED) { new Thread(new Runnable() { @Override @@ -878,7 +885,21 @@ public class JingleConnection implements Downloadable { } }).start(); } else { - Log.d(Config.LOGTAG, "status (" + status + ") was not ok"); + Log.d(Config.LOGTAG, "status (" + mJingleStatus + ") was not ok"); + } + } + + @Override + public int getStatus() { + return this.mStatus; + } + + @Override + public long getFileSize() { + if (this.file != null) { + return this.file.getExpectedSize(); + } else { + return 0; } } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index bb360204..40ccbfe3 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -154,7 +154,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { public void cancelInTransmission() { for (JingleConnection connection : this.connections) { - if (connection.getStatus() == JingleConnection.STATUS_TRANSMITTING) { + if (connection.getJingleStatus() == JingleConnection.JINGLE_STATUS_TRANSMITTING) { connection.cancel(); } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java index e5016935..cc1e92f6 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java @@ -100,7 +100,8 @@ public class JingleInbandTransport extends JingleTransport { } @Override - public void send(DownloadableFile file, OnFileTransmissionStatusChanged callback) { + public void send(DownloadableFile file, + OnFileTransmissionStatusChanged callback) { this.onFileTransmissionStatusChanged = callback; this.file = file; try { -- cgit v1.2.3 From f5019ba96647bd1c33153e6e9099d21dcf47bfa7 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 15 Oct 2014 22:08:13 +0200 Subject: detect deleted files on start up. got rid of lagecy image provider for performance reasons. NOTE: this will prevent you to access images older than version 0.6 --- src/eu/siacs/conversations/crypto/PgpEngine.java | 8 +- .../siacs/conversations/entities/Downloadable.java | 1 + .../siacs/conversations/http/HttpConnection.java | 23 ++--- .../conversations/http/HttpConnectionManager.java | 8 +- .../conversations/persistance/FileBackend.java | 51 +++------- .../conversations/services/ImageProvider.java | 109 --------------------- .../services/XmppConnectionService.java | 32 +++++- .../ui/adapter/ConversationAdapter.java | 2 + .../conversations/ui/adapter/MessageAdapter.java | 18 +--- .../xmpp/jingle/JingleConnection.java | 4 +- 10 files changed, 65 insertions(+), 191 deletions(-) delete mode 100644 src/eu/siacs/conversations/services/ImageProvider.java (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index e5524df5..2696c7d2 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -88,9 +88,9 @@ public class PgpEngine { } else if (message.getType() == Message.TYPE_IMAGE) { try { final DownloadableFile inputFile = this.mXmppConnectionService - .getFileBackend().getConversationsFile(message, false); + .getFileBackend().getFile(message, false); final DownloadableFile outputFile = this.mXmppConnectionService - .getFileBackend().getConversationsFile(message, true); + .getFileBackend().getFile(message, true); outputFile.createNewFile(); InputStream is = new FileInputStream(inputFile); OutputStream os = new FileOutputStream(outputFile); @@ -198,9 +198,9 @@ public class PgpEngine { } else if (message.getType() == Message.TYPE_IMAGE) { try { DownloadableFile inputFile = this.mXmppConnectionService - .getFileBackend().getConversationsFile(message, true); + .getFileBackend().getFile(message, true); DownloadableFile outputFile = this.mXmppConnectionService - .getFileBackend().getConversationsFile(message, false); + .getFileBackend().getFile(message, false); outputFile.createNewFile(); InputStream is = new FileInputStream(inputFile); OutputStream os = new FileOutputStream(outputFile); diff --git a/src/eu/siacs/conversations/entities/Downloadable.java b/src/eu/siacs/conversations/entities/Downloadable.java index 3fc94c58..c8ca599f 100644 --- a/src/eu/siacs/conversations/entities/Downloadable.java +++ b/src/eu/siacs/conversations/entities/Downloadable.java @@ -10,6 +10,7 @@ public interface Downloadable { public static final int STATUS_FAILED = 0x202; public static final int STATUS_OFFER = 0x203; public static final int STATUS_DOWNLOADING = 0x204; + public static final int STATUS_DELETED = 0x205; public void start(); diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index c53b9fd5..34036412 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -9,7 +9,9 @@ import java.net.URL; import javax.net.ssl.HttpsURLConnection; +import android.content.Intent; import android.graphics.BitmapFactory; +import android.net.Uri; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; @@ -24,8 +26,8 @@ public class HttpConnection implements Downloadable { private URL mUrl; private Message message; private DownloadableFile file; - private long mPreviousFileSize = 0; private int mStatus = Downloadable.STATUS_UNKNOWN; + private boolean mAutostart = true; public HttpConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; @@ -44,23 +46,14 @@ public class HttpConnection implements Downloadable { try { mUrl = new URL(message.getBody()); this.file = mXmppConnectionService.getFileBackend() - .getConversationsFile(message, false); + .getFile(message, false); + this.mAutostart = true; checkFileSize(); } catch (MalformedURLException e) { this.cancel(); } } - public void init(Message message, URL url) { - this.message = message; - this.message.setDownloadable(this); - this.mUrl = url; - this.file = mXmppConnectionService.getFileBackend() - .getConversationsFile(message, false); - this.mPreviousFileSize = message.getImageParams().size; - checkFileSize(); - } - private void checkFileSize() { changeStatus(STATUS_CHECKING); new Thread(new FileSizeChecker()).start(); @@ -74,6 +67,9 @@ public class HttpConnection implements Downloadable { } private void finish() { + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(Uri.fromFile(file)); + mXmppConnectionService.sendBroadcast(intent); message.setDownloadable(null); mHttpConnectionManager.finishConnection(this); } @@ -96,8 +92,7 @@ public class HttpConnection implements Downloadable { } file.setExpectedSize(size); message.setType(Message.TYPE_IMAGE); - if (size <= mHttpConnectionManager.getAutoAcceptFileSize() - || size == mPreviousFileSize) { + if (size <= mHttpConnectionManager.getAutoAcceptFileSize() && mAutostart) { start(); } else { changeStatus(STATUS_OFFER); diff --git a/src/eu/siacs/conversations/http/HttpConnectionManager.java b/src/eu/siacs/conversations/http/HttpConnectionManager.java index 011ecc3f..ff71d45c 100644 --- a/src/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/eu/siacs/conversations/http/HttpConnectionManager.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; @@ -23,13 +24,6 @@ public class HttpConnectionManager extends AbstractConnectionManager { return connection; } - public HttpConnection createNewConnection(Message message, URL url) { - HttpConnection connection = new HttpConnection(this); - connection.init(message, url); - this.connections.add(connection); - return connection; - } - public void finishConnection(HttpConnection connection) { this.connections.remove(connection); } diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 35aa9042..72c620a7 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -34,7 +34,6 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.services.ImageProvider; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.pep.Avatar; @@ -66,34 +65,11 @@ public class FileBackend { return thumbnailCache; } - public DownloadableFile getJingleFileLegacy(Message message) { - return getJingleFileLegacy(message, true); + public DownloadableFile getFile(Message message) { + return getFile(message, true); } - public DownloadableFile getJingleFileLegacy(Message message, - boolean decrypted) { - Conversation conversation = message.getConversation(); - String prefix = context.getFilesDir().getAbsolutePath(); - String path = prefix + "/" + conversation.getAccount().getJid() + "/" - + conversation.getContactJid(); - String filename; - if ((decrypted) || (message.getEncryption() == Message.ENCRYPTION_NONE)) { - filename = message.getUuid() + ".webp"; - } else { - if (message.getEncryption() == Message.ENCRYPTION_OTR) { - filename = message.getUuid() + ".webp"; - } else { - filename = message.getUuid() + ".webp.pgp"; - } - } - return new DownloadableFile(path + "/" + filename); - } - - public DownloadableFile getJingleFile(Message message) { - return getConversationsFile(message, true); - } - - public DownloadableFile getConversationsFile(Message message, + public DownloadableFile getFile(Message message, boolean decrypted) { StringBuilder filename = new StringBuilder(); filename.append(Environment.getExternalStoragePublicDirectory( @@ -151,7 +127,7 @@ public class FileBackend { try { InputStream is = context.getContentResolver() .openInputStream(image); - DownloadableFile file = getJingleFile(message); + DownloadableFile file = getFile(message); file.getParentFile().mkdirs(); file.createNewFile(); Bitmap originalBitmap; @@ -240,7 +216,7 @@ public class FileBackend { } public Bitmap getImageFromMessage(Message message) { - return BitmapFactory.decodeFile(getJingleFile(message) + return BitmapFactory.decodeFile(getFile(message) .getAbsolutePath()); } @@ -248,10 +224,7 @@ public class FileBackend { throws FileNotFoundException { Bitmap thumbnail = thumbnailCache.get(message.getUuid()); if ((thumbnail == null) && (!cacheOnly)) { - File file = getJingleFile(message); - if (!file.exists()) { - file = getJingleFileLegacy(message); - } + File file = getFile(message); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = calcSampleSize(file, size); Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(), @@ -447,12 +420,8 @@ public class FileBackend { } public Uri getJingleFileUri(Message message) { - File file = getJingleFile(message); - if (file.exists()) { - return Uri.parse("file://" + file.getAbsolutePath()); - } else { - return ImageProvider.getProviderUri(message); - } + File file = getFile(message); + return Uri.parse("file://" + file.getAbsolutePath()); } public class ImageCopyException extends Exception { @@ -476,4 +445,8 @@ public class FileBackend { } return cropCenterSquare(bm, UIHelper.getRealPx(size, context)); } + + public boolean isFileAvailable(Message message) { + return getFile(message).exists(); + } } diff --git a/src/eu/siacs/conversations/services/ImageProvider.java b/src/eu/siacs/conversations/services/ImageProvider.java deleted file mode 100644 index ac78a454..00000000 --- a/src/eu/siacs/conversations/services/ImageProvider.java +++ /dev/null @@ -1,109 +0,0 @@ -package eu.siacs.conversations.services; - -import java.io.File; -import java.io.FileNotFoundException; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.persistance.DatabaseBackend; -import eu.siacs.conversations.persistance.FileBackend; -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -public class ImageProvider extends ContentProvider { - - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - ParcelFileDescriptor pfd; - FileBackend fileBackend = new FileBackend(getContext()); - if ("r".equals(mode)) { - DatabaseBackend databaseBackend = DatabaseBackend - .getInstance(getContext()); - String uuids = uri.getPath(); - Log.d(Config.LOGTAG, "uuids = " + uuids + " mode=" + mode); - if (uuids == null) { - throw new FileNotFoundException(); - } - String[] uuidsSplited = uuids.split("/", 2); - if (uuidsSplited.length != 3) { - throw new FileNotFoundException(); - } - String conversationUuid = uuidsSplited[1]; - String messageUuid = uuidsSplited[2].split("\\.")[0]; - - Log.d(Config.LOGTAG, "messageUuid=" + messageUuid); - - Conversation conversation = databaseBackend - .findConversationByUuid(conversationUuid); - if (conversation == null) { - throw new FileNotFoundException("conversation " - + conversationUuid + " could not be found"); - } - Message message = databaseBackend.findMessageByUuid(messageUuid); - if (message == null) { - throw new FileNotFoundException("message " + messageUuid - + " could not be found"); - } - - Account account = databaseBackend.findAccountByUuid(conversation - .getAccountUuid()); - if (account == null) { - throw new FileNotFoundException("account " - + conversation.getAccountUuid() + " cound not be found"); - } - message.setConversation(conversation); - conversation.setAccount(account); - - File file = fileBackend.getJingleFileLegacy(message); - pfd = ParcelFileDescriptor.open(file, - ParcelFileDescriptor.MODE_READ_ONLY); - return pfd; - } else { - throw new FileNotFoundException(); - } - } - - @Override - public int delete(Uri arg0, String arg1, String[] arg2) { - return 0; - } - - @Override - public String getType(Uri arg0) { - return null; - } - - @Override - public Uri insert(Uri arg0, ContentValues arg1) { - return null; - } - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, - String arg4) { - return null; - } - - @Override - public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { - return 0; - } - - public static Uri getProviderUri(Message message) { - return Uri.parse("content://eu.siacs.conversations.images/" - + message.getConversationUuid() + "/" + message.getUuid() - + ".webp"); - } -} \ No newline at end of file diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 07897f8c..04d5711a 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -27,6 +27,7 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions.OnRenameListener; @@ -797,11 +798,21 @@ public class XmppConnectionService extends Service { Account account = accountLookupTable.get(conv.getAccountUuid()); conv.setAccount(account); conv.setMessages(databaseBackend.getMessages(conv, 50)); + checkDeletedFiles(conv); } } - return this.conversations; } + + private void checkDeletedFiles(Conversation conversation) { + for(Message message : conversation.getMessages()) { + if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP) { + if (!getFileBackend().isFileAvailable(message)) { + message.setDownloadable(new DeletedDownloadable()); + } + } + } + } public void populateWithOrderedConversations(List list) { populateWithOrderedConversations(list, true); @@ -1833,4 +1844,23 @@ public class XmppConnectionService extends Service { public HttpConnectionManager getHttpConnectionManager() { return this.mHttpConnectionManager; } + + private class DeletedDownloadable implements Downloadable { + + @Override + public void start() { + return; + } + + @Override + public int getStatus() { + return Downloadable.STATUS_DELETED; + } + + @Override + public long getFileSize() { + return 0; + } + + } } diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 6943a85c..bd37f7fc 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -92,6 +92,8 @@ public class ConversationAdapter extends ArrayAdapter { mLastMessage.setText(R.string.receiving_image); } else if (d.getStatus() == Downloadable.STATUS_OFFER) { mLastMessage.setText(R.string.image_offered_for_download); + } else if (d.getStatus() == Downloadable.STATUS_DELETED) { + mLastMessage.setText(R.string.image_file_deleted); } else { mLastMessage.setText(""); } diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index efb07292..24a824b3 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1,7 +1,5 @@ package eu.siacs.conversations.ui.adapter; -import java.net.MalformedURLException; -import java.net.URL; import java.util.HashMap; import java.util.List; @@ -476,6 +474,8 @@ public class MessageAdapter extends ArrayAdapter { } else if (d != null && d.getStatus() == Downloadable.STATUS_CHECKING) { displayInfoMessage(viewHolder, R.string.checking_image); + } else if (d != null && d.getStatus() == Downloadable.STATUS_DELETED) { + displayInfoMessage(viewHolder, R.string.image_file_deleted); } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER) { viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); @@ -531,19 +531,7 @@ public class MessageAdapter extends ArrayAdapter { downloadable.start(); return true; } else { - ImageParams params = message.getImageParams(); - if (params.origin != null) { - try { - URL url = new URL(params.origin); - activity.xmppConnectionService.getHttpConnectionManager() - .createNewConnection(message, url); - return true; - } catch (MalformedURLException e) { - return false; - } - } else { - return false; - } + return false; } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 8e4714f4..bfc3c18c 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -327,7 +327,7 @@ public class JingleConnection implements Downloadable { .push(message); } this.file = this.mXmppConnectionService.getFileBackend() - .getConversationsFile(message, false); + .getFile(message, false); if (message.getEncryption() == Message.ENCRYPTION_OTR) { byte[] key = conversation.getSymmetricKey(); if (key == null) { @@ -359,7 +359,7 @@ public class JingleConnection implements Downloadable { if (message.getType() == Message.TYPE_IMAGE) { content.setTransportId(this.transportId); this.file = this.mXmppConnectionService.getFileBackend() - .getConversationsFile(message, false); + .getFile(message, false); if (message.getEncryption() == Message.ENCRYPTION_OTR) { Conversation conversation = this.message.getConversation(); this.mXmppConnectionService.renewSymmetricKey(conversation); -- cgit v1.2.3 From 88d88ffb7b704e2ae5a2eaf1af6e8a21fb0fb574 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 16 Oct 2014 02:39:02 +0200 Subject: added file observer to get notified when files are deleted: fixes #396 --- .../conversations/persistance/FileBackend.java | 9 +++++--- .../services/XmppConnectionService.java | 26 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 72c620a7..74918670 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -72,9 +72,7 @@ public class FileBackend { public DownloadableFile getFile(Message message, boolean decrypted) { StringBuilder filename = new StringBuilder(); - filename.append(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES).getAbsolutePath()); - filename.append("/Conversations/"); + filename.append(getConversationsDirectory()); filename.append(message.getUuid()); if ((decrypted) || (message.getEncryption() == Message.ENCRYPTION_NONE)) { filename.append(".webp"); @@ -87,6 +85,11 @@ public class FileBackend { } return new DownloadableFile(filename.toString()); } + + public static String getConversationsDirectory() { + return Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES).getAbsolutePath()+"/Conversations/"; + } public Bitmap resize(Bitmap originalBitmap, int size) { int w = originalBitmap.getWidth(); diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 04d5711a..9a540df0 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -76,6 +76,7 @@ import android.net.NetworkInfo; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.FileObserver; import android.os.IBinder; import android.os.PowerManager; import android.os.PowerManager.WakeLock; @@ -143,6 +144,16 @@ public class XmppConnectionService extends Service { startService(intent); } }; + + private FileObserver fileObserver = new FileObserver(FileBackend.getConversationsDirectory()) { + + @Override + public void onEvent(int event, String path) { + if (event == FileObserver.DELETE) { + markFileDeleted(path.split("\\.")[0]); + } + } + }; private final IBinder mBinder = new XmppConnectionBinder(); private OnStatusChanged statusListener = new OnStatusChanged() { @@ -424,6 +435,7 @@ public class XmppConnectionService extends Service { getContentResolver().registerContentObserver( ContactsContract.Contacts.CONTENT_URI, true, contactObserver); + this.fileObserver.startWatching(); this.pgpServiceConnection = new OpenPgpServiceConnection( getApplicationContext(), "org.sufficientlysecure.keychain"); this.pgpServiceConnection.bindToService(); @@ -813,6 +825,20 @@ public class XmppConnectionService extends Service { } } } + + private void markFileDeleted(String uuid) { + for(Conversation conversation : getConversations()) { + for(Message message : conversation.getMessages()) { + if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getUuid().equals(uuid)) { + if (!getFileBackend().isFileAvailable(message)) { + message.setDownloadable(new DeletedDownloadable()); + updateConversationUi(); + } + return; + } + } + } + } public void populateWithOrderedConversations(List list) { populateWithOrderedConversations(list, true); -- cgit v1.2.3 From 45e0f99b8841ed64f70c29e5c986509693833f92 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 16 Oct 2014 15:29:39 +0200 Subject: make image download message to type=image only after completion --- src/eu/siacs/conversations/http/HttpConnection.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 34036412..b0c230d0 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -62,8 +62,7 @@ public class HttpConnection implements Downloadable { public void cancel() { mHttpConnectionManager.finishConnection(this); message.setDownloadable(null); - message.setBody(mUrl.toString()); - mXmppConnectionService.updateMessage(message); + mXmppConnectionService.updateConversationUi(); } private void finish() { @@ -91,7 +90,6 @@ public class HttpConnection implements Downloadable { return; } file.setExpectedSize(size); - message.setType(Message.TYPE_IMAGE); if (size <= mHttpConnectionManager.getAutoAcceptFileSize() && mAutostart) { start(); } else { @@ -159,6 +157,7 @@ public class HttpConnection implements Downloadable { int imageWidth = options.outWidth; message.setBody(mUrl.toString() + "," + file.getSize() + ',' + imageWidth + ',' + imageHeight); + message.setType(Message.TYPE_IMAGE); mXmppConnectionService.updateMessage(message); } -- cgit v1.2.3 From 6cfb14a2e40b0ecf912f13d2a84af24b56d607cc Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 16 Oct 2014 15:39:09 +0200 Subject: forground/background logging without csi --- src/eu/siacs/conversations/services/XmppConnectionService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 9a540df0..33bddae6 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1110,11 +1110,10 @@ public class XmppConnectionService extends Service { XmppConnection connection = account.getXmppConnection(); if (connection != null && connection.getFeatures().csi()) { connection.sendActive(); - Log.d(Config.LOGTAG, account.getJid() - + " sending csi//active"); } } } + Log.d(Config.LOGTAG,"app switched into foreground"); } private void switchToBackground() { @@ -1123,11 +1122,10 @@ public class XmppConnectionService extends Service { XmppConnection connection = account.getXmppConnection(); if (connection != null && connection.getFeatures().csi()) { connection.sendInactive(); - Log.d(Config.LOGTAG, account.getJid() - + " sending csi//inactive"); } } } + Log.d(Config.LOGTAG,"app switched into background"); } private boolean isScreenOn() { -- cgit v1.2.3 From c1a55608df588df12b562598e985f427cdd9a9db Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 16 Oct 2014 15:53:44 +0200 Subject: log ending otr sessions on disconnect --- src/eu/siacs/conversations/entities/Conversation.java | 7 ++++++- src/eu/siacs/conversations/services/XmppConnectionService.java | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index 5f204ec2..e29981fd 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -297,18 +297,23 @@ public class Conversation extends AbstractEntity { } } - public void endOtrIfNeeded() { + public boolean endOtrIfNeeded() { if (this.otrSession != null) { if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) { try { this.otrSession.endSession(); this.resetOtrSession(); + return true; } catch (OtrException e) { this.resetOtrSession(); + return false; } } else { this.resetOtrSession(); + return false; } + } else { + return false; } } diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 33bddae6..2ee4fc79 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1269,7 +1269,7 @@ public class XmppConnectionService extends Service { conversation.getMucOptions().setOffline(); conversation.deregisterWithBookmark(); Log.d(Config.LOGTAG, conversation.getAccount().getJid() - + " leaving muc " + conversation.getContactJid()); + + ": leaving muc " + conversation.getContactJid()); } else { account.pendingConferenceLeaves.add(conversation); } @@ -1286,7 +1286,9 @@ public class XmppConnectionService extends Service { if (conversation.getMode() == Conversation.MODE_MULTI) { leaveMuc(conversation); } else { - conversation.endOtrIfNeeded(); + if (conversation.endOtrIfNeeded()) { + Log.d(Config.LOGTAG,account.getJid()+": ended otr session with "+conversation.getContactJid()); + } } } } -- cgit v1.2.3 From c4b9d428616ba3efcea00a88158f12922d876e42 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Thu, 16 Oct 2014 10:02:47 -0400 Subject: Enable all supported protocols including TLSv1.1 and 1.2 --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 43614f50..0162af9e 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -519,6 +519,7 @@ public class XmppConnection implements Runnable { SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true); + sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols()); if (verifier != null && !verifier.verify(account.getServer(), -- cgit v1.2.3 From 0fd634ae52a0e6b8d58c88b687cffe9db7d39956 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 16 Oct 2014 16:09:54 +0200 Subject: simplified determination whether otr needs starting in a session --- src/eu/siacs/conversations/entities/Conversation.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index e29981fd..c984933f 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -72,8 +72,6 @@ public class Conversation extends AbstractEntity { private byte[] symmetricKey; - private boolean otrSessionNeedsStarting = false; - private Bookmark bookmark; public Conversation(String name, Account account, String contactJid, @@ -264,10 +262,7 @@ public class Conversation extends AbstractEntity { try { if (sendStart) { this.otrSession.startSession(); - this.otrSessionNeedsStarting = false; return this.otrSession; - } else { - this.otrSessionNeedsStarting = true; } return this.otrSession; } catch (OtrException e) { @@ -283,12 +278,12 @@ public class Conversation extends AbstractEntity { public void resetOtrSession() { this.otrFingerprint = null; - this.otrSessionNeedsStarting = false; this.otrSession = null; } public void startOtrIfNeeded() { - if (this.otrSession != null && this.otrSessionNeedsStarting) { + if (this.otrSession != null + && this.otrSession.getSessionStatus() != SessionStatus.ENCRYPTED) { try { this.otrSession.startSession(); } catch (OtrException e) { -- cgit v1.2.3 From 5e3caf962696d3fe39e7ce70274530aa4f77d134 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 16 Oct 2014 19:10:37 +0200 Subject: additonal safty net for disabling notifications --- src/eu/siacs/conversations/services/XmppConnectionService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 2ee4fc79..8007191f 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1125,6 +1125,7 @@ public class XmppConnectionService extends Service { } } } + this.mNotificationService.setIsInForeground(false); Log.d(Config.LOGTAG,"app switched into background"); } -- cgit v1.2.3 From c725da954c5b2c4a8dc7014f5468bc14ecb5a5f8 Mon Sep 17 00:00:00 2001 From: Frank Zschockelt Date: Thu, 16 Oct 2014 23:31:48 +0200 Subject: try all srv responses if necessary --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 43614f50..9755be6a 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -161,10 +161,23 @@ public class XmppConnection implements Runnable { + "[" + srvIpServer + "]:" + srvRecordPort); socket = new Socket(srvIpServer, srvRecordPort); } else { - Log.d(Config.LOGTAG, account.getJid() - + ": using values from dns " + srvRecordServer - + ":" + srvRecordPort); - socket = new Socket(srvRecordServer, srvRecordPort); + boolean socketError = true; + int srvIndex = 0; + while (socketError && namePort.containsKey("name" + srvIndex)){ + try { + srvRecordServer = namePort.getString("name" + srvIndex); + srvRecordPort = namePort.getInt("port" + srvIndex); + Log.d(Config.LOGTAG, account.getJid() + + ": using values from dns " + srvRecordServer + + ":" + srvRecordPort); + socket = new Socket(srvRecordServer, srvRecordPort); + socketError = false; + } catch (UnknownHostException e) { + srvIndex++; + } catch (IOException e) { + srvIndex++; + } + } } } else if (namePort.containsKey("error") && "nosrv".equals(namePort.getString("error", null))) { -- cgit v1.2.3 From 3372e50155ac16c9eabce9a484914c2acbf391c8 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 17 Oct 2014 11:01:38 +0200 Subject: made grace period on a per account basis --- src/eu/siacs/conversations/Config.java | 2 +- src/eu/siacs/conversations/entities/Account.java | 27 ++++++++++++++++------ .../siacs/conversations/parser/MessageParser.java | 6 ++--- .../siacs/conversations/parser/PresenceParser.java | 3 +-- .../services/NotificationService.java | 25 ++++---------------- .../services/XmppConnectionService.java | 4 +--- 6 files changed, 30 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/Config.java b/src/eu/siacs/conversations/Config.java index a11e1763..1725eca6 100644 --- a/src/eu/siacs/conversations/Config.java +++ b/src/eu/siacs/conversations/Config.java @@ -10,7 +10,7 @@ public final class Config { public static final int PING_MIN_INTERVAL = 30; public static final int PING_TIMEOUT = 10; public static final int CONNECT_TIMEOUT = 90; - public static final int CARBON_GRACE_PERIOD = 120; + public static final int CARBON_GRACE_PERIOD = 60; public static final int AVATAR_SIZE = 192; public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.WEBP; diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java index 9b1cbcab..ff509ba1 100644 --- a/src/eu/siacs/conversations/entities/Account.java +++ b/src/eu/siacs/conversations/entities/Account.java @@ -11,6 +11,7 @@ import net.java.otr4j.crypto.OtrCryptoException; import org.json.JSONException; import org.json.JSONObject; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrEngine; import eu.siacs.conversations.persistance.FileBackend; @@ -21,6 +22,7 @@ import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; +import android.os.SystemClock; public class Account extends AbstractEntity { @@ -64,16 +66,14 @@ public class Account extends AbstractEntity { protected boolean online = false; - transient OtrEngine otrEngine = null; - transient XmppConnection xmppConnection = null; - transient protected Presences presences = new Presences(); - + private OtrEngine otrEngine = null; + private XmppConnection xmppConnection = null; + private Presences presences = new Presences(); + private long mEndGracePeriod = 0L; private String otrFingerprint; - private Roster roster = null; - + private List bookmarks = new CopyOnWriteArrayList(); - public List pendingConferenceJoins = new CopyOnWriteArrayList(); public List pendingConferenceLeaves = new CopyOnWriteArrayList(); @@ -401,4 +401,17 @@ public class Account extends AbstractEntity { return R.string.account_status_unknown; } } + + public void activateGracePeriod() { + this.mEndGracePeriod = SystemClock.elapsedRealtime() + + (Config.CARBON_GRACE_PERIOD * 1000); + } + + public void deactivateGracePeriod() { + this.mEndGracePeriod = 0L; + } + + public boolean inGracePeriod() { + return SystemClock.elapsedRealtime() < this.mEndGracePeriod; + } } diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index 486dd389..4090ed39 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -417,8 +417,7 @@ public class MessageParser extends AbstractParser implements message = this.parseCarbonMessage(packet, account); if (message != null) { if (message.getStatus() == Message.STATUS_SEND) { - mXmppConnectionService.getNotificationService() - .activateGracePeriod(); + account.activateGracePeriod(); notify = false; mXmppConnectionService.markRead( message.getConversation(), false); @@ -440,8 +439,7 @@ public class MessageParser extends AbstractParser implements } else { mXmppConnectionService.markRead(message.getConversation(), false); - mXmppConnectionService.getNotificationService() - .activateGracePeriod(); + account.activateGracePeriod(); notify = false; } } diff --git a/src/eu/siacs/conversations/parser/PresenceParser.java b/src/eu/siacs/conversations/parser/PresenceParser.java index 2c3a7dbc..d54ddca0 100644 --- a/src/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/eu/siacs/conversations/parser/PresenceParser.java @@ -58,8 +58,7 @@ public class PresenceParser extends AbstractParser implements Presences.parseShow(packet.findChild("show"))); } else if (type.equals("unavailable")) { account.removePresence(fromParts[1]); - mXmppConnectionService.getNotificationService() - .deactivateGracePeriod(); + account.deactivateGracePeriod(); } } } else { diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index e65085fb..1983e581 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -20,6 +20,7 @@ import android.text.Html; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; @@ -34,9 +35,7 @@ public class NotificationService { public int NOTIFICATION_ID = 0x2342; private Conversation mOpenConversation; private boolean mIsInForeground; - - private long mEndGracePeriod = 0L; - + public NotificationService(XmppConnectionService service) { this.mXmppConnectionService = service; this.mNotificationManager = (NotificationManager) service @@ -62,8 +61,9 @@ public class NotificationService { notifications.put(conversationUuid, mList); } } + Account account = message.getConversation().getAccount(); updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) - && !inGracePeriod()); + && !account.inGracePeriod()); } public void clear() { @@ -170,9 +170,7 @@ public class NotificationService { } } mBuilder.setDeleteIntent(createDeleteIntent()); - if (!inGracePeriod()) { - mBuilder.setLights(0xffffffff, 2000, 4000); - } + mBuilder.setLights(0xffffffff, 2000, 4000); Notification notification = mBuilder.build(); mNotificationManager.notify(NOTIFICATION_ID, notification); } @@ -231,17 +229,4 @@ public class NotificationService { public void setIsInForeground(boolean foreground) { this.mIsInForeground = foreground; } - - public void activateGracePeriod() { - this.mEndGracePeriod = SystemClock.elapsedRealtime() - + (Config.CARBON_GRACE_PERIOD * 1000); - } - - public void deactivateGracePeriod() { - this.mEndGracePeriod = 0L; - } - - private boolean inGracePeriod() { - return SystemClock.elapsedRealtime() < this.mEndGracePeriod; - } } diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 8007191f..4a680228 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -529,6 +529,7 @@ public class XmppConnectionService extends Service { synchronized public void sendMessage(Message message) { Account account = message.getConversation().getAccount(); + account.deactivateGracePeriod(); Conversation conv = message.getConversation(); MessagePacket packet = null; boolean saveInDb = true; @@ -1019,7 +1020,6 @@ public class XmppConnectionService extends Service { return; } synchronized (this.convChangedListenerCount) { - this.mNotificationService.deactivateGracePeriod(); if (checkListeners()) { switchToForeground(); } @@ -1049,7 +1049,6 @@ public class XmppConnectionService extends Service { return; } synchronized (this.accountChangedListenerCount) { - this.mNotificationService.deactivateGracePeriod(); if (checkListeners()) { switchToForeground(); } @@ -1077,7 +1076,6 @@ public class XmppConnectionService extends Service { return; } synchronized (this.rosterChangedListenerCount) { - this.mNotificationService.deactivateGracePeriod(); if (checkListeners()) { switchToForeground(); } -- cgit v1.2.3 From 0605390144b85dfe3531ad47cfa276f9f5c8ba5b Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 17 Oct 2014 13:09:02 +0200 Subject: do not attempt to download images when not connected --- .../siacs/conversations/entities/Downloadable.java | 2 +- .../siacs/conversations/http/HttpConnection.java | 13 +++++-- .../conversations/http/HttpConnectionManager.java | 2 -- .../services/NotificationService.java | 2 -- .../services/XmppConnectionService.java | 20 ++++++----- .../conversations/ui/adapter/MessageAdapter.java | 42 ++++++++++++---------- .../xmpp/jingle/JingleConnection.java | 23 ++++++------ 7 files changed, 59 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Downloadable.java b/src/eu/siacs/conversations/entities/Downloadable.java index c8ca599f..36584ab0 100644 --- a/src/eu/siacs/conversations/entities/Downloadable.java +++ b/src/eu/siacs/conversations/entities/Downloadable.java @@ -12,7 +12,7 @@ public interface Downloadable { public static final int STATUS_DOWNLOADING = 0x204; public static final int STATUS_DELETED = 0x205; - public void start(); + public boolean start(); public int getStatus(); diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index b0c230d0..0254dc2f 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -12,7 +12,9 @@ import javax.net.ssl.HttpsURLConnection; import android.content.Intent; import android.graphics.BitmapFactory; import android.net.Uri; +import android.util.Log; +import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; @@ -35,9 +37,14 @@ public class HttpConnection implements Downloadable { } @Override - public void start() { - changeStatus(STATUS_DOWNLOADING); - new Thread(new FileDownloader()).start(); + public boolean start() { + if (mXmppConnectionService.hasInternetConnection()) { + changeStatus(STATUS_DOWNLOADING); + new Thread(new FileDownloader()).start(); + return true; + } else { + return false; + } } public void init(Message message) { diff --git a/src/eu/siacs/conversations/http/HttpConnectionManager.java b/src/eu/siacs/conversations/http/HttpConnectionManager.java index ff71d45c..9a2a2405 100644 --- a/src/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/eu/siacs/conversations/http/HttpConnectionManager.java @@ -1,11 +1,9 @@ package eu.siacs.conversations.http; -import java.net.URL; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 1983e581..0b30e58e 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -13,12 +13,10 @@ import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.PowerManager; -import android.os.SystemClock; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.text.Html; -import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 4a680228..36ea350b 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -346,15 +346,10 @@ public class XmppConnectionService extends Service { } } this.wakeLock.acquire(); - ConnectivityManager cm = (ConnectivityManager) getApplicationContext() - .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - boolean isConnected = activeNetwork != null - && activeNetwork.isConnected(); - + for (Account account : accounts) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { - if (!isConnected) { + if (!hasInternetConnection()) { account.setStatus(Account.STATUS_NO_INTERNET); if (statusListener != null) { statusListener.onStatusChanged(account); @@ -412,6 +407,13 @@ public class XmppConnectionService extends Service { } return START_STICKY; } + + public boolean hasInternetConnection() { + ConnectivityManager cm = (ConnectivityManager) getApplicationContext() + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + return activeNetwork != null && activeNetwork.isConnected(); + } @SuppressLint("TrulyRandom") @Override @@ -1873,8 +1875,8 @@ public class XmppConnectionService extends Service { private class DeletedDownloadable implements Downloadable { @Override - public void start() { - return; + public boolean start() { + return false; } @Override diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 24a824b3..6b2a0094 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -102,7 +102,8 @@ public class MessageAdapter extends ArrayAdapter { } boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI && message.getMergedStatus() <= Message.STATUS_RECEIVED; - if (message.getType() == Message.TYPE_IMAGE) { + if (message.getType() == Message.TYPE_IMAGE + || message.getDownloadable() != null) { ImageParams params = message.getImageParams(); if (params.size != 0) { filesize = params.size / 1024 + " KB"; @@ -262,6 +263,20 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.messageBody.setTextIsSelectable(true); } + private void displayDownloadableMessage(ViewHolder viewHolder, + final Message message) { + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.download_button.setVisibility(View.VISIBLE); + viewHolder.download_button.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + startDonwloadable(message); + } + }); + } + private void displayImageMessage(ViewHolder viewHolder, final Message message) { if (viewHolder.download_button != null) { @@ -474,20 +489,11 @@ public class MessageAdapter extends ArrayAdapter { } else if (d != null && d.getStatus() == Downloadable.STATUS_CHECKING) { displayInfoMessage(viewHolder, R.string.checking_image); - } else if (d != null && d.getStatus() == Downloadable.STATUS_DELETED) { + } else if (d != null + && d.getStatus() == Downloadable.STATUS_DELETED) { displayInfoMessage(viewHolder, R.string.image_file_deleted); } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER) { - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.GONE); - viewHolder.download_button.setVisibility(View.VISIBLE); - viewHolder.download_button - .setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - startDonwloadable(item); - } - }); + displayDownloadableMessage(viewHolder, item); } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED) || (item.getEncryption() == Message.ENCRYPTION_NONE) || (item.getEncryption() == Message.ENCRYPTION_OTR)) { @@ -525,13 +531,13 @@ public class MessageAdapter extends ArrayAdapter { return view; } - public boolean startDonwloadable(Message message) { + public void startDonwloadable(Message message) { Downloadable downloadable = message.getDownloadable(); if (downloadable != null) { - downloadable.start(); - return true; - } else { - return false; + if (!downloadable.start()) { + Toast.makeText(activity, R.string.not_connected_try_again, + Toast.LENGTH_SHORT).show(); + } } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index bfc3c18c..e7e1a33d 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -875,17 +875,20 @@ public class JingleConnection implements Downloadable { return this.transport; } - public void start() { - if (mJingleStatus == JINGLE_STATUS_INITIATED) { - new Thread(new Runnable() { - - @Override - public void run() { - sendAccept(); - } - }).start(); + public boolean start() { + if (account.getStatus() == Account.STATUS_ONLINE) { + if (mJingleStatus == JINGLE_STATUS_INITIATED) { + new Thread(new Runnable() { + + @Override + public void run() { + sendAccept(); + } + }).start(); + } + return true; } else { - Log.d(Config.LOGTAG, "status (" + mJingleStatus + ") was not ok"); + return false; } } -- cgit v1.2.3 From 113b7d17361a7da7ae08b0845011070e0c005fc5 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Sat, 18 Oct 2014 15:56:59 -0400 Subject: Remove support for legacy SSL --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 0162af9e..1ac6cb2b 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -10,6 +10,7 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import java.util.List; @@ -519,7 +520,14 @@ public class XmppConnection implements Runnable { SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true); - sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols()); + + // Support all protocols except legacy SSL. + // The min SDK version prevents us having to worry about SSLv2. In future, this may be + // true of SSLv3 as well. + final List supportedProtocols = new LinkedList(Arrays.asList( + sslSocket.getSupportedProtocols())); + supportedProtocols.remove("SSLv3"); + sslSocket.setEnabledProtocols(supportedProtocols.toArray(new String[supportedProtocols.size()])); if (verifier != null && !verifier.verify(account.getServer(), -- cgit v1.2.3 From e8bf75d79b74637d369d2a7134416c1f0852c420 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 19 Oct 2014 20:48:01 +0200 Subject: force tls --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 9755be6a..be56927c 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -80,6 +80,7 @@ public class XmppConnection implements Runnable { private SparseArray messageReceipts = new SparseArray(); private boolean usingCompression = false; + private boolean usingEncryption = false; private int stanzasReceived = 0; private int stanzasSent = 0; @@ -135,6 +136,7 @@ public class XmppConnection implements Runnable { protected void connect() { Log.d(Config.LOGTAG, account.getJid() + ": connecting"); usingCompression = false; + usingEncryption = false; lastConnect = SystemClock.elapsedRealtime(); lastPingSent = SystemClock.elapsedRealtime(); this.attempt++; @@ -546,6 +548,7 @@ public class XmppConnection implements Runnable { sendStartStream(); Log.d(Config.LOGTAG, account.getJid() + ": TLS connection established"); + usingEncryption = true; processStream(tagReader.readTag()); sslSocket.close(); } catch (NoSuchAlgorithmException e1) { @@ -575,8 +578,7 @@ public class XmppConnection implements Runnable { private void processStreamFeatures(Tag currentTag) throws XmlPullParserException, IOException { this.streamFeatures = tagReader.readElement(currentTag); - if (this.streamFeatures.hasChild("starttls") - && account.isOptionSet(Account.OPTION_USETLS)) { + if (this.streamFeatures.hasChild("starttls") && !usingEncryption) { sendStartTLS(); } else if (compressionAvailable()) { sendCompressionZlib(); @@ -588,7 +590,7 @@ public class XmppConnection implements Runnable { changeStatus(Account.STATUS_REGISTRATION_NOT_SUPPORTED); disconnect(true); } else if (this.streamFeatures.hasChild("mechanisms") - && shouldAuthenticate) { + && shouldAuthenticate && usingEncryption) { List mechanisms = extractMechanisms(streamFeatures .findChild("mechanisms")); if (mechanisms.contains("PLAIN")) { -- cgit v1.2.3 From 6c7c3ddf15aebaedbd4c62e7771bb7e378ebf4ad Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Sun, 19 Oct 2014 15:53:03 -0400 Subject: Add "Enable legacy SSL" preference --- .../siacs/conversations/xmpp/XmppConnection.java | 44 ++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 1ac6cb2b..43469f08 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; +import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; @@ -27,15 +28,19 @@ import org.xmlpull.v1.XmlPullParserException; import de.duenndns.ssl.MemorizingTrustManager; +import android.content.Context; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; +import android.preference.PreferenceManager; import android.util.Log; import android.util.SparseArray; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.ui.StartConversationActivity; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.DNSHelper; import eu.siacs.conversations.utils.zlib.ZLibOutputStream; @@ -105,6 +110,7 @@ public class XmppConnection implements Runnable { private OnBindListener bindListener = null; private OnMessageAcknowledged acknowledgedListener = null; private MemorizingTrustManager mMemorizingTrustManager; + private final Context applicationContext; public XmppConnection(Account account, XmppConnectionService service) { this.mRandom = service.getRNG(); @@ -113,6 +119,7 @@ public class XmppConnection implements Runnable { this.wakeLock = service.getPowerManager().newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, account.getJid()); tagWriter = new TagWriter(); + applicationContext = service.getApplicationContext(); } protected void changeStatus(int nextStatus) { @@ -363,13 +370,13 @@ public class XmppConnection implements Runnable { iq.addChild("ping", "urn:xmpp:ping"); this.sendIqPacket(iq, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - Log.d(Config.LOGTAG, account.getJid() - + ": online with resource " + account.getResource()); - changeStatus(Account.STATUS_ONLINE); - } - }); + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + Log.d(Config.LOGTAG, account.getJid() + + ": online with resource " + account.getResource()); + changeStatus(Account.STATUS_ONLINE); + } + }); } private Element processPacket(Tag currentTag, int packetType) @@ -505,6 +512,14 @@ public class XmppConnection implements Runnable { tagWriter.writeTag(startTLS); } + private SharedPreferences getPreferences() { + return PreferenceManager.getDefaultSharedPreferences(applicationContext); + } + + private boolean enableLegacySSL() { + return getPreferences().getBoolean("enable_legacy_ssl", true); + } + private void switchOverToTls(Tag currentTag) throws XmlPullParserException, IOException { tagReader.readTag(); @@ -524,10 +539,17 @@ public class XmppConnection implements Runnable { // Support all protocols except legacy SSL. // The min SDK version prevents us having to worry about SSLv2. In future, this may be // true of SSLv3 as well. - final List supportedProtocols = new LinkedList(Arrays.asList( - sslSocket.getSupportedProtocols())); - supportedProtocols.remove("SSLv3"); - sslSocket.setEnabledProtocols(supportedProtocols.toArray(new String[supportedProtocols.size()])); + final String[] supportProtocols; + if (enableLegacySSL()) { + supportProtocols = sslSocket.getSupportedProtocols(); + } else { + final List supportedProtocols = new LinkedList(Arrays.asList( + sslSocket.getSupportedProtocols())); + supportedProtocols.remove("SSLv3"); + supportProtocols = new String[supportedProtocols.size()]; + supportedProtocols.toArray(supportProtocols); + } + sslSocket.setEnabledProtocols(supportProtocols); if (verifier != null && !verifier.verify(account.getServer(), -- cgit v1.2.3 From 99ee049115587b8d914d2df707d8bf152fdd42f6 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Sun, 19 Oct 2014 16:11:35 -0400 Subject: Make legacy SSL option default to false --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 43469f08..0ae51fb5 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -517,7 +517,7 @@ public class XmppConnection implements Runnable { } private boolean enableLegacySSL() { - return getPreferences().getBoolean("enable_legacy_ssl", true); + return getPreferences().getBoolean("enable_legacy_ssl", false); } private void switchOverToTls(Tag currentTag) throws XmlPullParserException, -- cgit v1.2.3 From a201f9e53f33109836a690488b9f8a98db4f5249 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 19 Oct 2014 23:13:55 +0200 Subject: got rid of copyonwrite array list for messages --- .../siacs/conversations/entities/Conversation.java | 30 ++++++++++++---------- .../siacs/conversations/parser/MessageParser.java | 2 +- .../conversations/persistance/DatabaseBackend.java | 10 +++++--- .../xmpp/jingle/JingleConnection.java | 4 ++- 4 files changed, 26 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index c984933f..600b9d38 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -1,8 +1,8 @@ package eu.siacs.conversations.entities; import java.security.interfaces.DSAPublicKey; +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; import org.json.JSONException; import org.json.JSONObject; @@ -57,7 +57,7 @@ public class Conversation extends AbstractEntity { private String nextPresence; - private transient CopyOnWriteArrayList messages = null; + private transient ArrayList messages = new ArrayList(); private transient Account account = null; private transient SessionImpl otrSession; @@ -104,17 +104,6 @@ public class Conversation extends AbstractEntity { } public List getMessages() { - if (messages == null) { - this.messages = new CopyOnWriteArrayList(); // prevent null - // pointer - } - - // populate with Conversation (this) - - for (Message msg : messages) { - msg.setConversation(this); - } - return messages; } @@ -165,7 +154,7 @@ public class Conversation extends AbstractEntity { } } - public void setMessages(CopyOnWriteArrayList msgs) { + public void setMessages(ArrayList msgs) { this.messages = msgs; } @@ -507,4 +496,17 @@ public class Conversation extends AbstractEntity { } } } + + public void add(Message message) { + message.setConversation(this); + synchronized (this.messages) { + this.messages.add(message); + } + } + + public void addAll(int index, List messages) { + synchronized (this.messages) { + this.messages.addAll(index, messages); + } + } } diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index 4090ed39..daf0174c 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -469,7 +469,7 @@ public class MessageParser extends AbstractParser implements } } Conversation conversation = message.getConversation(); - conversation.getMessages().add(message); + conversation.add(message); if (packet.getType() != MessagePacket.TYPE_ERROR) { if (message.getEncryption() == Message.ENCRYPTION_NONE || mXmppConnectionService.saveEncryptedMessages()) { diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java index d90b5c62..d3d6ccf2 100644 --- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -152,14 +152,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { return list; } - public CopyOnWriteArrayList getMessages( + public ArrayList getMessages( Conversation conversations, int limit) { return getMessages(conversations, limit, -1); } - public CopyOnWriteArrayList getMessages(Conversation conversation, + public ArrayList getMessages(Conversation conversation, int limit, long timestamp) { - CopyOnWriteArrayList list = new CopyOnWriteArrayList(); + ArrayList list = new ArrayList(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; if (timestamp == -1) { @@ -178,7 +178,9 @@ public class DatabaseBackend extends SQLiteOpenHelper { if (cursor.getCount() > 0) { cursor.moveToLast(); do { - list.add(Message.fromCursor(cursor)); + Message message = Message.fromCursor(cursor); + message.setConversation(conversation); + list.add(message); } while (cursor.moveToPrevious()); } return list; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index e7e1a33d..5b3dfbff 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -307,7 +307,7 @@ public class JingleConnection implements Downloadable { if (supportedFile) { long size = Long.parseLong(fileSize.getContent()); message.setBody(Long.toString(size)); - conversation.getMessages().add(message); + conversation.add(message); mXmppConnectionService.updateConversationUi(); if (size <= this.mJingleConnectionManager .getAutoAcceptFileSize()) { @@ -634,6 +634,7 @@ public class JingleConnection implements Downloadable { } private void sendFallbackToIbb() { + Log.d(Config.LOGTAG,"sending fallback to ibb"); JinglePacket packet = this.bootstrapPacket("transport-replace"); Content content = new Content(this.contentCreator, this.contentName); this.transportId = this.mJingleConnectionManager.nextRandomId(); @@ -645,6 +646,7 @@ public class JingleConnection implements Downloadable { } private boolean receiveFallbackToIbb(JinglePacket packet) { + Log.d(Config.LOGTAG,"receiving fallack to ibb"); String receivedBlockSize = packet.getJingleContent().ibbTransport() .getAttribute("block-size"); if (receivedBlockSize != null) { -- cgit v1.2.3 From c9238ef5ae2bc0facd89c53afd2c5ed6e16a10a7 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 19 Oct 2014 23:14:17 +0200 Subject: force tls for registrations as well --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index be56927c..debcaa51 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -583,10 +583,10 @@ public class XmppConnection implements Runnable { } else if (compressionAvailable()) { sendCompressionZlib(); } else if (this.streamFeatures.hasChild("register") - && (account.isOptionSet(Account.OPTION_REGISTER))) { + && account.isOptionSet(Account.OPTION_REGISTER) && usingEncryption) { sendRegistryRequest(); } else if (!this.streamFeatures.hasChild("register") - && (account.isOptionSet(Account.OPTION_REGISTER))) { + && account.isOptionSet(Account.OPTION_REGISTER)) { changeStatus(Account.STATUS_REGISTRATION_NOT_SUPPORTED); disconnect(true); } else if (this.streamFeatures.hasChild("mechanisms") @@ -606,6 +606,9 @@ public class XmppConnection implements Runnable { this.tagWriter.writeStanzaAsync(resume); } else if (this.streamFeatures.hasChild("bind") && shouldBind) { sendBindRequest(); + } else { + Log.d(Config.LOGTAG,account.getJid()+": incompatible server. disconnecting"); + disconnect(true); } } -- cgit v1.2.3 From 44f9022d951cb60cf3a56b6ac2459cf08e43ea54 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 19 Oct 2014 23:15:24 +0200 Subject: use new 'api' to add messages to a conversation --- src/eu/siacs/conversations/services/XmppConnectionService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 36ea350b..f557c3e1 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -529,7 +529,7 @@ public class XmppConnectionService extends Service { return connection; } - synchronized public void sendMessage(Message message) { + public void sendMessage(Message message) { Account account = message.getConversation().getAccount(); account.deactivateGracePeriod(); Conversation conv = message.getConversation(); @@ -615,7 +615,7 @@ public class XmppConnectionService extends Service { } } - conv.getMessages().add(message); + conv.add(message); if (saveInDb) { if (message.getEncryption() == Message.ENCRYPTION_NONE || saveEncryptedMessages()) { @@ -881,7 +881,7 @@ public class XmppConnectionService extends Service { for (Message message : messages) { message.setConversation(conversation); } - conversation.getMessages().addAll(0, messages); + conversation.addAll(0, messages); return messages.size(); } -- cgit v1.2.3 From 8263e073362aed2ebfda910df8ddad1e84302db1 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 19 Oct 2014 23:42:53 +0200 Subject: mtm support for image downloader --- .../siacs/conversations/entities/Downloadable.java | 1 + .../siacs/conversations/http/HttpConnection.java | 62 +++++++++++++++++----- .../ui/adapter/ConversationAdapter.java | 2 + .../conversations/ui/adapter/MessageAdapter.java | 7 ++- 4 files changed, 57 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Downloadable.java b/src/eu/siacs/conversations/entities/Downloadable.java index 36584ab0..70516b20 100644 --- a/src/eu/siacs/conversations/entities/Downloadable.java +++ b/src/eu/siacs/conversations/entities/Downloadable.java @@ -11,6 +11,7 @@ public interface Downloadable { public static final int STATUS_OFFER = 0x203; public static final int STATUS_DOWNLOADING = 0x204; public static final int STATUS_DELETED = 0x205; + public static final int STATUS_OFFER_CHECK_FILESIZE = 0x206; public boolean start(); diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 0254dc2f..3eb8bb84 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -6,15 +6,18 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.X509TrustManager; import android.content.Intent; import android.graphics.BitmapFactory; import android.net.Uri; -import android.util.Log; -import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; @@ -39,8 +42,12 @@ public class HttpConnection implements Downloadable { @Override public boolean start() { if (mXmppConnectionService.hasInternetConnection()) { - changeStatus(STATUS_DOWNLOADING); - new Thread(new FileDownloader()).start(); + if (this.mStatus == STATUS_OFFER_CHECK_FILESIZE) { + checkFileSize(true); + } else { + changeStatus(STATUS_DOWNLOADING); + new Thread(new FileDownloader()).start(); + } return true; } else { return false; @@ -52,18 +59,18 @@ public class HttpConnection implements Downloadable { this.message.setDownloadable(this); try { mUrl = new URL(message.getBody()); - this.file = mXmppConnectionService.getFileBackend() - .getFile(message, false); + this.file = mXmppConnectionService.getFileBackend().getFile( + message, false); this.mAutostart = true; - checkFileSize(); + checkFileSize(false); } catch (MalformedURLException e) { this.cancel(); } } - private void checkFileSize() { + private void checkFileSize(boolean interactive) { changeStatus(STATUS_CHECKING); - new Thread(new FileSizeChecker()).start(); + new Thread(new FileSizeChecker(interactive)).start(); } public void cancel() { @@ -84,33 +91,62 @@ public class HttpConnection implements Downloadable { this.mStatus = status; mXmppConnectionService.updateConversationUi(); } + + private void setupTrustManager(HttpsURLConnection connection, boolean interactive) { + X509TrustManager trustManager; + if (interactive) { + trustManager = mXmppConnectionService.getMemorizingTrustManager(); + } else { + trustManager = mXmppConnectionService.getMemorizingTrustManager().getNonInteractive(); + } + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null,new X509TrustManager[] { trustManager },mXmppConnectionService.getRNG()); + connection.setSSLSocketFactory(sc.getSocketFactory()); + } catch (KeyManagementException e) { + return; + } catch (NoSuchAlgorithmException e) { + return; + } + } private class FileSizeChecker implements Runnable { + + private boolean interactive = false; + + public FileSizeChecker(boolean interactive) { + this.interactive = interactive; + } @Override public void run() { long size; try { size = retrieveFileSize(); + } catch (SSLHandshakeException e) { + changeStatus(STATUS_OFFER_CHECK_FILESIZE); + return; } catch (IOException e) { cancel(); return; } file.setExpectedSize(size); - if (size <= mHttpConnectionManager.getAutoAcceptFileSize() && mAutostart) { + if (size <= mHttpConnectionManager.getAutoAcceptFileSize() + && mAutostart) { start(); } else { changeStatus(STATUS_OFFER); } } - private long retrieveFileSize() throws IOException { + private long retrieveFileSize() throws IOException, SSLHandshakeException { HttpURLConnection connection = (HttpURLConnection) mUrl .openConnection(); connection.setRequestMethod("HEAD"); if (connection instanceof HttpsURLConnection) { - + setupTrustManager((HttpsURLConnection) connection, interactive); } + connection.connect(); String contentLength = connection.getHeaderField("Content-Length"); if (contentLength == null) { throw new IOException(); @@ -141,7 +177,7 @@ public class HttpConnection implements Downloadable { HttpURLConnection connection = (HttpURLConnection) mUrl .openConnection(); if (connection instanceof HttpsURLConnection) { - + setupTrustManager((HttpsURLConnection) connection, true); } BufferedInputStream is = new BufferedInputStream( connection.getInputStream()); diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index bd37f7fc..20c7bee2 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -92,6 +92,8 @@ public class ConversationAdapter extends ArrayAdapter { mLastMessage.setText(R.string.receiving_image); } else if (d.getStatus() == Downloadable.STATUS_OFFER) { mLastMessage.setText(R.string.image_offered_for_download); + } else if (d.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) { + mLastMessage.setText(R.string.image_offered_for_download); } else if (d.getStatus() == Downloadable.STATUS_DELETED) { mLastMessage.setText(R.string.image_file_deleted); } else { diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 6b2a0094..db783b7f 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -264,10 +264,11 @@ public class MessageAdapter extends ArrayAdapter { } private void displayDownloadableMessage(ViewHolder viewHolder, - final Message message) { + final Message message, int resid) { viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); viewHolder.download_button.setVisibility(View.VISIBLE); + viewHolder.download_button.setText(resid); viewHolder.download_button.setOnClickListener(new OnClickListener() { @Override @@ -493,7 +494,9 @@ public class MessageAdapter extends ArrayAdapter { && d.getStatus() == Downloadable.STATUS_DELETED) { displayInfoMessage(viewHolder, R.string.image_file_deleted); } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER) { - displayDownloadableMessage(viewHolder, item); + displayDownloadableMessage(viewHolder, item,R.string.download_image); + } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) { + displayDownloadableMessage(viewHolder, item,R.string.check_image_filesize); } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED) || (item.getEncryption() == Message.ENCRYPTION_NONE) || (item.getEncryption() == Message.ENCRYPTION_OTR)) { -- cgit v1.2.3 From 0bb2c3c4d5b2a4b676610276fafd50ea55f43706 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 20 Oct 2014 17:01:37 +0200 Subject: keep reference to previous and next message in message --- .../siacs/conversations/entities/Conversation.java | 4 +-- src/eu/siacs/conversations/entities/Message.java | 36 ++++++++++++++++------ .../siacs/conversations/xmpp/XmppConnection.java | 1 - 3 files changed, 28 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index 600b9d38..e9500a0c 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -57,8 +57,8 @@ public class Conversation extends AbstractEntity { private String nextPresence; - private transient ArrayList messages = new ArrayList(); - private transient Account account = null; + protected ArrayList messages = new ArrayList(); + protected Account account = null; private transient SessionImpl otrSession; diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index a256d515..dab28539 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -62,6 +62,9 @@ public class Message extends AbstractEntity { protected Downloadable downloadable = null; public boolean markable = false; + private Message mNextMessage = null; + private Message mPreviousMessage = null; + private Message() { } @@ -293,21 +296,34 @@ public class Message extends AbstractEntity { } public Message next() { - int index = this.conversation.getMessages().indexOf(this); - if (index < 0 || index >= this.conversation.getMessages().size() - 1) { - return null; - } else { - return this.conversation.getMessages().get(index + 1); + if (this.mNextMessage == null) { + synchronized (this.conversation.messages) { + int index = this.conversation.messages.indexOf(this); + if (index < 0 + || index >= this.conversation.getMessages().size() - 1) { + this.mNextMessage = null; + } else { + this.mNextMessage = this.conversation.messages + .get(index + 1); + } + } } + return this.mNextMessage; } public Message prev() { - int index = this.conversation.getMessages().indexOf(this); - if (index <= 0 || index > this.conversation.getMessages().size()) { - return null; - } else { - return this.conversation.getMessages().get(index - 1); + if (this.mPreviousMessage == null) { + synchronized (this.conversation.messages) { + int index = this.conversation.messages.indexOf(this); + if (index <= 0 || index > this.conversation.messages.size()) { + this.mPreviousMessage = null; + } else { + this.mPreviousMessage = this.conversation.messages + .get(index - 1); + } + } } + return this.mPreviousMessage; } public boolean mergable(Message message) { diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 0252d80e..34ff70c9 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -40,7 +40,6 @@ import android.util.SparseArray; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.ui.StartConversationActivity; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.DNSHelper; import eu.siacs.conversations.utils.zlib.ZLibOutputStream; -- cgit v1.2.3 From 21961673cbcb3132d2405c3d276058b94cbdbbfc Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 20 Oct 2014 21:08:33 +0200 Subject: refactored avatar generation. first step --- src/eu/siacs/conversations/entities/Account.java | 22 +-- src/eu/siacs/conversations/entities/Bookmark.java | 18 +- src/eu/siacs/conversations/entities/Contact.java | 22 +-- .../siacs/conversations/entities/Conversation.java | 16 +- src/eu/siacs/conversations/entities/ListItem.java | 5 - .../siacs/conversations/entities/MucOptions.java | 17 +- src/eu/siacs/conversations/entities/Roster.java | 3 + .../siacs/conversations/http/HttpConnection.java | 16 +- .../conversations/persistance/DatabaseBackend.java | 7 +- .../conversations/persistance/FileBackend.java | 67 +++++-- .../conversations/services/AvatarService.java | 194 +++++++++++++++++++++ .../services/NotificationService.java | 6 +- .../services/XmppConnectionService.java | 45 +++-- .../ui/ConferenceDetailsActivity.java | 19 +- .../conversations/ui/ContactDetailsActivity.java | 15 +- .../ui/PublishProfilePictureActivity.java | 4 +- src/eu/siacs/conversations/ui/XmppActivity.java | 5 + .../conversations/ui/adapter/AccountAdapter.java | 3 +- .../ui/adapter/ConversationAdapter.java | 4 +- .../conversations/ui/adapter/ListItemAdapter.java | 11 +- .../conversations/ui/adapter/MessageAdapter.java | 22 ++- src/eu/siacs/conversations/utils/PhoneHelper.java | 8 +- src/eu/siacs/conversations/utils/UIHelper.java | 190 -------------------- .../siacs/conversations/xmpp/XmppConnection.java | 44 +++-- .../xmpp/jingle/JingleConnection.java | 10 +- 25 files changed, 405 insertions(+), 368 deletions(-) create mode 100644 src/eu/siacs/conversations/services/AvatarService.java (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java index ff509ba1..80a9d62f 100644 --- a/src/eu/siacs/conversations/entities/Account.java +++ b/src/eu/siacs/conversations/entities/Account.java @@ -14,14 +14,10 @@ import org.json.JSONObject; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrEngine; -import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.XmppConnection; import android.content.ContentValues; -import android.content.Context; import android.database.Cursor; -import android.graphics.Bitmap; import android.os.SystemClock; public class Account extends AbstractEntity { @@ -72,7 +68,7 @@ public class Account extends AbstractEntity { private long mEndGracePeriod = 0L; private String otrFingerprint; private Roster roster = null; - + private List bookmarks = new CopyOnWriteArrayList(); public List pendingConferenceJoins = new CopyOnWriteArrayList(); public List pendingConferenceLeaves = new CopyOnWriteArrayList(); @@ -345,20 +341,6 @@ public class Account extends AbstractEntity { return false; } - public Bitmap getImage(Context context, int size) { - if (this.avatar != null) { - Bitmap bm = FileBackend.getAvatar(this.avatar, size, context); - if (bm == null) { - return UIHelper.getContactPicture(getJid(), size, context, - false); - } else { - return bm; - } - } else { - return UIHelper.getContactPicture(getJid(), size, context, false); - } - } - public boolean setAvatar(String filename) { if (this.avatar != null && this.avatar.equals(filename)) { return false; @@ -401,7 +383,7 @@ public class Account extends AbstractEntity { return R.string.account_status_unknown; } } - + public void activateGracePeriod() { this.mEndGracePeriod = SystemClock.elapsedRealtime() + (Config.CARBON_GRACE_PERIOD * 1000); diff --git a/src/eu/siacs/conversations/entities/Bookmark.java b/src/eu/siacs/conversations/entities/Bookmark.java index 722fb6d9..dd9e805c 100644 --- a/src/eu/siacs/conversations/entities/Bookmark.java +++ b/src/eu/siacs/conversations/entities/Bookmark.java @@ -2,9 +2,6 @@ package eu.siacs.conversations.entities; import java.util.Locale; -import android.content.Context; -import android.graphics.Bitmap; -import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; public class Bookmark extends Element implements ListItem { @@ -120,21 +117,14 @@ public class Bookmark extends Element implements ListItem { return this.account; } - @Override - public Bitmap getImage(int dpSize, Context context) { - if (this.mJoinedConversation == null) { - return UIHelper.getContactPicture(getDisplayName(), dpSize, - context, false); - } else { - return UIHelper.getContactPicture(this.mJoinedConversation, dpSize, - context, false); - } - } - public void setConversation(Conversation conversation) { this.mJoinedConversation = conversation; } + public Conversation getConversation() { + return this.mJoinedConversation; + } + public String getName() { return this.getAttribute("name"); } diff --git a/src/eu/siacs/conversations/entities/Contact.java b/src/eu/siacs/conversations/entities/Contact.java index 40eee73d..60c31a42 100644 --- a/src/eu/siacs/conversations/entities/Contact.java +++ b/src/eu/siacs/conversations/entities/Contact.java @@ -8,13 +8,9 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import eu.siacs.conversations.persistance.FileBackend; -import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; import android.content.ContentValues; -import android.content.Context; import android.database.Cursor; -import android.graphics.Bitmap; public class Contact implements ListItem { public static final String TABLENAME = "contacts"; @@ -330,20 +326,6 @@ public class Contact implements ListItem { } } - @Override - public Bitmap getImage(int size, Context context) { - if (this.avatar != null) { - Bitmap bm = FileBackend.getAvatar(avatar, size, context); - if (bm == null) { - return UIHelper.getContactPicture(this, size, context, false); - } else { - return bm; - } - } else { - return UIHelper.getContactPicture(this, size, context, false); - } - } - public boolean setAvatar(String filename) { if (this.avatar != null && this.avatar.equals(filename)) { return false; @@ -353,6 +335,10 @@ public class Contact implements ListItem { } } + public String getAvatar() { + return this.avatar; + } + public boolean deleteOtrFingerprint(String fingerprint) { boolean success = false; try { diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index e9500a0c..9d4c36db 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -8,7 +8,6 @@ import org.json.JSONException; import org.json.JSONObject; import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.utils.UIHelper; import net.java.otr4j.OtrException; import net.java.otr4j.crypto.OtrCryptoEngineImpl; @@ -17,9 +16,7 @@ import net.java.otr4j.session.SessionID; import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionStatus; import android.content.ContentValues; -import android.content.Context; import android.database.Cursor; -import android.graphics.Bitmap; import android.os.SystemClock; public class Conversation extends AbstractEntity { @@ -329,9 +326,8 @@ public class Conversation extends AbstractEntity { public synchronized MucOptions getMucOptions() { if (this.mucOptions == null) { - this.mucOptions = new MucOptions(this.getAccount()); + this.mucOptions = new MucOptions(this); } - this.mucOptions.setConversation(this); return this.mucOptions; } @@ -428,14 +424,6 @@ public class Conversation extends AbstractEntity { return this.bookmark; } - public Bitmap getImage(Context context, int size) { - if (mode == MODE_SINGLE) { - return getContact().getImage(size, context); - } else { - return UIHelper.getContactPicture(this, size, context, false); - } - } - public boolean hasDuplicateMessage(Message message) { for (int i = this.getMessages().size() - 1; i >= 0; --i) { if (this.messages.get(i).equals(message)) { @@ -496,7 +484,7 @@ public class Conversation extends AbstractEntity { } } } - + public void add(Message message) { message.setConversation(this); synchronized (this.messages) { diff --git a/src/eu/siacs/conversations/entities/ListItem.java b/src/eu/siacs/conversations/entities/ListItem.java index 19089b28..a1872d2f 100644 --- a/src/eu/siacs/conversations/entities/ListItem.java +++ b/src/eu/siacs/conversations/entities/ListItem.java @@ -1,12 +1,7 @@ package eu.siacs.conversations.entities; -import android.content.Context; -import android.graphics.Bitmap; - public interface ListItem extends Comparable { public String getDisplayName(); public String getJid(); - - public Bitmap getImage(int dpSize, Context context); } diff --git a/src/eu/siacs/conversations/entities/MucOptions.java b/src/eu/siacs/conversations/entities/MucOptions.java index 12ea4e93..d7407cd5 100644 --- a/src/eu/siacs/conversations/entities/MucOptions.java +++ b/src/eu/siacs/conversations/entities/MucOptions.java @@ -102,6 +102,10 @@ public class MucOptions { public long getPgpKeyId() { return this.pgpKeyId; } + + public Contact getContact() { + return account.getRoster().getContactFromRoster(getJid()); + } } private Account account; @@ -116,8 +120,9 @@ public class MucOptions { private String joinnick; private String password = null; - public MucOptions(Account account) { - this.account = account; + public MucOptions(Conversation conversation) { + this.account = conversation.getAccount(); + this.conversation = conversation; } public void deleteUser(String name) { @@ -253,10 +258,6 @@ public class MucOptions { this.joinnick = nick; } - public void setConversation(Conversation conversation) { - this.conversation = conversation; - } - public boolean online() { return this.isOnline; } @@ -361,4 +362,8 @@ public class MucOptions { conversation .setAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD, password); } + + public Conversation getConversation() { + return this.conversation; + } } \ No newline at end of file diff --git a/src/eu/siacs/conversations/entities/Roster.java b/src/eu/siacs/conversations/entities/Roster.java index ef47c577..3267b15a 100644 --- a/src/eu/siacs/conversations/entities/Roster.java +++ b/src/eu/siacs/conversations/entities/Roster.java @@ -15,6 +15,9 @@ public class Roster { } public Contact getContactFromRoster(String jid) { + if (jid == null) { + return null; + } String cleanJid = jid.split("/", 2)[0]; Contact contact = contacts.get(cleanJid); if (contact != null && contact.showInRoster()) { diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 3eb8bb84..cbcdfb5c 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -91,17 +91,20 @@ public class HttpConnection implements Downloadable { this.mStatus = status; mXmppConnectionService.updateConversationUi(); } - - private void setupTrustManager(HttpsURLConnection connection, boolean interactive) { + + private void setupTrustManager(HttpsURLConnection connection, + boolean interactive) { X509TrustManager trustManager; if (interactive) { trustManager = mXmppConnectionService.getMemorizingTrustManager(); } else { - trustManager = mXmppConnectionService.getMemorizingTrustManager().getNonInteractive(); + trustManager = mXmppConnectionService.getMemorizingTrustManager() + .getNonInteractive(); } try { SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null,new X509TrustManager[] { trustManager },mXmppConnectionService.getRNG()); + sc.init(null, new X509TrustManager[] { trustManager }, + mXmppConnectionService.getRNG()); connection.setSSLSocketFactory(sc.getSocketFactory()); } catch (KeyManagementException e) { return; @@ -111,7 +114,7 @@ public class HttpConnection implements Downloadable { } private class FileSizeChecker implements Runnable { - + private boolean interactive = false; public FileSizeChecker(boolean interactive) { @@ -139,7 +142,8 @@ public class HttpConnection implements Downloadable { } } - private long retrieveFileSize() throws IOException, SSLHandshakeException { + private long retrieveFileSize() throws IOException, + SSLHandshakeException { HttpURLConnection connection = (HttpURLConnection) mUrl .openConnection(); connection.setRequestMethod("HEAD"); diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java index d3d6ccf2..b49cf4e6 100644 --- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -152,13 +152,12 @@ public class DatabaseBackend extends SQLiteOpenHelper { return list; } - public ArrayList getMessages( - Conversation conversations, int limit) { + public ArrayList getMessages(Conversation conversations, int limit) { return getMessages(conversations, limit, -1); } - public ArrayList getMessages(Conversation conversation, - int limit, long timestamp) { + public ArrayList getMessages(Conversation conversation, int limit, + long timestamp) { ArrayList list = new ArrayList(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 74918670..0a417b5c 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -35,7 +35,6 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.utils.CryptoHelper; -import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.pep.Avatar; public class FileBackend { @@ -69,8 +68,7 @@ public class FileBackend { return getFile(message, true); } - public DownloadableFile getFile(Message message, - boolean decrypted) { + public DownloadableFile getFile(Message message, boolean decrypted) { StringBuilder filename = new StringBuilder(); filename.append(getConversationsDirectory()); filename.append(message.getUuid()); @@ -85,10 +83,11 @@ public class FileBackend { } return new DownloadableFile(filename.toString()); } - + public static String getConversationsDirectory() { return Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES).getAbsolutePath()+"/Conversations/"; + Environment.DIRECTORY_PICTURES).getAbsolutePath() + + "/Conversations/"; } public Bitmap resize(Bitmap originalBitmap, int size) { @@ -219,8 +218,7 @@ public class FileBackend { } public Bitmap getImageFromMessage(Message message) { - return BitmapFactory.decodeFile(getFile(message) - .getAbsolutePath()); + return BitmapFactory.decodeFile(getFile(message).getAbsolutePath()); } public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) @@ -306,7 +304,7 @@ public class FileBackend { } public boolean isAvatarCached(Avatar avatar) { - File file = new File(getAvatarPath(context, avatar.getFilename())); + File file = new File(getAvatarPath(avatar.getFilename())); return file.exists(); } @@ -314,7 +312,7 @@ public class FileBackend { if (isAvatarCached(avatar)) { return true; } - String filename = getAvatarPath(context, avatar.getFilename()); + String filename = getAvatarPath(avatar.getFilename()); File file = new File(filename + ".tmp"); file.getParentFile().mkdirs(); try { @@ -346,10 +344,14 @@ public class FileBackend { } } - public static String getAvatarPath(Context context, String avatar) { + public String getAvatarPath(String avatar) { return context.getFilesDir().getAbsolutePath() + "/avatars/" + avatar; } + public Uri getAvatarUri(String avatar) { + return Uri.parse("file:" + getAvatarPath(avatar)); + } + public Bitmap cropCenterSquare(Uri image, int size) { try { BitmapFactory.Options options = new BitmapFactory.Options(); @@ -371,7 +373,40 @@ public class FileBackend { } } - public static Bitmap cropCenterSquare(Bitmap input, int size) { + public Bitmap cropCenter(Uri image, int newHeight, int newWidth) { + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = calcSampleSize(image, + Math.max(newHeight, newWidth)); + InputStream is = context.getContentResolver() + .openInputStream(image); + Bitmap source = BitmapFactory.decodeStream(is, null, options); + + int sourceWidth = source.getWidth(); + int sourceHeight = source.getHeight(); + float xScale = (float) newWidth / sourceWidth; + float yScale = (float) newHeight / sourceHeight; + float scale = Math.max(xScale, yScale); + float scaledWidth = scale * sourceWidth; + float scaledHeight = scale * sourceHeight; + float left = (newWidth - scaledWidth) / 2; + float top = (newHeight - scaledHeight) / 2; + + RectF targetRect = new RectF(left, top, left + scaledWidth, top + + scaledHeight); + Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, + source.getConfig()); + Canvas canvas = new Canvas(dest); + canvas.drawBitmap(source, null, targetRect, null); + + return dest; + } catch (FileNotFoundException e) { + return null; + } + + } + + public Bitmap cropCenterSquare(Bitmap input, int size) { int w = input.getWidth(); int h = input.getHeight(); @@ -440,13 +475,15 @@ public class FileBackend { } } - public static Bitmap getAvatar(String avatar, int size, Context context) { - Bitmap bm = BitmapFactory.decodeFile(FileBackend.getAvatarPath(context, - avatar)); + public Bitmap getAvatar(String avatar, int size) { + if (avatar == null) { + return null; + } + Bitmap bm = cropCenter(getAvatarUri(avatar), size, size); if (bm == null) { return null; } - return cropCenterSquare(bm, UIHelper.getRealPx(size, context)); + return bm; } public boolean isFileAvailable(Message message) { diff --git a/src/eu/siacs/conversations/services/AvatarService.java b/src/eu/siacs/conversations/services/AvatarService.java new file mode 100644 index 00000000..def3bfd8 --- /dev/null +++ b/src/eu/siacs/conversations/services/AvatarService.java @@ -0,0 +1,194 @@ +package eu.siacs.conversations.services; + +import java.util.List; +import java.util.Locale; + +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Bookmark; +import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.entities.MucOptions; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.net.Uri; + +public class AvatarService { + + private static final int FG_COLOR = 0xFFFAFAFA; + private static final int TRANSPARENT = 0x00000000; + + protected XmppConnectionService mXmppConnectionService = null; + + public AvatarService(XmppConnectionService service) { + this.mXmppConnectionService = service; + } + + public Bitmap getAvatar(Contact contact, int size) { + Bitmap avatar = mXmppConnectionService.getFileBackend().getAvatar( + contact.getAvatar(), size); + if (avatar == null) { + if (contact.getProfilePhoto() != null) { + avatar = mXmppConnectionService.getFileBackend() + .cropCenterSquare(Uri.parse(contact.getProfilePhoto()), + size); + if (avatar == null) { + avatar = getAvatar(contact.getDisplayName(), size); + } + } else { + avatar = getAvatar(contact.getDisplayName(), size); + } + } + return avatar; + } + + public Bitmap getAvatar(ListItem item, int size) { + if (item instanceof Contact) { + return getAvatar((Contact) item, size); + } else if (item instanceof Bookmark) { + Bookmark bookmark = (Bookmark) item; + if (bookmark.getConversation() != null) { + return getAvatar(bookmark.getConversation(), size); + } else { + return getAvatar(bookmark.getDisplayName(), size); + } + } else { + return getAvatar(item.getDisplayName(), size); + } + } + + public Bitmap getAvatar(Conversation conversation, int size) { + if (conversation.getMode() == Conversation.MODE_SINGLE) { + return getAvatar(conversation.getContact(), size); + } else { + return getAvatar(conversation.getMucOptions(), size); + } + } + + public Bitmap getAvatar(MucOptions mucOptions, int size) { + List users = mucOptions.getUsers(); + int count = users.size(); + Bitmap bitmap = Bitmap + .createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + bitmap.eraseColor(TRANSPARENT); + + if (count == 0) { + String name = mucOptions.getConversation().getName(); + String letter = name.substring(0, 1); + int color = this.getColorForName(name); + drawTile(canvas, letter, color, 0, 0, size, size); + } else if (count == 1) { + drawTile(canvas, users.get(0), 0, 0, size, size); + } else if (count == 2) { + drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size); + drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size); + } else if (count == 3) { + drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size); + drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size / 2 - 1); + drawTile(canvas, users.get(2), size / 2 + 1, size / 2 + 1, size, + size); + } else if (count == 4) { + drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1); + drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size); + drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1); + drawTile(canvas, users.get(3), size / 2 + 1, size / 2 + 1, size, + size); + } else { + drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1); + drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size); + drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1); + drawTile(canvas, "\u2026", 0xFF202020, size / 2 + 1, size / 2 + 1, + size, size); + } + return bitmap; + } + + public Bitmap getAvatar(Account account, int size) { + Bitmap avatar = mXmppConnectionService.getFileBackend().getAvatar( + account.getAvatar(), size); + if (avatar == null) { + avatar = getAvatar(account.getJid(), size); + } + return avatar; + } + + public Bitmap getAvatar(String name, int size) { + Bitmap bitmap = Bitmap + .createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + String letter = name.substring(0, 1); + int color = this.getColorForName(name); + drawTile(canvas, letter, color, 0, 0, size, size); + return bitmap; + } + + private void drawTile(Canvas canvas, String letter, int tileColor, + int left, int top, int right, int bottom) { + letter = letter.toUpperCase(Locale.getDefault()); + Paint tilePaint = new Paint(), textPaint = new Paint(); + tilePaint.setColor(tileColor); + textPaint.setFlags(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(FG_COLOR); + textPaint.setTypeface(Typeface.create("sans-serif-light", + Typeface.NORMAL)); + textPaint.setTextSize((float) ((right - left) * 0.8)); + Rect rect = new Rect(); + + canvas.drawRect(new Rect(left, top, right, bottom), tilePaint); + textPaint.getTextBounds(letter, 0, 1, rect); + float width = textPaint.measureText(letter); + canvas.drawText(letter, (right + left) / 2 - width / 2, (top + bottom) + / 2 + rect.height() / 2, textPaint); + } + + private void drawTile(Canvas canvas, MucOptions.User user, int left, + int top, int right, int bottom) { + Contact contact = user.getContact(); + if (contact != null) { + Uri uri = null; + if (contact.getAvatar() != null) { + uri = mXmppConnectionService.getFileBackend().getAvatarUri( + contact.getAvatar()); + } else if (contact.getProfilePhoto() != null) { + uri = Uri.parse(contact.getProfilePhoto()); + } + if (uri != null) { + Bitmap bitmap = mXmppConnectionService.getFileBackend() + .cropCenter(uri, bottom - top, right - left); + if (bitmap != null) { + drawTile(canvas, bitmap, left, top, right, bottom); + } else { + String letter = user.getName().substring(0, 1); + int color = this.getColorForName(user.getName()); + drawTile(canvas, letter, color, left, top, right, bottom); + } + } else { + String letter = user.getName().substring(0, 1); + int color = this.getColorForName(user.getName()); + drawTile(canvas, letter, color, left, top, right, bottom); + } + } else { + String letter = user.getName().substring(0, 1); + int color = this.getColorForName(user.getName()); + drawTile(canvas, letter, color, left, top, right, bottom); + } + } + + private void drawTile(Canvas canvas, Bitmap bm, int dstleft, int dsttop, + int dstright, int dstbottom) { + Rect dst = new Rect(dstleft, dsttop, dstright, dstbottom); + canvas.drawBitmap(bm, null, dst, null); + } + + private int getColorForName(String name) { + int holoColors[] = { 0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, + 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, + 0xFF795548, 0xFF607d8b }; + return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)]; + } + +} diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 0b30e58e..a1336123 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -33,7 +33,7 @@ public class NotificationService { public int NOTIFICATION_ID = 0x2342; private Conversation mOpenConversation; private boolean mIsInForeground; - + public NotificationService(XmppConnectionService service) { this.mXmppConnectionService = service; this.mNotificationManager = (NotificationManager) service @@ -97,8 +97,8 @@ public class NotificationService { if (messages.size() >= 1) { Conversation conversation = messages.get(0) .getConversation(); - mBuilder.setLargeIcon(conversation.getImage( - mXmppConnectionService, 64)); + // mBuilder.setLargeIcon(conversation.getImage(mXmppConnectionService, + // 64)); mBuilder.setContentTitle(conversation.getName()); StringBuilder text = new StringBuilder(); for (int i = 0; i < messages.size(); ++i) { diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index f557c3e1..6c8dc17a 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -111,6 +111,7 @@ public class XmppConnectionService extends Service { this); private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager( this); + private AvatarService mAvatarService = new AvatarService(this); private OnConversationUpdate mOnConversationUpdate = null; private Integer convChangedListenerCount = 0; @@ -144,9 +145,10 @@ public class XmppConnectionService extends Service { startService(intent); } }; - - private FileObserver fileObserver = new FileObserver(FileBackend.getConversationsDirectory()) { - + + private FileObserver fileObserver = new FileObserver( + FileBackend.getConversationsDirectory()) { + @Override public void onEvent(int event, String path) { if (event == FileObserver.DELETE) { @@ -286,6 +288,10 @@ public class XmppConnectionService extends Service { return this.fileBackend; } + public AvatarService getAvatarService() { + return this.mAvatarService; + } + public Message attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback callback) { final Message message; @@ -346,7 +352,7 @@ public class XmppConnectionService extends Service { } } this.wakeLock.acquire(); - + for (Account account : accounts) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!hasInternetConnection()) { @@ -407,7 +413,7 @@ public class XmppConnectionService extends Service { } return START_STICKY; } - + public boolean hasInternetConnection() { ConnectivityManager cm = (ConnectivityManager) getApplicationContext() .getSystemService(Context.CONNECTIVITY_SERVICE); @@ -818,21 +824,24 @@ public class XmppConnectionService extends Service { } return this.conversations; } - + private void checkDeletedFiles(Conversation conversation) { - for(Message message : conversation.getMessages()) { - if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP) { + for (Message message : conversation.getMessages()) { + if (message.getType() == Message.TYPE_IMAGE + && message.getEncryption() != Message.ENCRYPTION_PGP) { if (!getFileBackend().isFileAvailable(message)) { message.setDownloadable(new DeletedDownloadable()); } } } } - + private void markFileDeleted(String uuid) { - for(Conversation conversation : getConversations()) { - for(Message message : conversation.getMessages()) { - if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getUuid().equals(uuid)) { + for (Conversation conversation : getConversations()) { + for (Message message : conversation.getMessages()) { + if (message.getType() == Message.TYPE_IMAGE + && message.getEncryption() != Message.ENCRYPTION_PGP + && message.getUuid().equals(uuid)) { if (!getFileBackend().isFileAvailable(message)) { message.setDownloadable(new DeletedDownloadable()); updateConversationUi(); @@ -1113,7 +1122,7 @@ public class XmppConnectionService extends Service { } } } - Log.d(Config.LOGTAG,"app switched into foreground"); + Log.d(Config.LOGTAG, "app switched into foreground"); } private void switchToBackground() { @@ -1126,7 +1135,7 @@ public class XmppConnectionService extends Service { } } this.mNotificationService.setIsInForeground(false); - Log.d(Config.LOGTAG,"app switched into background"); + Log.d(Config.LOGTAG, "app switched into background"); } private boolean isScreenOn() { @@ -1288,7 +1297,9 @@ public class XmppConnectionService extends Service { leaveMuc(conversation); } else { if (conversation.endOtrIfNeeded()) { - Log.d(Config.LOGTAG,account.getJid()+": ended otr session with "+conversation.getContactJid()); + Log.d(Config.LOGTAG, account.getJid() + + ": ended otr session with " + + conversation.getContactJid()); } } } @@ -1871,7 +1882,7 @@ public class XmppConnectionService extends Service { public HttpConnectionManager getHttpConnectionManager() { return this.mHttpConnectionManager; } - + private class DeletedDownloadable implements Downloadable { @Override @@ -1888,6 +1899,6 @@ public class XmppConnectionService extends Service { public long getFileSize() { return 0; } - + } } diff --git a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index ca3bb4a2..98bf70ed 100644 --- a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -201,7 +201,8 @@ public class ConferenceDetailsActivity extends XmppActivity { private void populateView() { mAccountJid.setText(getString(R.string.using_account, conversation .getAccount().getJid())); - mYourPhoto.setImageBitmap(conversation.getAccount().getImage(this, 48)); + mYourPhoto.setImageBitmap(xmppConnectionService.getAvatarService() + .getAvatar(conversation.getAccount(), getPixel(48))); setTitle(conversation.getName()); mFullJid.setText(conversation.getContactJid().split("/", 2)[0]); mYourNick.setText(conversation.getMucOptions().getActualNick()); @@ -248,21 +249,23 @@ public class ConferenceDetailsActivity extends XmppActivity { } Bitmap bm; if (user.getJid() != null) { - Contact contact = account.getRoster().getContact(user.getJid()); - if (contact.showInRoster()) { - bm = contact.getImage(48, this); + Contact contact = account.getRoster().getContactFromRoster( + user.getJid()); + if (contact != null) { + bm = xmppConnectionService.getAvatarService().getAvatar( + contact, getPixel(48)); name.setText(contact.getDisplayName()); role.setText(user.getName() + " \u2022 " + getReadableRole(user.getRole())); } else { - bm = UIHelper.getContactPicture(user.getName(), 48, this, - false); + bm = xmppConnectionService.getAvatarService().getAvatar( + user.getName(), getPixel(48)); name.setText(user.getName()); role.setText(getReadableRole(user.getRole())); } } else { - bm = UIHelper - .getContactPicture(user.getName(), 48, this, false); + bm = xmppConnectionService.getAvatarService().getAvatar( + user.getName(), getPixel(48)); name.setText(user.getName()); role.setText(getReadableRole(user.getRole())); } diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java index 65bd5cbf..d43eee59 100644 --- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -313,10 +313,7 @@ public class ContactDetailsActivity extends XmppActivity { } accountJidTv.setText(getString(R.string.using_account, contact .getAccount().getJid())); - - UIHelper.prepareContactBadge(this, badge, contact, - getApplicationContext()); - + prepareContactBadge(badge, contact); if (contact.getSystemAccount() == null) { badge.setOnClickListener(onBadgeClick); } @@ -383,6 +380,16 @@ public class ContactDetailsActivity extends XmppActivity { } } + private void prepareContactBadge(QuickContactBadge badge, Contact contact) { + if (contact.getSystemAccount() != null) { + String[] systemAccount = contact.getSystemAccount().split("#"); + long id = Long.parseLong(systemAccount[0]); + badge.assignContactUri(Contacts.getLookupUri(id, systemAccount[1])); + } + badge.setImageBitmap(xmppConnectionService.getAvatarService() + .getAvatar(contact, getPixel(72))); + } + protected void confirmToDeleteFingerprint(final String fingerprint) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.delete_fingerprint); diff --git a/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index f46d92f9..24330361 100644 --- a/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -158,8 +158,8 @@ public class PublishProfilePictureActivity extends XmppActivity { if (this.avatarUri == null) { if (this.account.getAvatar() != null || this.defaultUri == null) { - this.avatar.setImageBitmap(this.account.getImage( - getApplicationContext(), 384)); + // this.avatar.setImageBitmap(this.account.getImage(getApplicationContext(), + // 384)); if (this.defaultUri != null) { this.avatar .setOnLongClickListener(this.backToDefaultListener); diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index cd77557c..ca1bf465 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -526,6 +526,11 @@ public abstract class XmppActivity extends Activity { return this.mSecondaryBackgroundColor; } + public int getPixel(int dp) { + DisplayMetrics metrics = getResources().getDisplayMetrics(); + return ((int) (dp * metrics.density)); + } + class BitmapWorkerTask extends AsyncTask { private final WeakReference imageViewReference; private Message message = null; diff --git a/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java index 5c25bf34..40229953 100644 --- a/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -34,7 +34,8 @@ public class AccountAdapter extends ArrayAdapter { jid.setText(account.getJid()); TextView statusView = (TextView) view.findViewById(R.id.account_status); ImageView imageView = (ImageView) view.findViewById(R.id.account_image); - imageView.setImageBitmap(account.getImage(activity, 48)); + imageView.setImageBitmap(activity.xmppConnectionService + .getAvatarService().getAvatar(account, activity.getPixel(48))); switch (account.getStatus()) { case Account.STATUS_DISABLED: statusView.setText(getContext().getString( diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 20c7bee2..1fea8dcf 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -127,7 +127,9 @@ public class ConversationAdapter extends ArrayAdapter { ImageView profilePicture = (ImageView) view .findViewById(R.id.conversation_image); - profilePicture.setImageBitmap(conversation.getImage(activity, 56)); + profilePicture.setImageBitmap(activity.xmppConnectionService + .getAvatarService().getAvatar(conversation, + activity.getPixel(56))); return view; } diff --git a/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index df67e566..64e077a3 100644 --- a/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -4,6 +4,7 @@ import java.util.List; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.ui.XmppActivity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; @@ -14,8 +15,11 @@ import android.widget.TextView; public class ListItemAdapter extends ArrayAdapter { - public ListItemAdapter(Context context, List objects) { - super(context, 0, objects); + protected XmppActivity activity; + + public ListItemAdapter(XmppActivity activity, List objects) { + super(activity, 0, objects); + this.activity = activity; } @Override @@ -32,7 +36,8 @@ public class ListItemAdapter extends ArrayAdapter { jid.setText(item.getJid()); name.setText(item.getDisplayName()); - picture.setImageBitmap(item.getImage(48, getContext())); + picture.setImageBitmap(activity.xmppConnectionService + .getAvatarService().getAvatar(item, activity.getPixel(48))); return view; } diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index db783b7f..bc5b3387 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -59,8 +59,10 @@ public class MessageAdapter extends ArrayAdapter { if (this.accountBitmap == null) { if (getCount() > 0) { - this.accountBitmap = getItem(0).getConversation().getAccount() - .getImage(getContext(), 48); + this.accountBitmap = activity.xmppConnectionService + .getAvatarService().getAvatar( + getItem(0).getConversation().getAccount(), + activity.getPixel(48)); } } return this.accountBitmap; @@ -494,9 +496,12 @@ public class MessageAdapter extends ArrayAdapter { && d.getStatus() == Downloadable.STATUS_DELETED) { displayInfoMessage(viewHolder, R.string.image_file_deleted); } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER) { - displayDownloadableMessage(viewHolder, item,R.string.download_image); - } else if (d != null && d.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) { - displayDownloadableMessage(viewHolder, item,R.string.check_image_filesize); + displayDownloadableMessage(viewHolder, item, + R.string.download_image); + } else if (d != null + && d.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) { + displayDownloadableMessage(viewHolder, item, + R.string.check_image_filesize); } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED) || (item.getEncryption() == Message.ENCRYPTION_NONE) || (item.getEncryption() == Message.ENCRYPTION_OTR)) { @@ -564,7 +569,8 @@ public class MessageAdapter extends ArrayAdapter { public Bitmap get(Contact contact, Context context) { if (!contactBitmaps.containsKey(contact.getJid())) { contactBitmaps.put(contact.getJid(), - contact.getImage(48, context)); + activity.xmppConnectionService.getAvatarService() + .getAvatar(contact, activity.getPixel(48))); } return contactBitmaps.get(contact.getJid()); } @@ -573,8 +579,8 @@ public class MessageAdapter extends ArrayAdapter { if (unknownBitmaps.containsKey(name)) { return unknownBitmaps.get(name); } else { - Bitmap bm = UIHelper - .getContactPicture(name, 48, context, false); + Bitmap bm = activity.xmppConnectionService.getAvatarService() + .getAvatar(name, activity.getPixel(48)); unknownBitmaps.put(name, bm); return bm; } diff --git a/src/eu/siacs/conversations/utils/PhoneHelper.java b/src/eu/siacs/conversations/utils/PhoneHelper.java index 25cff099..5becc7e7 100644 --- a/src/eu/siacs/conversations/utils/PhoneHelper.java +++ b/src/eu/siacs/conversations/utils/PhoneHelper.java @@ -22,7 +22,7 @@ public class PhoneHelper { final String[] PROJECTION = new String[] { ContactsContract.Data._ID, ContactsContract.Data.DISPLAY_NAME, - ContactsContract.Data.PHOTO_THUMBNAIL_URI, + ContactsContract.Data.PHOTO_URI, ContactsContract.Data.LOOKUP_KEY, ContactsContract.CommonDataKinds.Im.DATA }; @@ -50,10 +50,8 @@ public class PhoneHelper { "displayname", cursor.getString(cursor .getColumnIndex(ContactsContract.Data.DISPLAY_NAME))); - contact.putString( - "photouri", - cursor.getString(cursor - .getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI))); + contact.putString("photouri", cursor.getString(cursor + .getColumnIndex(ContactsContract.Data.PHOTO_URI))); contact.putString("lookup", cursor.getString(cursor .getColumnIndex(ContactsContract.Data.LOOKUP_KEY))); diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java index 671e66d5..57e9153d 100644 --- a/src/eu/siacs/conversations/utils/UIHelper.java +++ b/src/eu/siacs/conversations/utils/UIHelper.java @@ -123,167 +123,6 @@ public class UIHelper { } } - public static int getRealPx(int dp, Context context) { - final DisplayMetrics metrics = context.getResources() - .getDisplayMetrics(); - return ((int) (dp * metrics.density)); - } - - private static int getNameColor(String name) { - /* - * int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713, - * 0xFFe92727 }; - */ - int holoColors[] = { 0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, - 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, - 0xFF795548, 0xFF607d8b }; - return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)]; - } - - private static void drawTile(Canvas canvas, String letter, int tileColor, - int textColor, int left, int top, int right, int bottom) { - Paint tilePaint = new Paint(), textPaint = new Paint(); - tilePaint.setColor(tileColor); - textPaint.setFlags(Paint.ANTI_ALIAS_FLAG); - textPaint.setColor(textColor); - textPaint.setTypeface(Typeface.create("sans-serif-light", - Typeface.NORMAL)); - textPaint.setTextSize((float) ((right - left) * 0.8)); - Rect rect = new Rect(); - - canvas.drawRect(new Rect(left, top, right, bottom), tilePaint); - textPaint.getTextBounds(letter, 0, 1, rect); - float width = textPaint.measureText(letter); - canvas.drawText(letter, (right + left) / 2 - width / 2, (top + bottom) - / 2 + rect.height() / 2, textPaint); - } - - private static Bitmap getUnknownContactPicture(String[] names, int size, - int bgColor, int fgColor) { - int tiles = (names.length > 4) ? 4 : (names.length < 1) ? 1 - : names.length; - Bitmap bitmap = Bitmap - .createBitmap(size, size, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - - String[] letters = new String[tiles]; - int[] colors = new int[tiles]; - if (names.length < 1) { - letters[0] = "?"; - colors[0] = 0xFFe92727; - } else { - for (int i = 0; i < tiles; ++i) { - letters[i] = (names[i].length() > 0) ? names[i].substring(0, 1) - .toUpperCase(Locale.US) : " "; - colors[i] = getNameColor(names[i]); - } - - if (names.length > 4) { - letters[3] = "\u2026"; // Unicode ellipsis - colors[3] = 0xFF202020; - } - } - - bitmap.eraseColor(bgColor); - - switch (tiles) { - case 1: - drawTile(canvas, letters[0], colors[0], fgColor, 0, 0, size, size); - break; - - case 2: - drawTile(canvas, letters[0], colors[0], fgColor, 0, 0, - size / 2 - 1, size); - drawTile(canvas, letters[1], colors[1], fgColor, size / 2 + 1, 0, - size, size); - break; - - case 3: - drawTile(canvas, letters[0], colors[0], fgColor, 0, 0, - size / 2 - 1, size); - drawTile(canvas, letters[1], colors[1], fgColor, size / 2 + 1, 0, - size, size / 2 - 1); - drawTile(canvas, letters[2], colors[2], fgColor, size / 2 + 1, - size / 2 + 1, size, size); - break; - - case 4: - drawTile(canvas, letters[0], colors[0], fgColor, 0, 0, - size / 2 - 1, size / 2 - 1); - drawTile(canvas, letters[1], colors[1], fgColor, 0, size / 2 + 1, - size / 2 - 1, size); - drawTile(canvas, letters[2], colors[2], fgColor, size / 2 + 1, 0, - size, size / 2 - 1); - drawTile(canvas, letters[3], colors[3], fgColor, size / 2 + 1, - size / 2 + 1, size, size); - break; - } - - return bitmap; - } - - private static Bitmap getMucContactPicture(Conversation conversation, - int size, int bgColor, int fgColor) { - List members = conversation.getMucOptions().getUsers(); - if (members.size() == 0) { - return getUnknownContactPicture( - new String[] { conversation.getName() }, size, bgColor, - fgColor); - } - ArrayList names = new ArrayList(); - names.add(conversation.getMucOptions().getActualNick()); - for (User user : members) { - names.add(user.getName()); - if (names.size() > 4) { - break; - } - } - String[] mArrayNames = new String[names.size()]; - names.toArray(mArrayNames); - return getUnknownContactPicture(mArrayNames, size, bgColor, fgColor); - } - - public static Bitmap getContactPicture(Conversation conversation, - int dpSize, Context context, boolean notification) { - if (conversation.getMode() == Conversation.MODE_SINGLE) { - return getContactPicture(conversation.getContact(), dpSize, - context, notification); - } else { - int fgColor = UIHelper.FG_COLOR, bgColor = (notification) ? UIHelper.BG_COLOR - : UIHelper.TRANSPARENT; - - return getMucContactPicture(conversation, - getRealPx(dpSize, context), bgColor, fgColor); - } - } - - public static Bitmap getContactPicture(Contact contact, int dpSize, - Context context, boolean notification) { - String uri = contact.getProfilePhoto(); - if (uri == null) { - return getContactPicture(contact.getDisplayName(), dpSize, context, - notification); - } - try { - Bitmap bm = BitmapFactory.decodeStream(context.getContentResolver() - .openInputStream(Uri.parse(uri))); - return Bitmap.createScaledBitmap(bm, getRealPx(dpSize, context), - getRealPx(dpSize, context), false); - } catch (FileNotFoundException e) { - return getContactPicture(contact.getDisplayName(), dpSize, context, - notification); - } - } - - public static Bitmap getContactPicture(String name, int dpSize, - Context context, boolean notification) { - int fgColor = UIHelper.FG_COLOR, bgColor = (notification) ? UIHelper.BG_COLOR - : UIHelper.TRANSPARENT; - - return getUnknownContactPicture(new String[] { name }, - getRealPx(dpSize, context), bgColor, fgColor); - } - public static void showErrorNotification(Context context, List accounts) { NotificationManager mNotificationManager = (NotificationManager) context @@ -326,16 +165,6 @@ public class UIHelper { mNotificationManager.notify(1111, notification); } - public static void prepareContactBadge(final Activity activity, - QuickContactBadge badge, final Contact contact, Context context) { - if (contact.getSystemAccount() != null) { - String[] systemAccount = contact.getSystemAccount().split("#"); - long id = Long.parseLong(systemAccount[0]); - badge.assignContactUri(Contacts.getLookupUri(id, systemAccount[1])); - } - badge.setImageBitmap(contact.getImage(72, context)); - } - @SuppressLint("InflateParams") public static AlertDialog getVerifyFingerprintDialog( final ConversationActivity activity, @@ -370,25 +199,6 @@ public class UIHelper { return builder.create(); } - public static Bitmap getSelfContactPicture(Account account, int size, - boolean showPhoneSelfContactPicture, Context context) { - if (showPhoneSelfContactPicture) { - Uri selfiUri = PhoneHelper.getSefliUri(context); - if (selfiUri != null) { - try { - return BitmapFactory.decodeStream(context - .getContentResolver().openInputStream(selfiUri)); - } catch (FileNotFoundException e) { - return getContactPicture(account.getJid(), size, context, - false); - } - } - return getContactPicture(account.getJid(), size, context, false); - } else { - return getContactPicture(account.getJid(), size, context, false); - } - } - private final static class EmoticonPattern { Pattern pattern; String replacement; diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 34ff70c9..ffa438bd 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -110,7 +110,7 @@ public class XmppConnection implements Runnable { private OnBindListener bindListener = null; private OnMessageAcknowledged acknowledgedListener = null; private MemorizingTrustManager mMemorizingTrustManager; - private final Context applicationContext; + private final Context applicationContext; public XmppConnection(Account account, XmppConnectionService service) { this.mRandom = service.getRNG(); @@ -119,7 +119,7 @@ public class XmppConnection implements Runnable { this.wakeLock = service.getPowerManager().newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, account.getJid()); tagWriter = new TagWriter(); - applicationContext = service.getApplicationContext(); + applicationContext = service.getApplicationContext(); } protected void changeStatus(int nextStatus) { @@ -172,13 +172,15 @@ public class XmppConnection implements Runnable { } else { boolean socketError = true; int srvIndex = 0; - while (socketError && namePort.containsKey("name" + srvIndex)){ + while (socketError + && namePort.containsKey("name" + srvIndex)) { try { - srvRecordServer = namePort.getString("name" + srvIndex); + srvRecordServer = namePort.getString("name" + + srvIndex); srvRecordPort = namePort.getInt("port" + srvIndex); Log.d(Config.LOGTAG, account.getJid() - + ": using values from dns " + srvRecordServer - + ":" + srvRecordPort); + + ": using values from dns " + + srvRecordServer + ":" + srvRecordPort); socket = new Socket(srvRecordServer, srvRecordPort); socketError = false; } catch (UnknownHostException e) { @@ -384,13 +386,13 @@ public class XmppConnection implements Runnable { iq.addChild("ping", "urn:xmpp:ping"); this.sendIqPacket(iq, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - Log.d(Config.LOGTAG, account.getJid() - + ": online with resource " + account.getResource()); - changeStatus(Account.STATUS_ONLINE); - } - }); + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + Log.d(Config.LOGTAG, account.getJid() + + ": online with resource " + account.getResource()); + changeStatus(Account.STATUS_ONLINE); + } + }); } private Element processPacket(Tag currentTag, int packetType) @@ -527,7 +529,8 @@ public class XmppConnection implements Runnable { } private SharedPreferences getPreferences() { - return PreferenceManager.getDefaultSharedPreferences(applicationContext); + return PreferenceManager + .getDefaultSharedPreferences(applicationContext); } private boolean enableLegacySSL() { @@ -551,14 +554,15 @@ public class XmppConnection implements Runnable { true); // Support all protocols except legacy SSL. - // The min SDK version prevents us having to worry about SSLv2. In future, this may be + // The min SDK version prevents us having to worry about SSLv2. In + // future, this may be // true of SSLv3 as well. final String[] supportProtocols; if (enableLegacySSL()) { supportProtocols = sslSocket.getSupportedProtocols(); } else { - final List supportedProtocols = new LinkedList(Arrays.asList( - sslSocket.getSupportedProtocols())); + final List supportedProtocols = new LinkedList( + Arrays.asList(sslSocket.getSupportedProtocols())); supportedProtocols.remove("SSLv3"); supportProtocols = new String[supportedProtocols.size()]; supportedProtocols.toArray(supportProtocols); @@ -613,7 +617,8 @@ public class XmppConnection implements Runnable { } else if (compressionAvailable()) { sendCompressionZlib(); } else if (this.streamFeatures.hasChild("register") - && account.isOptionSet(Account.OPTION_REGISTER) && usingEncryption) { + && account.isOptionSet(Account.OPTION_REGISTER) + && usingEncryption) { sendRegistryRequest(); } else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) { @@ -637,7 +642,8 @@ public class XmppConnection implements Runnable { } else if (this.streamFeatures.hasChild("bind") && shouldBind) { sendBindRequest(); } else { - Log.d(Config.LOGTAG,account.getJid()+": incompatible server. disconnecting"); + Log.d(Config.LOGTAG, account.getJid() + + ": incompatible server. disconnecting"); disconnect(true); } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 5b3dfbff..330a4ebb 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -358,8 +358,8 @@ public class JingleConnection implements Downloadable { Content content = new Content(this.contentCreator, this.contentName); if (message.getType() == Message.TYPE_IMAGE) { content.setTransportId(this.transportId); - this.file = this.mXmppConnectionService.getFileBackend() - .getFile(message, false); + this.file = this.mXmppConnectionService.getFileBackend().getFile( + message, false); if (message.getEncryption() == Message.ENCRYPTION_OTR) { Conversation conversation = this.message.getConversation(); this.mXmppConnectionService.renewSymmetricKey(conversation); @@ -634,7 +634,7 @@ public class JingleConnection implements Downloadable { } private void sendFallbackToIbb() { - Log.d(Config.LOGTAG,"sending fallback to ibb"); + Log.d(Config.LOGTAG, "sending fallback to ibb"); JinglePacket packet = this.bootstrapPacket("transport-replace"); Content content = new Content(this.contentCreator, this.contentName); this.transportId = this.mJingleConnectionManager.nextRandomId(); @@ -646,7 +646,7 @@ public class JingleConnection implements Downloadable { } private boolean receiveFallbackToIbb(JinglePacket packet) { - Log.d(Config.LOGTAG,"receiving fallack to ibb"); + Log.d(Config.LOGTAG, "receiving fallack to ibb"); String receivedBlockSize = packet.getJingleContent().ibbTransport() .getAttribute("block-size"); if (receivedBlockSize != null) { @@ -881,7 +881,7 @@ public class JingleConnection implements Downloadable { if (account.getStatus() == Account.STATUS_ONLINE) { if (mJingleStatus == JINGLE_STATUS_INITIATED) { new Thread(new Runnable() { - + @Override public void run() { sendAccept(); -- cgit v1.2.3 From 0d767c39711f171d94d4682f355370d4bdd225ae Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 21 Oct 2014 14:57:16 +0200 Subject: proper avatar caching --- .../siacs/conversations/parser/MessageParser.java | 4 + .../siacs/conversations/parser/PresenceParser.java | 2 + .../conversations/persistance/FileBackend.java | 44 +++---- .../conversations/services/AvatarService.java | 146 ++++++++++++++++++--- .../services/NotificationService.java | 22 ++-- .../services/XmppConnectionService.java | 27 +++- .../ui/ConferenceDetailsActivity.java | 31 ++--- .../conversations/ui/ContactDetailsActivity.java | 3 +- .../ui/PublishProfilePictureActivity.java | 4 +- src/eu/siacs/conversations/ui/XmppActivity.java | 5 + .../conversations/ui/adapter/AccountAdapter.java | 4 +- .../ui/adapter/ConversationAdapter.java | 5 +- .../conversations/ui/adapter/ListItemAdapter.java | 4 +- .../conversations/ui/adapter/MessageAdapter.java | 69 +++------- src/eu/siacs/conversations/utils/UIHelper.java | 17 --- 15 files changed, 223 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index daf0174c..e4be25bf 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -348,10 +348,14 @@ public class MessageParser extends AbstractParser implements mXmppConnectionService.databaseBackend .updateAccount(account); } + mXmppConnectionService.getAvatarService().clear( + account); } else { Contact contact = account.getRoster().getContact( from); contact.setAvatar(avatar.getFilename()); + mXmppConnectionService.getAvatarService().clear( + contact); } } else { mXmppConnectionService.fetchAvatar(account, avatar); diff --git a/src/eu/siacs/conversations/parser/PresenceParser.java b/src/eu/siacs/conversations/parser/PresenceParser.java index d54ddca0..4e90cda8 100644 --- a/src/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/eu/siacs/conversations/parser/PresenceParser.java @@ -29,6 +29,7 @@ public class PresenceParser extends AbstractParser implements if (before != muc.getMucOptions().online()) { mXmppConnectionService.updateConversationUi(); } + mXmppConnectionService.getAvatarService().clear(muc); } } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { Conversation muc = mXmppConnectionService.find(account, packet @@ -39,6 +40,7 @@ public class PresenceParser extends AbstractParser implements if (before != muc.getMucOptions().online()) { mXmppConnectionService.updateConversationUi(); } + mXmppConnectionService.getAvatarService().clear(muc); } } } diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 0a417b5c..b891e9ef 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -14,7 +14,6 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -28,12 +27,12 @@ import android.provider.MediaStore; import android.util.Base64; import android.util.Base64OutputStream; import android.util.Log; -import android.util.LruCache; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xmpp.pep.Avatar; @@ -41,27 +40,13 @@ public class FileBackend { private static int IMAGE_SIZE = 1920; - private Context context; - private LruCache thumbnailCache; - private SimpleDateFormat imageDateFormat = new SimpleDateFormat( "yyyyMMdd_HHmmssSSS", Locale.US); - public FileBackend(Context context) { - this.context = context; - int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); - int cacheSize = maxMemory / 8; - thumbnailCache = new LruCache(cacheSize) { - @Override - protected int sizeOf(String key, Bitmap bitmap) { - return bitmap.getByteCount() / 1024; - } - }; - - } + private XmppConnectionService mXmppConnectionService; - public LruCache getThumbnailCache() { - return thumbnailCache; + public FileBackend(XmppConnectionService service) { + this.mXmppConnectionService = service; } public DownloadableFile getFile(Message message) { @@ -127,7 +112,7 @@ public class FileBackend { private DownloadableFile copyImageToPrivateStorage(Message message, Uri image, int sampleSize) throws ImageCopyException { try { - InputStream is = context.getContentResolver() + InputStream is = mXmppConnectionService.getContentResolver() .openInputStream(image); DownloadableFile file = getFile(message); file.getParentFile().mkdirs(); @@ -182,7 +167,7 @@ public class FileBackend { private int getRotation(Uri image) { if ("content".equals(image.getScheme())) { try { - Cursor cursor = context + Cursor cursor = mXmppConnectionService .getContentResolver() .query(image, new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, @@ -223,7 +208,8 @@ public class FileBackend { public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws FileNotFoundException { - Bitmap thumbnail = thumbnailCache.get(message.getUuid()); + Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get( + message.getUuid()); if ((thumbnail == null) && (!cacheOnly)) { File file = getFile(message); BitmapFactory.Options options = new BitmapFactory.Options(); @@ -234,13 +220,14 @@ public class FileBackend { throw new FileNotFoundException(); } thumbnail = resize(fullsize, size); - this.thumbnailCache.put(message.getUuid(), thumbnail); + this.mXmppConnectionService.getBitmapCache().put(message.getUuid(), + thumbnail); } return thumbnail; } public void removeFiles(Conversation conversation) { - String prefix = context.getFilesDir().getAbsolutePath(); + String prefix = mXmppConnectionService.getFilesDir().getAbsolutePath(); String path = prefix + "/" + conversation.getAccount().getJid() + "/" + conversation.getContactJid(); File file = new File(path); @@ -345,7 +332,8 @@ public class FileBackend { } public String getAvatarPath(String avatar) { - return context.getFilesDir().getAbsolutePath() + "/avatars/" + avatar; + return mXmppConnectionService.getFilesDir().getAbsolutePath() + + "/avatars/" + avatar; } public Uri getAvatarUri(String avatar) { @@ -356,7 +344,7 @@ public class FileBackend { try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = calcSampleSize(image, size); - InputStream is = context.getContentResolver() + InputStream is = mXmppConnectionService.getContentResolver() .openInputStream(image); Bitmap input = BitmapFactory.decodeStream(is, null, options); if (input == null) { @@ -378,7 +366,7 @@ public class FileBackend { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = calcSampleSize(image, Math.max(newHeight, newWidth)); - InputStream is = context.getContentResolver() + InputStream is = mXmppConnectionService.getContentResolver() .openInputStream(image); Bitmap source = BitmapFactory.decodeStream(is, null, options); @@ -428,7 +416,7 @@ public class FileBackend { throws FileNotFoundException { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(context.getContentResolver() + BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver() .openInputStream(image), null, options); return calcSampleSize(options, size); } diff --git a/src/eu/siacs/conversations/services/AvatarService.java b/src/eu/siacs/conversations/services/AvatarService.java index def3bfd8..c0668a19 100644 --- a/src/eu/siacs/conversations/services/AvatarService.java +++ b/src/eu/siacs/conversations/services/AvatarService.java @@ -1,8 +1,10 @@ package eu.siacs.conversations.services; +import java.util.ArrayList; import java.util.List; import java.util.Locale; +import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; @@ -15,20 +17,34 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.net.Uri; +import android.util.Log; public class AvatarService { private static final int FG_COLOR = 0xFFFAFAFA; private static final int TRANSPARENT = 0x00000000; + private static final String PREFIX_CONTACT = "contact"; + private static final String PREFIX_CONVERSATION = "conversation"; + private static final String PREFIX_ACCOUNT = "account"; + private static final String PREFIX_GENERIC = "generic"; + + private ArrayList sizes = new ArrayList(); + protected XmppConnectionService mXmppConnectionService = null; public AvatarService(XmppConnectionService service) { this.mXmppConnectionService = service; } - public Bitmap getAvatar(Contact contact, int size) { - Bitmap avatar = mXmppConnectionService.getFileBackend().getAvatar( + public Bitmap get(Contact contact, int size) { + final String KEY = key(contact, size); + Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); + if (avatar != null) { + return avatar; + } + Log.d(Config.LOGTAG, "no cache hit for " + KEY); + avatar = mXmppConnectionService.getFileBackend().getAvatar( contact.getAvatar(), size); if (avatar == null) { if (contact.getProfilePhoto() != null) { @@ -36,43 +52,74 @@ public class AvatarService { .cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size); if (avatar == null) { - avatar = getAvatar(contact.getDisplayName(), size); + avatar = get(contact.getDisplayName(), size); } } else { - avatar = getAvatar(contact.getDisplayName(), size); + avatar = get(contact.getDisplayName(), size); } } + this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; } - public Bitmap getAvatar(ListItem item, int size) { + public void clear(Contact contact) { + for (Integer size : sizes) { + this.mXmppConnectionService.getBitmapCache().remove( + key(contact, size)); + } + } + + private String key(Contact contact, int size) { + synchronized (this.sizes) { + if (!this.sizes.contains(size)) { + this.sizes.add(size); + } + } + return PREFIX_CONTACT + "_" + contact.getAccount().getJid() + "_" + + contact.getJid() + "_" + String.valueOf(size); + } + + public Bitmap get(ListItem item, int size) { if (item instanceof Contact) { - return getAvatar((Contact) item, size); + return get((Contact) item, size); } else if (item instanceof Bookmark) { Bookmark bookmark = (Bookmark) item; if (bookmark.getConversation() != null) { - return getAvatar(bookmark.getConversation(), size); + return get(bookmark.getConversation(), size); } else { - return getAvatar(bookmark.getDisplayName(), size); + return get(bookmark.getDisplayName(), size); } } else { - return getAvatar(item.getDisplayName(), size); + return get(item.getDisplayName(), size); } } - public Bitmap getAvatar(Conversation conversation, int size) { + public Bitmap get(Conversation conversation, int size) { if (conversation.getMode() == Conversation.MODE_SINGLE) { - return getAvatar(conversation.getContact(), size); + return get(conversation.getContact(), size); } else { - return getAvatar(conversation.getMucOptions(), size); + return get(conversation.getMucOptions(), size); } } - public Bitmap getAvatar(MucOptions mucOptions, int size) { + public void clear(Conversation conversation) { + if (conversation.getMode() == Conversation.MODE_SINGLE) { + clear(conversation.getContact()); + } else { + clear(conversation.getMucOptions()); + } + } + + public Bitmap get(MucOptions mucOptions, int size) { + final String KEY = key(mucOptions, size); + Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY); + if (bitmap != null) { + return bitmap; + } + Log.d(Config.LOGTAG, "no cache hit for " + KEY); List users = mucOptions.getUsers(); int count = users.size(); - Bitmap bitmap = Bitmap - .createBitmap(size, size, Bitmap.Config.ARGB_8888); + bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); bitmap.eraseColor(TRANSPARENT); @@ -104,28 +151,85 @@ public class AvatarService { drawTile(canvas, "\u2026", 0xFF202020, size / 2 + 1, size / 2 + 1, size, size); } + this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap); return bitmap; } - public Bitmap getAvatar(Account account, int size) { - Bitmap avatar = mXmppConnectionService.getFileBackend().getAvatar( + public void clear(MucOptions options) { + for (Integer size : sizes) { + this.mXmppConnectionService.getBitmapCache().remove( + key(options, size)); + } + } + + private String key(MucOptions options, int size) { + synchronized (this.sizes) { + if (!this.sizes.contains(size)) { + this.sizes.add(size); + } + } + return PREFIX_CONVERSATION + "_" + options.getConversation().getUuid() + + "_" + String.valueOf(size); + } + + public Bitmap get(Account account, int size) { + final String KEY = key(account, size); + Bitmap avatar = mXmppConnectionService.getBitmapCache().get(KEY); + if (avatar != null) { + return avatar; + } + Log.d(Config.LOGTAG, "no cache hit for " + KEY); + avatar = mXmppConnectionService.getFileBackend().getAvatar( account.getAvatar(), size); if (avatar == null) { - avatar = getAvatar(account.getJid(), size); + avatar = get(account.getJid(), size); } + mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; } - public Bitmap getAvatar(String name, int size) { - Bitmap bitmap = Bitmap - .createBitmap(size, size, Bitmap.Config.ARGB_8888); + public void clear(Account account) { + for (Integer size : sizes) { + this.mXmppConnectionService.getBitmapCache().remove( + key(account, size)); + } + } + + private String key(Account account, int size) { + synchronized (this.sizes) { + if (!this.sizes.contains(size)) { + this.sizes.add(size); + } + } + return PREFIX_ACCOUNT + "_" + account.getUuid() + "_" + + String.valueOf(size); + } + + public Bitmap get(String name, int size) { + final String KEY = key(name, size); + Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY); + if (bitmap != null) { + return bitmap; + } + Log.d(Config.LOGTAG, "no cache hit for " + KEY); + bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); String letter = name.substring(0, 1); int color = this.getColorForName(name); drawTile(canvas, letter, color, 0, 0, size, size); + mXmppConnectionService.getBitmapCache().put(KEY, bitmap); return bitmap; } + private String key(String name, int size) { + synchronized (this.sizes) { + if (!this.sizes.contains(size)) { + this.sizes.add(size); + } + } + return PREFIX_GENERIC + "_" + name + "_" + String.valueOf(size); + } + private void drawTile(Canvas canvas, String letter, int tileColor, int left, int top, int right, int bottom) { letter = letter.toUpperCase(Locale.getDefault()); diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index a1336123..8eba49a9 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -16,6 +16,7 @@ import android.os.PowerManager; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.text.Html; +import android.util.DisplayMetrics; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; @@ -26,7 +27,6 @@ import eu.siacs.conversations.ui.ConversationActivity; public class NotificationService { private XmppConnectionService mXmppConnectionService; - private NotificationManager mNotificationManager; private LinkedHashMap> notifications = new LinkedHashMap>(); @@ -36,8 +36,6 @@ public class NotificationService { public NotificationService(XmppConnectionService service) { this.mXmppConnectionService = service; - this.mNotificationManager = (NotificationManager) service - .getSystemService(Context.NOTIFICATION_SERVICE); } public void push(Message message) { @@ -79,6 +77,8 @@ public class NotificationService { } private void updateNotification(boolean notify) { + NotificationManager notificationManager = (NotificationManager) mXmppConnectionService + .getSystemService(Context.NOTIFICATION_SERVICE); SharedPreferences preferences = mXmppConnectionService.getPreferences(); String ringtone = preferences.getString("notification_ringtone", null); @@ -86,7 +86,7 @@ public class NotificationService { true); if (notifications.size() == 0) { - mNotificationManager.cancel(NOTIFICATION_ID); + notificationManager.cancel(NOTIFICATION_ID); } else { NotificationCompat.Builder mBuilder = new NotificationCompat.Builder( mXmppConnectionService); @@ -97,8 +97,8 @@ public class NotificationService { if (messages.size() >= 1) { Conversation conversation = messages.get(0) .getConversation(); - // mBuilder.setLargeIcon(conversation.getImage(mXmppConnectionService, - // 64)); + mBuilder.setLargeIcon(mXmppConnectionService + .getAvatarService().get(conversation, getPixel(64))); mBuilder.setContentTitle(conversation.getName()); StringBuilder text = new StringBuilder(); for (int i = 0; i < messages.size(); ++i) { @@ -119,7 +119,7 @@ public class NotificationService { mBuilder.setContentIntent(createContentIntent(conversation .getUuid())); } else { - mNotificationManager.cancel(NOTIFICATION_ID); + notificationManager.cancel(NOTIFICATION_ID); return; } } else { @@ -170,7 +170,7 @@ public class NotificationService { mBuilder.setDeleteIntent(createDeleteIntent()); mBuilder.setLights(0xffffffff, 2000, 4000); Notification notification = mBuilder.build(); - mNotificationManager.notify(NOTIFICATION_ID, notification); + notificationManager.notify(NOTIFICATION_ID, notification); } } @@ -227,4 +227,10 @@ public class NotificationService { public void setIsInForeground(boolean foreground) { this.mIsInForeground = foreground; } + + private int getPixel(int dp) { + DisplayMetrics metrics = mXmppConnectionService.getResources() + .getDisplayMetrics(); + return ((int) (dp * metrics.density)); + } } diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 6c8dc17a..5da87b10 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -84,11 +84,12 @@ import android.os.SystemClock; import android.preference.PreferenceManager; import android.provider.ContactsContract; import android.util.Log; +import android.util.LruCache; public class XmppConnectionService extends Service { public DatabaseBackend databaseBackend; - private FileBackend fileBackend; + private FileBackend fileBackend = new FileBackend(this); public long startDate; @@ -97,7 +98,8 @@ public class XmppConnectionService extends Service { private MemorizingTrustManager mMemorizingTrustManager; - private NotificationService mNotificationService; + private NotificationService mNotificationService = new NotificationService( + this); private MessageParser mMessageParser = new MessageParser(this); private PresenceParser mPresenceParser = new PresenceParser(this); @@ -269,6 +271,7 @@ public class XmppConnectionService extends Service { } } }; + private LruCache mBitmapCache; public PgpEngine getPgpEngine() { if (pgpServiceConnection.isBound()) { @@ -429,10 +432,18 @@ public class XmppConnectionService extends Service { this.mRandom = new SecureRandom(); this.mMemorizingTrustManager = new MemorizingTrustManager( getApplicationContext()); - this.mNotificationService = new NotificationService(this); + + int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); + int cacheSize = maxMemory / 8; + this.mBitmapCache = new LruCache(cacheSize) { + @Override + protected int sizeOf(String key, Bitmap bitmap) { + return bitmap.getByteCount() / 1024; + } + }; + this.databaseBackend = DatabaseBackend .getInstance(getApplicationContext()); - this.fileBackend = new FileBackend(getApplicationContext()); this.accounts = databaseBackend.getAccounts(); for (Account account : this.accounts) { @@ -801,6 +812,7 @@ public class XmppConnectionService extends Service { .getString("photouri")); contact.setSystemName(phoneContact .getString("displayname")); + getAvatarService().clear(contact); } } } @@ -1497,10 +1509,12 @@ public class XmppConnectionService extends Service { if (account.setAvatar(avatar.getFilename())) { databaseBackend.updateAccount(account); } + getAvatarService().clear(account); } else { Contact contact = account.getRoster() .getContact(avatar.owner); contact.setAvatar(avatar.getFilename()); + getAvatarService().clear(contact); } if (callback != null) { callback.success(avatar); @@ -1550,6 +1564,7 @@ public class XmppConnectionService extends Service { if (account.setAvatar(avatar.getFilename())) { databaseBackend.updateAccount(account); } + getAvatarService().clear(account); callback.success(avatar); } else { fetchAvatar(account, avatar, callback); @@ -1762,6 +1777,10 @@ public class XmppConnectionService extends Service { return this.pm; } + public LruCache getBitmapCache() { + return this.mBitmapCache; + } + public void replyWithNotAcceptable(Account account, MessagePacket packet) { if (account.getStatus() == Account.STATUS_ONLINE) { MessagePacket error = this.mMessageGenerator diff --git a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 98bf70ed..6b4642cb 100644 --- a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -7,14 +7,12 @@ import org.openintents.openpgp.util.OpenPgpUtils; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; -import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions.OnRenameListener; import eu.siacs.conversations.entities.MucOptions.User; import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate; -import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import android.app.PendingIntent; import android.content.Context; @@ -201,8 +199,8 @@ public class ConferenceDetailsActivity extends XmppActivity { private void populateView() { mAccountJid.setText(getString(R.string.using_account, conversation .getAccount().getJid())); - mYourPhoto.setImageBitmap(xmppConnectionService.getAvatarService() - .getAvatar(conversation.getAccount(), getPixel(48))); + mYourPhoto.setImageBitmap(avatarService().get( + conversation.getAccount(), getPixel(48))); setTitle(conversation.getName()); mFullJid.setText(conversation.getContactJid().split("/", 2)[0]); mYourNick.setText(conversation.getMucOptions().getActualNick()); @@ -228,7 +226,6 @@ public class ConferenceDetailsActivity extends XmppActivity { this.users.addAll(conversation.getMucOptions().getUsers()); LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); membersView.removeAllViews(); - Account account = conversation.getAccount(); for (final User user : conversation.getMucOptions().getUsers()) { View view = (View) inflater.inflate(R.layout.contact, membersView, false); @@ -248,24 +245,14 @@ public class ConferenceDetailsActivity extends XmppActivity { key.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); } Bitmap bm; - if (user.getJid() != null) { - Contact contact = account.getRoster().getContactFromRoster( - user.getJid()); - if (contact != null) { - bm = xmppConnectionService.getAvatarService().getAvatar( - contact, getPixel(48)); - name.setText(contact.getDisplayName()); - role.setText(user.getName() + " \u2022 " - + getReadableRole(user.getRole())); - } else { - bm = xmppConnectionService.getAvatarService().getAvatar( - user.getName(), getPixel(48)); - name.setText(user.getName()); - role.setText(getReadableRole(user.getRole())); - } + Contact contact = user.getContact(); + if (contact != null) { + bm = avatarService().get(contact, getPixel(48)); + name.setText(contact.getDisplayName()); + role.setText(user.getName() + " \u2022 " + + getReadableRole(user.getRole())); } else { - bm = xmppConnectionService.getAvatarService().getAvatar( - user.getName(), getPixel(48)); + bm = avatarService().get(user.getName(), getPixel(48)); name.setText(user.getName()); role.setText(getReadableRole(user.getRole())); } diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java index d43eee59..ae26466e 100644 --- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -386,8 +386,7 @@ public class ContactDetailsActivity extends XmppActivity { long id = Long.parseLong(systemAccount[0]); badge.assignContactUri(Contacts.getLookupUri(id, systemAccount[1])); } - badge.setImageBitmap(xmppConnectionService.getAvatarService() - .getAvatar(contact, getPixel(72))); + badge.setImageBitmap(avatarService().get(contact, getPixel(72))); } protected void confirmToDeleteFingerprint(final String fingerprint) { diff --git a/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index 24330361..6aa40c41 100644 --- a/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -158,8 +158,8 @@ public class PublishProfilePictureActivity extends XmppActivity { if (this.avatarUri == null) { if (this.account.getAvatar() != null || this.defaultUri == null) { - // this.avatar.setImageBitmap(this.account.getImage(getApplicationContext(), - // 384)); + this.avatar.setImageBitmap(avatarService().get(account, + getPixel(194))); if (this.defaultUri != null) { this.avatar .setOnLongClickListener(this.backToDefaultListener); diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index ca1bf465..d26f0e31 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -12,6 +12,7 @@ import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Presences; +import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; import eu.siacs.conversations.utils.ExceptionHelper; @@ -531,6 +532,10 @@ public abstract class XmppActivity extends Activity { return ((int) (dp * metrics.density)); } + public AvatarService avatarService() { + return xmppConnectionService.getAvatarService(); + } + class BitmapWorkerTask extends AsyncTask { private final WeakReference imageViewReference; private Message message = null; diff --git a/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java index 40229953..4ca21a3b 100644 --- a/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -34,8 +34,8 @@ public class AccountAdapter extends ArrayAdapter { jid.setText(account.getJid()); TextView statusView = (TextView) view.findViewById(R.id.account_status); ImageView imageView = (ImageView) view.findViewById(R.id.account_image); - imageView.setImageBitmap(activity.xmppConnectionService - .getAvatarService().getAvatar(account, activity.getPixel(48))); + imageView.setImageBitmap(activity.avatarService().get(account, + activity.getPixel(48))); switch (account.getStatus()) { case Account.STATUS_DISABLED: statusView.setText(getContext().getString( diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 1fea8dcf..183c89fa 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -127,9 +127,8 @@ public class ConversationAdapter extends ArrayAdapter { ImageView profilePicture = (ImageView) view .findViewById(R.id.conversation_image); - profilePicture.setImageBitmap(activity.xmppConnectionService - .getAvatarService().getAvatar(conversation, - activity.getPixel(56))); + profilePicture.setImageBitmap(activity.avatarService().get( + conversation, activity.getPixel(56))); return view; } diff --git a/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 64e077a3..977aa7b5 100644 --- a/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -36,8 +36,8 @@ public class ListItemAdapter extends ArrayAdapter { jid.setText(item.getJid()); name.setText(item.getDisplayName()); - picture.setImageBitmap(activity.xmppConnectionService - .getAvatarService().getAvatar(item, activity.getPixel(48))); + picture.setImageBitmap(activity.avatarService().get(item, + activity.getPixel(48))); return view; } diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index bc5b3387..a9a55cbf 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.ui.adapter; -import java.util.HashMap; import java.util.List; import eu.siacs.conversations.Config; @@ -12,9 +11,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.utils.UIHelper; -import android.content.Context; import android.content.Intent; -import android.graphics.Bitmap; import android.graphics.Typeface; import android.text.Spannable; import android.text.SpannableString; @@ -41,9 +38,6 @@ public class MessageAdapter extends ArrayAdapter { private ConversationActivity activity; - private Bitmap accountBitmap; - - private BitmapCache mBitmapCache = new BitmapCache(); private DisplayMetrics metrics; private OnContactPictureClicked mOnContactPictureClickedListener; @@ -55,19 +49,6 @@ public class MessageAdapter extends ArrayAdapter { metrics = getContext().getResources().getDisplayMetrics(); } - private Bitmap getSelfBitmap() { - if (this.accountBitmap == null) { - - if (getCount() > 0) { - this.accountBitmap = activity.xmppConnectionService - .getAvatarService().getAvatar( - getItem(0).getConversation().getAccount(), - activity.getPixel(48)); - } - } - return this.accountBitmap; - } - public void setOnContactPictureClicked(OnContactPictureClicked listener) { this.mOnContactPictureClickedListener = listener; } @@ -349,7 +330,10 @@ public class MessageAdapter extends ArrayAdapter { .findViewById(R.id.message_box); viewHolder.contact_picture = (ImageView) view .findViewById(R.id.message_photo); - viewHolder.contact_picture.setImageBitmap(getSelfBitmap()); + viewHolder.contact_picture.setImageBitmap(activity + .avatarService().get( + item.getConversation().getAccount(), + activity.getPixel(48))); viewHolder.download_button = (Button) view .findViewById(R.id.download_button); viewHolder.indicator = (ImageView) view @@ -374,8 +358,9 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.download_button = (Button) view .findViewById(R.id.download_button); if (item.getConversation().getMode() == Conversation.MODE_SINGLE) { - viewHolder.contact_picture.setImageBitmap(mBitmapCache.get( - item.getConversation().getContact(), getContext())); + viewHolder.contact_picture.setImageBitmap(activity + .avatarService().get(item.getContact(), + activity.getPixel(48))); } viewHolder.indicator = (ImageView) view .findViewById(R.id.security_indicator); @@ -394,8 +379,10 @@ public class MessageAdapter extends ArrayAdapter { .findViewById(R.id.message_photo); if (item.getConversation().getMode() == Conversation.MODE_SINGLE) { - viewHolder.contact_picture.setImageBitmap(mBitmapCache.get( - item.getConversation().getContact(), getContext())); + viewHolder.contact_picture.setImageBitmap(activity + .avatarService().get( + item.getConversation().getContact(), + activity.getPixel(32))); viewHolder.contact_picture.setAlpha(0.5f); viewHolder.contact_picture .setOnClickListener(new OnClickListener() { @@ -471,15 +458,16 @@ public class MessageAdapter extends ArrayAdapter { if (item.getConversation().getMode() == Conversation.MODE_MULTI) { Contact contact = item.getContact(); if (contact != null) { - viewHolder.contact_picture.setImageBitmap(mBitmapCache.get( - contact, getContext())); + viewHolder.contact_picture.setImageBitmap(activity + .avatarService() + .get(contact, activity.getPixel(48))); } else { String name = item.getPresence(); if (name == null) { name = item.getCounterpart(); } - viewHolder.contact_picture.setImageBitmap(mBitmapCache.get( - name, getContext())); + viewHolder.contact_picture.setImageBitmap(activity + .avatarService().get(name, activity.getPixel(48))); } } } @@ -562,31 +550,6 @@ public class MessageAdapter extends ArrayAdapter { } - private class BitmapCache { - private HashMap contactBitmaps = new HashMap(); - private HashMap unknownBitmaps = new HashMap(); - - public Bitmap get(Contact contact, Context context) { - if (!contactBitmaps.containsKey(contact.getJid())) { - contactBitmaps.put(contact.getJid(), - activity.xmppConnectionService.getAvatarService() - .getAvatar(contact, activity.getPixel(48))); - } - return contactBitmaps.get(contact.getJid()); - } - - public Bitmap get(String name, Context context) { - if (unknownBitmaps.containsKey(name)) { - return unknownBitmaps.get(name); - } else { - Bitmap bm = activity.xmppConnectionService.getAvatarService() - .getAvatar(name, activity.getPixel(48)); - unknownBitmaps.put(name, bm); - return bm; - } - } - } - public interface OnContactPictureClicked { public void onContactPictureClicked(Message message); } diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java index 57e9153d..5141c83c 100644 --- a/src/eu/siacs/conversations/utils/UIHelper.java +++ b/src/eu/siacs/conversations/utils/UIHelper.java @@ -1,22 +1,18 @@ package eu.siacs.conversations.utils; -import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.regex.Pattern; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.MucOptions.User; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.ManageAccountActivity; import android.annotation.SuppressLint; -import android.app.Activity; import android.app.AlertDialog; import android.app.Notification; import android.app.NotificationManager; @@ -25,28 +21,15 @@ import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.net.Uri; -import android.provider.ContactsContract.Contacts; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.text.format.DateFormat; import android.text.format.DateUtils; -import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; -import android.widget.QuickContactBadge; import android.widget.TextView; public class UIHelper { - private static final int BG_COLOR = 0xFF181818; - private static final int FG_COLOR = 0xFFFAFAFA; - private static final int TRANSPARENT = 0x00000000; private static final int SHORT_DATE_FLAGS = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR | DateUtils.FORMAT_ABBREV_ALL; private static final int FULL_DATE_FLAGS = DateUtils.FORMAT_SHOW_TIME -- cgit v1.2.3 From a56ee63a3ebe6c224b967d4b40ab2ccf4386dbed Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 21 Oct 2014 15:26:17 +0200 Subject: update ui when new avatar was found --- src/eu/siacs/conversations/parser/MessageParser.java | 4 ++++ src/eu/siacs/conversations/services/XmppConnectionService.java | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index e4be25bf..b5e14305 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -350,12 +350,16 @@ public class MessageParser extends AbstractParser implements } mXmppConnectionService.getAvatarService().clear( account); + mXmppConnectionService.updateConversationUi(); + mXmppConnectionService.updateAccountUi(); } else { Contact contact = account.getRoster().getContact( from); contact.setAvatar(avatar.getFilename()); mXmppConnectionService.getAvatarService().clear( contact); + mXmppConnectionService.updateConversationUi(); + mXmppConnectionService.updateRosterUi(); } } else { mXmppConnectionService.fetchAvatar(account, avatar); diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 5da87b10..37e334eb 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1510,11 +1510,15 @@ public class XmppConnectionService extends Service { databaseBackend.updateAccount(account); } getAvatarService().clear(account); + updateConversationUi(); + updateAccountUi(); } else { Contact contact = account.getRoster() .getContact(avatar.owner); contact.setAvatar(avatar.getFilename()); getAvatarService().clear(contact); + updateConversationUi(); + updateRosterUi(); } if (callback != null) { callback.success(avatar); -- cgit v1.2.3 From 3821a726440eb880164d1cc2d61ce3a7715f0ddb Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 21 Oct 2014 19:43:34 +0200 Subject: fixed #564 --- src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java | 4 ++-- src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java | 4 ++-- src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 330a4ebb..a0b2feb2 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -150,8 +150,8 @@ public class JingleConnection implements Downloadable { return this.sessionId; } - public String getAccountJid() { - return this.account.getFullJid(); + public Account getAccount() { + return this.account; } public String getCounterPart() { diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 40ccbfe3..c8209bd9 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -36,7 +36,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { connections.add(connection); } else { for (JingleConnection connection : connections) { - if (connection.getAccountJid().equals(account.getFullJid()) + if (connection.getAccount() == account && connection.getSessionId().equals( packet.getSessionId()) && connection.getCounterPart().equals(packet.getFrom())) { @@ -136,7 +136,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { } if (sid != null) { for (JingleConnection connection : connections) { - if (connection.hasTransportId(sid)) { + if (connection.getAccount() == account && connection.hasTransportId(sid)) { JingleTransport transport = connection.getTransport(); if (transport instanceof JingleInbandTransport) { JingleInbandTransport inbandTransport = (JingleInbandTransport) transport; diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java index f1dd1e51..1da2f0cd 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -30,11 +30,11 @@ public class JingleSocks5Transport extends JingleTransport { StringBuilder destBuilder = new StringBuilder(); destBuilder.append(jingleConnection.getSessionId()); if (candidate.isOurs()) { - destBuilder.append(jingleConnection.getAccountJid()); + destBuilder.append(jingleConnection.getAccount().getFullJid()); destBuilder.append(jingleConnection.getCounterPart()); } else { destBuilder.append(jingleConnection.getCounterPart()); - destBuilder.append(jingleConnection.getAccountJid()); + destBuilder.append(jingleConnection.getAccount().getFullJid()); } mDigest.reset(); this.destination = CryptoHelper.bytesToHex(mDigest -- cgit v1.2.3 From 63704b114c858e45cbbd765e713f6fea76fd1595 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 21 Oct 2014 20:13:06 +0200 Subject: throw exception when no servers are left to try --- src/eu/siacs/conversations/xmpp/XmppConnection.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index ffa438bd..2a72f4c2 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -185,8 +185,14 @@ public class XmppConnection implements Runnable { socketError = false; } catch (UnknownHostException e) { srvIndex++; + if (!namePort.containsKey("name" + srvIndex)) { + throw e; + } } catch (IOException e) { srvIndex++; + if (!namePort.containsKey("name" + srvIndex)) { + throw e; + } } } } -- cgit v1.2.3 From 40c74b432ed5151538fd50218a19e6973524d98e Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 21 Oct 2014 23:59:02 +0200 Subject: made iterating over hashmap in notification service thread safe --- src/eu/siacs/conversations/services/NotificationService.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 8eba49a9..7a116ed4 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -1,7 +1,9 @@ package eu.siacs.conversations.services; import java.util.ArrayList; +import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -130,7 +132,11 @@ public class NotificationService { .getString(R.string.unread_conversations)); StringBuilder names = new StringBuilder(); Conversation conversation = null; - for (ArrayList messages : notifications.values()) { + Iterator>> it = notifications + .entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + ArrayList messages = entry.getValue(); if (messages.size() > 0) { conversation = messages.get(0).getConversation(); String name = conversation.getName(); @@ -142,6 +148,7 @@ public class NotificationService { names.append(name); names.append(", "); } + it.remove(); } if (names.length() >= 2) { names.delete(names.length() - 2, names.length()); -- cgit v1.2.3 From df2257aed68f0c886d96b9474d611923801fe65e Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 22 Oct 2014 00:00:01 +0200 Subject: added hostname verifier to httpconnection --- .../siacs/conversations/http/HttpConnection.java | 40 ++++++++++++++++------ .../siacs/conversations/xmpp/XmppConnection.java | 3 +- 2 files changed, 32 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index cbcdfb5c..467b6a80 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -9,15 +9,20 @@ import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.X509TrustManager; +import org.apache.http.conn.ssl.StrictHostnameVerifier; + import android.content.Intent; import android.graphics.BitmapFactory; import android.net.Uri; +import android.util.Log; +import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; @@ -32,7 +37,6 @@ public class HttpConnection implements Downloadable { private Message message; private DownloadableFile file; private int mStatus = Downloadable.STATUS_UNKNOWN; - private boolean mAutostart = true; public HttpConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; @@ -45,8 +49,7 @@ public class HttpConnection implements Downloadable { if (this.mStatus == STATUS_OFFER_CHECK_FILESIZE) { checkFileSize(true); } else { - changeStatus(STATUS_DOWNLOADING); - new Thread(new FileDownloader()).start(); + new Thread(new FileDownloader(true)).start(); } return true; } else { @@ -61,7 +64,6 @@ public class HttpConnection implements Downloadable { mUrl = new URL(message.getBody()); this.file = mXmppConnectionService.getFileBackend().getFile( message, false); - this.mAutostart = true; checkFileSize(false); } catch (MalformedURLException e) { this.cancel(); @@ -69,7 +71,6 @@ public class HttpConnection implements Downloadable { } private void checkFileSize(boolean interactive) { - changeStatus(STATUS_CHECKING); new Thread(new FileSizeChecker(interactive)).start(); } @@ -95,17 +96,26 @@ public class HttpConnection implements Downloadable { private void setupTrustManager(HttpsURLConnection connection, boolean interactive) { X509TrustManager trustManager; + HostnameVerifier hostnameVerifier; if (interactive) { trustManager = mXmppConnectionService.getMemorizingTrustManager(); + hostnameVerifier = mXmppConnectionService + .getMemorizingTrustManager().wrapHostnameVerifier( + new StrictHostnameVerifier()); } else { trustManager = mXmppConnectionService.getMemorizingTrustManager() .getNonInteractive(); + hostnameVerifier = mXmppConnectionService + .getMemorizingTrustManager() + .wrapHostnameVerifierNonInteractive( + new StrictHostnameVerifier()); } try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new X509TrustManager[] { trustManager }, mXmppConnectionService.getRNG()); connection.setSSLSocketFactory(sc.getSocketFactory()); + connection.setHostnameVerifier(hostnameVerifier); } catch (KeyManagementException e) { return; } catch (NoSuchAlgorithmException e) { @@ -134,9 +144,8 @@ public class HttpConnection implements Downloadable { return; } file.setExpectedSize(size); - if (size <= mHttpConnectionManager.getAutoAcceptFileSize() - && mAutostart) { - start(); + if (size <= mHttpConnectionManager.getAutoAcceptFileSize()) { + new Thread(new FileDownloader(interactive)).start(); } else { changeStatus(STATUS_OFFER); } @@ -144,6 +153,7 @@ public class HttpConnection implements Downloadable { private long retrieveFileSize() throws IOException, SSLHandshakeException { + changeStatus(STATUS_CHECKING); HttpURLConnection connection = (HttpURLConnection) mUrl .openConnection(); connection.setRequestMethod("HEAD"); @@ -166,23 +176,33 @@ public class HttpConnection implements Downloadable { private class FileDownloader implements Runnable { + private boolean interactive = false; + + public FileDownloader(boolean interactive) { + this.interactive = interactive; + } + @Override public void run() { try { + changeStatus(STATUS_DOWNLOADING); download(); updateImageBounds(); finish(); + } catch (SSLHandshakeException e) { + changeStatus(STATUS_OFFER); } catch (IOException e) { cancel(); } } - private void download() throws IOException { + private void download() throws SSLHandshakeException, IOException { HttpURLConnection connection = (HttpURLConnection) mUrl .openConnection(); if (connection instanceof HttpsURLConnection) { - setupTrustManager((HttpsURLConnection) connection, true); + setupTrustManager((HttpsURLConnection) connection, interactive); } + connection.connect(); BufferedInputStream is = new BufferedInputStream( connection.getInputStream()); OutputStream os = file.createOutputStream(); diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 2a72f4c2..903dc59d 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -24,6 +24,7 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509TrustManager; +import org.apache.http.conn.ssl.StrictHostnameVerifier; import org.xmlpull.v1.XmlPullParserException; import de.duenndns.ssl.MemorizingTrustManager; @@ -554,7 +555,7 @@ public class XmppConnection implements Runnable { SSLSocketFactory factory = sc.getSocketFactory(); HostnameVerifier verifier = this.mMemorizingTrustManager - .wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()); + .wrapHostnameVerifier(new StrictHostnameVerifier()); SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true); -- cgit v1.2.3 From 45bdadd915ed0e0135de16876f9842b3401f1ac4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 22 Oct 2014 00:25:28 +0200 Subject: better aproach on thread saftey --- .../conversations/services/NotificationService.java | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 7a116ed4..00765deb 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -1,9 +1,7 @@ package eu.siacs.conversations.services; import java.util.ArrayList; -import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -58,24 +56,25 @@ public class NotificationService { mList.add(message); notifications.put(conversationUuid, mList); } + Account account = message.getConversation().getAccount(); + updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) + && !account.inGracePeriod()); } - Account account = message.getConversation().getAccount(); - updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) - && !account.inGracePeriod()); + } public void clear() { synchronized (notifications) { notifications.clear(); + updateNotification(false); } - updateNotification(false); } public void clear(Conversation conversation) { synchronized (notifications) { notifications.remove(conversation.getUuid()); + updateNotification(false); } - updateNotification(false); } private void updateNotification(boolean notify) { @@ -132,11 +131,7 @@ public class NotificationService { .getString(R.string.unread_conversations)); StringBuilder names = new StringBuilder(); Conversation conversation = null; - Iterator>> it = notifications - .entrySet().iterator(); - while (it.hasNext()) { - Entry> entry = it.next(); - ArrayList messages = entry.getValue(); + for (ArrayList messages : notifications.values()) { if (messages.size() > 0) { conversation = messages.get(0).getConversation(); String name = conversation.getName(); @@ -148,7 +143,6 @@ public class NotificationService { names.append(name); names.append(", "); } - it.remove(); } if (names.length() >= 2) { names.delete(names.length() - 2, names.length()); -- cgit v1.2.3 From 62b0fc3fdac1af440d61bb6d197dcd7fc34372b4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 22 Oct 2014 13:06:46 +0200 Subject: made httpconnection accept aes encrypted files --- .../conversations/entities/DownloadableFile.java | 23 +++++++++++++--------- src/eu/siacs/conversations/entities/Message.java | 5 +++-- .../siacs/conversations/http/HttpConnection.java | 9 +++++++++ src/eu/siacs/conversations/utils/CryptoHelper.java | 9 +++++---- .../xmpp/jingle/JingleConnectionManager.java | 3 ++- 5 files changed, 33 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/DownloadableFile.java b/src/eu/siacs/conversations/entities/DownloadableFile.java index 50b00fb8..1605c75b 100644 --- a/src/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/eu/siacs/conversations/entities/DownloadableFile.java @@ -19,7 +19,6 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import eu.siacs.conversations.Config; -import eu.siacs.conversations.utils.CryptoHelper; import android.util.Log; public class DownloadableFile extends File { @@ -43,7 +42,11 @@ public class DownloadableFile extends File { public long getExpectedSize() { if (this.aeskey != null) { - return (this.expectedSize / 16 + 1) * 16; + if (this.expectedSize == 0) { + return 0; + } else { + return (this.expectedSize / 16 + 1) * 16; + } } else { return this.expectedSize; } @@ -62,7 +65,14 @@ public class DownloadableFile extends File { } public void setKey(byte[] key) { - if (key.length >= 32) { + if (key.length == 48) { + byte[] secretKey = new byte[32]; + byte[] iv = new byte[16]; + System.arraycopy(key, 0, iv, 0, 16); + System.arraycopy(key, 16, secretKey, 0, 32); + this.aeskey = new SecretKeySpec(secretKey, "AES"); + this.iv = iv; + } else if (key.length >= 32) { byte[] secretKey = new byte[32]; System.arraycopy(key, 0, secretKey, 0, 32); this.aeskey = new SecretKeySpec(secretKey, "AES"); @@ -70,12 +80,7 @@ public class DownloadableFile extends File { byte[] secretKey = new byte[16]; System.arraycopy(key, 0, secretKey, 0, 16); this.aeskey = new SecretKeySpec(secretKey, "AES"); - } else { - Log.d(Config.LOGTAG, "weird key"); } - Log.d(Config.LOGTAG, - "using aes key " - + CryptoHelper.bytesToHex(this.aeskey.getEncoded())); } public Key getKey() { @@ -123,7 +128,7 @@ public class DownloadableFile extends File { } } else { try { - IvParameterSpec ips = new IvParameterSpec(iv); + IvParameterSpec ips = new IvParameterSpec(this.iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, this.getKey(), ips); Log.d(Config.LOGTAG, "opening encrypted output stream"); diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index dab28539..a390c7ca 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -403,8 +403,9 @@ public class Message extends AbstractEntity { extensionParts[extensionParts.length - 1])) { return true; } else if (extensionParts.length == 3 - && Arrays.asList(Downloadable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts.length - 1) + && Arrays + .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) + .contains(extensionParts[extensionParts.length - 1]) && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains( extensionParts[extensionParts.length - 2])) { return true; diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 467b6a80..407a13d9 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -27,6 +27,7 @@ import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.utils.CryptoHelper; public class HttpConnection implements Downloadable { @@ -64,6 +65,14 @@ public class HttpConnection implements Downloadable { mUrl = new URL(message.getBody()); this.file = mXmppConnectionService.getFileBackend().getFile( message, false); + String reference = mUrl.getRef(); + if (reference != null && reference.length() == 96) { + this.file.setKey(CryptoHelper.hexToBytes(reference)); + } + if (this.message.getEncryption() == Message.ENCRYPTION_OTR + && this.file.getKey() == null) { + this.message.setEncryption(Message.ENCRYPTION_NONE); + } checkFileSize(false); } catch (MalformedURLException e) { this.cancel(); diff --git a/src/eu/siacs/conversations/utils/CryptoHelper.java b/src/eu/siacs/conversations/utils/CryptoHelper.java index a28b519e..47595c6e 100644 --- a/src/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/eu/siacs/conversations/utils/CryptoHelper.java @@ -5,7 +5,6 @@ import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import java.util.Arrays; import eu.siacs.conversations.entities.Account; import android.util.Base64; @@ -28,9 +27,11 @@ public class CryptoHelper { } public static byte[] hexToBytes(String hexString) { - byte[] array = new BigInteger(hexString, 16).toByteArray(); - if (array[0] == 0) { - array = Arrays.copyOfRange(array, 1, array.length); + int len = hexString.length(); + byte[] array = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + array[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character + .digit(hexString.charAt(i + 1), 16)); } return array; } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index c8209bd9..1e7c84d4 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -136,7 +136,8 @@ public class JingleConnectionManager extends AbstractConnectionManager { } if (sid != null) { for (JingleConnection connection : connections) { - if (connection.getAccount() == account && connection.hasTransportId(sid)) { + if (connection.getAccount() == account + && connection.hasTransportId(sid)) { JingleTransport transport = connection.getTransport(); if (transport instanceof JingleInbandTransport) { JingleInbandTransport inbandTransport = (JingleInbandTransport) transport; -- cgit v1.2.3 From c067bf96b032e1bef3b021df246dadccbb1b5fd7 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 22 Oct 2014 17:32:59 +0200 Subject: small bug fixes for the conversation activity --- src/eu/siacs/conversations/ui/ConversationActivity.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 24ef9a6f..91e1c81f 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -605,8 +605,11 @@ public class ConversationActivity extends XmppActivity implements .beginTransaction(); transaction.replace(R.id.selected_conversation, selectedFragment, "conversation"); - - transaction.commitAllowingStateLoss(); + try { + transaction.commitAllowingStateLoss(); + } catch (IllegalStateException e) { + return selectedFragment; + } } return selectedFragment; } @@ -786,6 +789,10 @@ public class ConversationActivity extends XmppActivity implements attachAudioToConversation(getSelectedConversation(), data.getData()); } + } else { + if (requestCode == REQUEST_IMAGE_CAPTURE) { + pendingImageUri = null; + } } } -- cgit v1.2.3 From d04afe453a277dfe7d7018c55068d2b4fed6c387 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 22 Oct 2014 19:05:15 +0200 Subject: ability to download pgp encrypted files over http as well --- src/eu/siacs/conversations/http/HttpConnection.java | 8 ++++++-- src/eu/siacs/conversations/ui/ConversationFragment.java | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 407a13d9..b8ce5ed2 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -20,9 +20,7 @@ import org.apache.http.conn.ssl.StrictHostnameVerifier; import android.content.Intent; import android.graphics.BitmapFactory; import android.net.Uri; -import android.util.Log; -import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; @@ -63,12 +61,17 @@ public class HttpConnection implements Downloadable { this.message.setDownloadable(this); try { mUrl = new URL(message.getBody()); + String path = mUrl.getPath(); + if (path != null && (path.endsWith(".pgp") || path.endsWith(".gpg"))) { + this.message.setEncryption(Message.ENCRYPTION_PGP); + } this.file = mXmppConnectionService.getFileBackend().getFile( message, false); String reference = mUrl.getRef(); if (reference != null && reference.length() == 96) { this.file.setKey(CryptoHelper.hexToBytes(reference)); } + if (this.message.getEncryption() == Message.ENCRYPTION_OTR && this.file.getKey() == null) { this.message.setEncryption(Message.ENCRYPTION_NONE); @@ -95,6 +98,7 @@ public class HttpConnection implements Downloadable { mXmppConnectionService.sendBroadcast(intent); message.setDownloadable(null); mHttpConnectionManager.finishConnection(this); + mXmppConnectionService.updateConversationUi(); } private void changeStatus(int status) { diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 0e71801b..580fa2d2 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -435,9 +435,9 @@ public class ConversationFragment extends Fragment { }); } for (Message message : this.conversation.getMessages()) { - if ((message.getEncryption() == Message.ENCRYPTION_PGP) - && ((message.getStatus() == Message.STATUS_RECEIVED) || (message - .getStatus() == Message.STATUS_SEND))) { + if (message.getEncryption() == Message.ENCRYPTION_PGP + && (message.getStatus() == Message.STATUS_RECEIVED || message + .getStatus() >= Message.STATUS_SEND) && message.getDownloadable() == null) { if (!mEncryptedMessages.contains(message)) { mEncryptedMessages.add(message); } -- cgit v1.2.3 From d73a77643d7923cae0789c5ed9f6a2a4cf41385f Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 23 Oct 2014 21:27:41 +0200 Subject: context menu for messages. allow to resend single messages --- src/eu/siacs/conversations/entities/Message.java | 11 +++ .../services/XmppConnectionService.java | 17 ++++ .../conversations/ui/ConversationActivity.java | 1 + .../conversations/ui/ConversationFragment.java | 101 ++++++++++++++++++++- .../conversations/ui/EditAccountActivity.java | 13 +-- src/eu/siacs/conversations/ui/XmppActivity.java | 13 +++ .../conversations/ui/adapter/MessageAdapter.java | 28 +++--- 7 files changed, 154 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index a390c7ca..5fa16460 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -431,6 +431,11 @@ public class Message extends AbstractEntity { params.size = Long.parseLong(parts[0]); } catch (NumberFormatException e) { params.origin = parts[0]; + try { + params.url = new URL(parts[0]); + } catch (MalformedURLException e1) { + params.url = null; + } } } else if (parts.length == 3) { try { @@ -450,6 +455,11 @@ public class Message extends AbstractEntity { } } else if (parts.length == 4) { params.origin = parts[0]; + try { + params.url = new URL(parts[0]); + } catch (MalformedURLException e1) { + params.url = null; + } try { params.size = Long.parseLong(parts[1]); } catch (NumberFormatException e) { @@ -470,6 +480,7 @@ public class Message extends AbstractEntity { } public class ImageParams { + public URL url; public long size = 0; public int width = 0; public int height = 0; diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 37e334eb..6d6c672e 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1924,4 +1924,21 @@ public class XmppConnectionService extends Service { } } + + public void resendFailedMessages(Message message) { + List messages = new ArrayList(); + Message current = message; + while(current.getStatus() == Message.STATUS_SEND_FAILED) { + messages.add(current); + if (current.mergable(current.next())) { + current = current.next(); + } else { + break; + } + } + for(Message msg: messages) { + markMessage(msg, Message.STATUS_WAITING); + this.resendMessage(msg); + } + } } diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 91e1c81f..8a647f30 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -191,6 +191,7 @@ public class ConversationActivity extends XmppActivity implements xmppConnectionService.getNotificationService() .setOpenConversation(null); } + closeContextMenu(); } @Override diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 580fa2d2..4c8d27e9 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -11,6 +11,7 @@ import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; @@ -33,9 +34,12 @@ import android.content.IntentSender.SendIntentException; import android.os.Bundle; import android.text.Editable; import android.text.Selection; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -45,6 +49,8 @@ import android.widget.AbsListView.OnScrollListener; import android.widget.TextView.OnEditorActionListener; import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ListView; import android.widget.ImageButton; import android.widget.RelativeLayout; @@ -193,6 +199,7 @@ public class ConversationFragment extends Fragment { }; private ConversationActivity activity; + private Message selectedMessage; private void sendMessage() { if (this.conversation == null) { @@ -326,9 +333,100 @@ public class ConversationFragment extends Fragment { }); messagesView.setAdapter(messageListAdapter); + registerForContextMenu(messagesView); + return view; } + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; + this.selectedMessage = this.messageList.get(acmi.position); + populateContextMenu(menu); + } + + private void populateContextMenu(ContextMenu menu) { + if (this.selectedMessage.getType() != Message.TYPE_STATUS) { + activity.getMenuInflater().inflate(R.menu.message_context, menu); + menu.setHeaderTitle(R.string.message_options); + MenuItem copyText = menu.findItem(R.id.copy_text); + MenuItem shareImage = menu.findItem(R.id.share_image); + MenuItem sendAgain = menu.findItem(R.id.send_again); + MenuItem copyUrl = menu.findItem(R.id.copy_url); + if (this.selectedMessage.getType() != Message.TYPE_TEXT + || this.selectedMessage.getDownloadable() != null) { + copyText.setVisible(false); + } + if (this.selectedMessage.getType() != Message.TYPE_IMAGE + || (this.selectedMessage.getDownloadable() != null && this.selectedMessage + .getDownloadable().getStatus() == Downloadable.STATUS_DELETED)) { + shareImage.setVisible(false); + } + if (this.selectedMessage.getStatus() != Message.STATUS_SEND_FAILED) { + sendAgain.setVisible(false); + } + if ((this.selectedMessage.getType() != Message.TYPE_IMAGE && this.selectedMessage + .getDownloadable() == null) + || this.selectedMessage.getImageParams().url == null) { + copyUrl.setVisible(false); + } + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.share_image: + shareImage(selectedMessage); + return true; + case R.id.copy_text: + copyText(selectedMessage); + return true; + case R.id.send_again: + resendMessage(selectedMessage); + return true; + case R.id.copy_url: + copyUrl(selectedMessage); + return true; + default: + return super.onContextItemSelected(item); + } + } + + private void shareImage(Message message) { + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_STREAM, + activity.xmppConnectionService.getFileBackend() + .getJingleFileUri(message)); + shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + shareIntent.setType("image/webp"); + activity.startActivity(Intent.createChooser(shareIntent, + getText(R.string.share_with))); + } + + private void copyText(Message message) { + if (activity.copyTextToClipboard(message.getMergedBody(), + R.string.message_text)) { + Toast.makeText(activity, R.string.message_copied_to_clipboard, + Toast.LENGTH_SHORT).show(); + } + } + + private void resendMessage(Message message) { + activity.xmppConnectionService.resendFailedMessages(message); + } + + private void copyUrl(Message message) { + if (activity.copyTextToClipboard( + message.getImageParams().url.toString(), R.string.image_url)) { + Toast.makeText(activity, R.string.url_copied_to_clipboard, + Toast.LENGTH_SHORT).show(); + } + } + protected void privateMessageWith(String counterpart) { this.mEditMessage.setText(""); this.conversation.setNextPresence(counterpart); @@ -437,7 +535,8 @@ public class ConversationFragment extends Fragment { for (Message message : this.conversation.getMessages()) { if (message.getEncryption() == Message.ENCRYPTION_PGP && (message.getStatus() == Message.STATUS_RECEIVED || message - .getStatus() >= Message.STATUS_SEND) && message.getDownloadable() == null) { + .getStatus() >= Message.STATUS_SEND) + && message.getDownloadable() == null) { if (!mEncryptedMessages.contains(message)) { mEncryptedMessages.add(message); } diff --git a/src/eu/siacs/conversations/ui/EditAccountActivity.java b/src/eu/siacs/conversations/ui/EditAccountActivity.java index 1543d740..89c06592 100644 --- a/src/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/eu/siacs/conversations/ui/EditAccountActivity.java @@ -389,7 +389,7 @@ public class EditAccountActivity extends XmppActivity { @Override public void onClick(View v) { - if (OtrFingerprintToClipBoard(fingerprint)) { + if (copyTextToClipboard(fingerprint,R.string.otr_fingerprint)) { Toast.makeText( EditAccountActivity.this, R.string.toast_message_otr_fingerprint, @@ -409,15 +409,4 @@ public class EditAccountActivity extends XmppActivity { this.mStats.setVisibility(View.GONE); } } - - private boolean OtrFingerprintToClipBoard(String fingerprint) { - ClipboardManager mClipBoardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - String label = getResources().getString(R.string.otr_fingerprint); - if (mClipBoardManager != null) { - ClipData mClipData = ClipData.newPlainText(label, fingerprint); - mClipBoardManager.setPrimaryClip(mClipData); - return true; - } - return false; - } } diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index d26f0e31..c04a4c0b 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -21,6 +21,8 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.PendingIntent; import android.app.AlertDialog.Builder; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -531,6 +533,17 @@ public abstract class XmppActivity extends Activity { DisplayMetrics metrics = getResources().getDisplayMetrics(); return ((int) (dp * metrics.density)); } + + public boolean copyTextToClipboard(String text,int labelResId) { + ClipboardManager mClipBoardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); + String label = getResources().getString(labelResId); + if (mClipBoardManager != null) { + ClipData mClipData = ClipData.newPlainText(label, text); + mClipBoardManager.setPrimaryClip(mClipData); + return true; + } + return false; + } public AvatarService avatarService() { return xmppConnectionService.getAvatarService(); diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index a9a55cbf..4e04e315 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -43,6 +43,15 @@ public class MessageAdapter extends ArrayAdapter { private OnContactPictureClicked mOnContactPictureClickedListener; private OnContactPictureLongClicked mOnContactPictureLongClickedListener; + private OnLongClickListener openContextMenu = new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + v.showContextMenu(); + return true; + } + }; + public MessageAdapter(ConversationActivity activity, List messages) { super(activity, 0, messages); this.activity = activity; @@ -259,6 +268,7 @@ public class MessageAdapter extends ArrayAdapter { startDonwloadable(message); } }); + viewHolder.download_button.setOnLongClickListener(openContextMenu); } private void displayImageMessage(ViewHolder viewHolder, @@ -292,23 +302,7 @@ public class MessageAdapter extends ArrayAdapter { getContext().startActivity(intent); } }); - viewHolder.image.setOnLongClickListener(new OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.putExtra(Intent.EXTRA_STREAM, - activity.xmppConnectionService.getFileBackend() - .getJingleFileUri(message)); - shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - shareIntent.setType("image/webp"); - getContext().startActivity( - Intent.createChooser(shareIntent, - getContext().getText(R.string.share_with))); - return true; - } - }); + viewHolder.image.setOnLongClickListener(openContextMenu); } @Override -- cgit v1.2.3 From cbc3d9bd6f275984b390eb4dae48f8eed669fe7a Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 24 Oct 2014 13:29:18 +0200 Subject: notify only after image has been received over http. introduced mini grace for catching up with SM or offline messages --- src/eu/siacs/conversations/Config.java | 1 + src/eu/siacs/conversations/entities/Message.java | 15 ------ .../siacs/conversations/http/HttpConnection.java | 9 ++++ .../siacs/conversations/parser/MessageParser.java | 1 + .../services/NotificationService.java | 59 +++++++++++++++++----- .../ui/adapter/ConversationAdapter.java | 12 +++-- 6 files changed, 64 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/Config.java b/src/eu/siacs/conversations/Config.java index 1725eca6..7dd5a799 100644 --- a/src/eu/siacs/conversations/Config.java +++ b/src/eu/siacs/conversations/Config.java @@ -11,6 +11,7 @@ public final class Config { public static final int PING_TIMEOUT = 10; public static final int CONNECT_TIMEOUT = 90; public static final int CARBON_GRACE_PERIOD = 60; + public static final int MINI_GRACE_PERIOD = 750; public static final int AVATAR_SIZE = 192; public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.WEBP; diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index 5fa16460..68a71d4a 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -5,9 +5,7 @@ import java.net.URL; import java.util.Arrays; import eu.siacs.conversations.Config; -import eu.siacs.conversations.R; import android.content.ContentValues; -import android.content.Context; import android.database.Cursor; public class Message extends AbstractEntity { @@ -145,19 +143,6 @@ public class Message extends AbstractEntity { return body; } - public String getReadableBody(Context context) { - if (encryption == ENCRYPTION_PGP) { - return context.getText(R.string.encrypted_message_received) - .toString(); - } else if (encryption == ENCRYPTION_DECRYPTION_FAILED) { - return context.getText(R.string.decryption_failed).toString(); - } else if (type == TYPE_IMAGE) { - return context.getText(R.string.image_file).toString(); - } else { - return body.trim(); - } - } - public long getTimeSent() { return timeSent; } diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index b8ce5ed2..9b04decc 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -36,6 +36,7 @@ public class HttpConnection implements Downloadable { private Message message; private DownloadableFile file; private int mStatus = Downloadable.STATUS_UNKNOWN; + private boolean acceptedAutomatically = false; public HttpConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; @@ -99,6 +100,9 @@ public class HttpConnection implements Downloadable { message.setDownloadable(null); mHttpConnectionManager.finishConnection(this); mXmppConnectionService.updateConversationUi(); + if (acceptedAutomatically) { + mXmppConnectionService.getNotificationService().push(message); + } } private void changeStatus(int status) { @@ -151,6 +155,8 @@ public class HttpConnection implements Downloadable { size = retrieveFileSize(); } catch (SSLHandshakeException e) { changeStatus(STATUS_OFFER_CHECK_FILESIZE); + HttpConnection.this.acceptedAutomatically = false; + HttpConnection.this.mXmppConnectionService.getNotificationService().push(message); return; } catch (IOException e) { cancel(); @@ -158,9 +164,12 @@ public class HttpConnection implements Downloadable { } file.setExpectedSize(size); if (size <= mHttpConnectionManager.getAutoAcceptFileSize()) { + HttpConnection.this.acceptedAutomatically = true; new Thread(new FileDownloader(interactive)).start(); } else { changeStatus(STATUS_OFFER); + HttpConnection.this.acceptedAutomatically = false; + HttpConnection.this.mXmppConnectionService.getNotificationService().push(message); } } diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index b5e14305..26841f43 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -487,6 +487,7 @@ public class MessageParser extends AbstractParser implements if (message.bodyContainsDownloadable()) { this.mXmppConnectionService.getHttpConnectionManager() .createNewConnection(message); + notify = false; } notify = notify && !conversation.isMuted(); if (notify) { diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 00765deb..2dff736b 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -13,14 +13,17 @@ import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.PowerManager; +import android.os.SystemClock; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.text.Html; import android.util.DisplayMetrics; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; @@ -30,9 +33,10 @@ public class NotificationService { private LinkedHashMap> notifications = new LinkedHashMap>(); - public int NOTIFICATION_ID = 0x2342; + public static int NOTIFICATION_ID = 0x2342; private Conversation mOpenConversation; private boolean mIsInForeground; + private long mLastNotification; public NotificationService(XmppConnectionService service) { this.mXmppConnectionService = service; @@ -58,7 +62,8 @@ public class NotificationService { } Account account = message.getConversation().getAccount(); updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) - && !account.inGracePeriod()); + && !account.inGracePeriod() + && !this.inMiniGracePeriod(account)); } } @@ -89,6 +94,9 @@ public class NotificationService { if (notifications.size() == 0) { notificationManager.cancel(NOTIFICATION_ID); } else { + if (notify) { + this.markLastNotification(); + } NotificationCompat.Builder mBuilder = new NotificationCompat.Builder( mXmppConnectionService); mBuilder.setSmallIcon(R.drawable.ic_notification); @@ -103,19 +111,17 @@ public class NotificationService { mBuilder.setContentTitle(conversation.getName()); StringBuilder text = new StringBuilder(); for (int i = 0; i < messages.size(); ++i) { - text.append(messages.get(i).getReadableBody( - mXmppConnectionService)); + text.append(getReadableBody(messages.get(i))); if (i != messages.size() - 1) { text.append("\n"); } } mBuilder.setStyle(new NotificationCompat.BigTextStyle() .bigText(text.toString())); - mBuilder.setContentText(messages.get(0).getReadableBody( - mXmppConnectionService)); + mBuilder.setContentText(getReadableBody(messages.get(0))); if (notify) { - mBuilder.setTicker(messages.get(messages.size() - 1) - .getReadableBody(mXmppConnectionService)); + mBuilder.setTicker(getReadableBody(messages + .get(messages.size() - 1))); } mBuilder.setContentIntent(createContentIntent(conversation .getUuid())); @@ -135,11 +141,8 @@ public class NotificationService { if (messages.size() > 0) { conversation = messages.get(0).getConversation(); String name = conversation.getName(); - style.addLine(Html.fromHtml("" - + name - + " " - + messages.get(0).getReadableBody( - mXmppConnectionService))); + style.addLine(Html.fromHtml("" + name + " " + + getReadableBody(messages.get(0)))); names.append(name); names.append(", "); } @@ -175,6 +178,26 @@ public class NotificationService { } } + private String getReadableBody(Message message) { + if (message.getDownloadable() != null + && (message.getDownloadable().getStatus() == Downloadable.STATUS_OFFER || message + .getDownloadable().getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE)) { + return mXmppConnectionService.getText( + R.string.image_offered_for_download).toString(); + } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { + return mXmppConnectionService.getText( + R.string.encrypted_message_received).toString(); + } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { + return mXmppConnectionService.getText(R.string.decryption_failed) + .toString(); + } else if (message.getType() == Message.TYPE_IMAGE) { + return mXmppConnectionService.getText(R.string.image_file) + .toString(); + } else { + return message.getBody().trim(); + } + } + private PendingIntent createContentIntent(String conversationUuid) { TaskStackBuilder stackBuilder = TaskStackBuilder .create(mXmppConnectionService); @@ -234,4 +257,14 @@ public class NotificationService { .getDisplayMetrics(); return ((int) (dp * metrics.density)); } + + private void markLastNotification() { + this.mLastNotification = SystemClock.elapsedRealtime(); + } + + private boolean inMiniGracePeriod(Account account) { + int miniGrace = account.getStatus() == Account.STATUS_ONLINE ? Config.MINI_GRACE_PERIOD + : Config.MINI_GRACE_PERIOD * 2; + return SystemClock.elapsedRealtime() < (this.mLastNotification + miniGrace); + } } diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 183c89fa..0c294e7e 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -78,14 +78,14 @@ public class ConversationAdapter extends ArrayAdapter { if (message.getType() == Message.TYPE_IMAGE || message.getDownloadable() != null) { Downloadable d = message.getDownloadable(); + if (conversation.isRead()) { + mLastMessage.setTypeface(null, Typeface.ITALIC); + } else { + mLastMessage.setTypeface(null, Typeface.BOLD_ITALIC); + } if (d != null) { mLastMessage.setVisibility(View.VISIBLE); imagePreview.setVisibility(View.GONE); - if (conversation.isRead()) { - mLastMessage.setTypeface(null, Typeface.ITALIC); - } else { - mLastMessage.setTypeface(null, Typeface.BOLD_ITALIC); - } if (d.getStatus() == Downloadable.STATUS_CHECKING) { mLastMessage.setText(R.string.checking_image); } else if (d.getStatus() == Downloadable.STATUS_DOWNLOADING) { @@ -99,6 +99,8 @@ public class ConversationAdapter extends ArrayAdapter { } else { mLastMessage.setText(""); } + } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { + mLastMessage.setText(R.string.encrypted_message_received); } else { mLastMessage.setVisibility(View.GONE); imagePreview.setVisibility(View.VISIBLE); -- cgit v1.2.3 From 864f3610b30d684a19fe86eff22835a5ba2e92c4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 24 Oct 2014 14:34:46 +0200 Subject: picture notification and some drive by bug fixes --- .../services/NotificationService.java | 38 +++++++++++++++------- .../conversations/ui/ConversationActivity.java | 32 +++++++----------- src/eu/siacs/conversations/ui/XmppActivity.java | 1 - .../ui/adapter/ConversationAdapter.java | 2 ++ 4 files changed, 40 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 2dff736b..50e3dec0 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.services; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.regex.Matcher; @@ -11,6 +12,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.graphics.Bitmap; import android.net.Uri; import android.os.PowerManager; import android.os.SystemClock; @@ -109,19 +111,31 @@ public class NotificationService { mBuilder.setLargeIcon(mXmppConnectionService .getAvatarService().get(conversation, getPixel(64))); mBuilder.setContentTitle(conversation.getName()); - StringBuilder text = new StringBuilder(); - for (int i = 0; i < messages.size(); ++i) { - text.append(getReadableBody(messages.get(i))); - if (i != messages.size() - 1) { - text.append("\n"); + if (messages.size() == 1 && messages.get(0).getType() == Message.TYPE_IMAGE) { + try { + Bitmap bitmap = mXmppConnectionService.getFileBackend().getThumbnail(messages.get(0),getPixel(288),false); + mBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap)); + mBuilder.setContentText(mXmppConnectionService.getString(R.string.image_file)); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } else { + StringBuilder text = new StringBuilder(); + for (int i = 0; i < messages.size(); ++i) { + text.append(getReadableBody(messages.get(i))); + if (i != messages.size() - 1) { + text.append("\n"); + } + } + mBuilder.setStyle(new NotificationCompat.BigTextStyle() + .bigText(text.toString())); + mBuilder.setContentText(getReadableBody(messages.get(0))); + if (notify) { + mBuilder.setTicker(getReadableBody(messages + .get(messages.size() - 1))); } - } - mBuilder.setStyle(new NotificationCompat.BigTextStyle() - .bigText(text.toString())); - mBuilder.setContentText(getReadableBody(messages.get(0))); - if (notify) { - mBuilder.setTicker(getReadableBody(messages - .get(messages.size() - 1))); } mBuilder.setContentIntent(createContentIntent(conversation .getUuid())); diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 8a647f30..28325eea 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -629,23 +629,11 @@ public class ConversationActivity extends XmppActivity implements @Override protected void onNewIntent(Intent intent) { if (xmppConnectionServiceBound) { - if ((Intent.ACTION_VIEW.equals(intent.getAction()) && (VIEW_CONVERSATION - .equals(intent.getType())))) { - String convToView = (String) intent.getExtras().get( - CONVERSATION); - updateConversationList(); - for (int i = 0; i < conversationList.size(); ++i) { - if (conversationList.get(i).getUuid().equals(convToView)) { - setSelectedConversation(conversationList.get(i)); - break; - } - } - paneShouldBeOpen = false; - String text = intent.getExtras().getString(TEXT, null); - swapConversationFragment().setText(text); + if (intent != null + && VIEW_CONVERSATION.equals(getIntent().getType())) { + handleViewConversationIntent(intent); } } else { - handledViewIntent = false; setIntent(intent); } } @@ -705,11 +693,7 @@ public class ConversationActivity extends XmppActivity implements mOpenConverstaion = null; } else if (getIntent() != null && VIEW_CONVERSATION.equals(getIntent().getType())) { - String uuid = (String) getIntent().getExtras().get(CONVERSATION); - String text = getIntent().getExtras().getString(TEXT, null); - selectConversationByUuid(uuid); - paneShouldBeOpen = false; - swapConversationFragment().setText(text); + handleViewConversationIntent(getIntent()); setIntent(null); } else { showConversationsOverview(); @@ -731,6 +715,14 @@ public class ConversationActivity extends XmppActivity implements } ExceptionHelper.checkForCrash(this, this.xmppConnectionService); } + + private void handleViewConversationIntent(Intent intent) { + String uuid = (String) intent.getExtras().get(CONVERSATION); + String text = intent.getExtras().getString(TEXT, null); + selectConversationByUuid(uuid); + paneShouldBeOpen = false; + swapConversationFragment().setText(text); + } private void selectConversationByUuid(String uuid) { for (int i = 0; i < conversationList.size(); ++i) { diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index c04a4c0b..02157e74 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -58,7 +58,6 @@ public abstract class XmppActivity extends Activity { public XmppConnectionService xmppConnectionService; public boolean xmppConnectionServiceBound = false; - protected boolean handledViewIntent = false; protected int mPrimaryTextColor; protected int mSecondaryTextColor; diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 0c294e7e..b2e5dd07 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -100,6 +100,8 @@ public class ConversationAdapter extends ArrayAdapter { mLastMessage.setText(""); } } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { + imagePreview.setVisibility(View.GONE); + mLastMessage.setVisibility(View.VISIBLE); mLastMessage.setText(R.string.encrypted_message_received); } else { mLastMessage.setVisibility(View.GONE); -- cgit v1.2.3 From e1f11a5735cf826ca3cb4ada062e2b90c1a18381 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 24 Oct 2014 18:27:53 +0200 Subject: also show some text in new image notification --- .../services/NotificationService.java | 195 +++++++++++++-------- 1 file changed, 122 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java index 50e3dec0..7b2e16df 100644 --- a/src/eu/siacs/conversations/services/NotificationService.java +++ b/src/eu/siacs/conversations/services/NotificationService.java @@ -17,6 +17,8 @@ import android.net.Uri; import android.os.PowerManager; import android.os.SystemClock; import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationCompat.BigPictureStyle; +import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.app.TaskStackBuilder; import android.text.Html; import android.util.DisplayMetrics; @@ -99,81 +101,11 @@ public class NotificationService { if (notify) { this.markLastNotification(); } - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder( - mXmppConnectionService); - mBuilder.setSmallIcon(R.drawable.ic_notification); + Builder mBuilder; if (notifications.size() == 1) { - ArrayList messages = notifications.values().iterator() - .next(); - if (messages.size() >= 1) { - Conversation conversation = messages.get(0) - .getConversation(); - mBuilder.setLargeIcon(mXmppConnectionService - .getAvatarService().get(conversation, getPixel(64))); - mBuilder.setContentTitle(conversation.getName()); - if (messages.size() == 1 && messages.get(0).getType() == Message.TYPE_IMAGE) { - try { - Bitmap bitmap = mXmppConnectionService.getFileBackend().getThumbnail(messages.get(0),getPixel(288),false); - mBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap)); - mBuilder.setContentText(mXmppConnectionService.getString(R.string.image_file)); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } else { - StringBuilder text = new StringBuilder(); - for (int i = 0; i < messages.size(); ++i) { - text.append(getReadableBody(messages.get(i))); - if (i != messages.size() - 1) { - text.append("\n"); - } - } - mBuilder.setStyle(new NotificationCompat.BigTextStyle() - .bigText(text.toString())); - mBuilder.setContentText(getReadableBody(messages.get(0))); - if (notify) { - mBuilder.setTicker(getReadableBody(messages - .get(messages.size() - 1))); - } - } - mBuilder.setContentIntent(createContentIntent(conversation - .getUuid())); - } else { - notificationManager.cancel(NOTIFICATION_ID); - return; - } + mBuilder = buildSingleConversations(notify); } else { - NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle(); - style.setBigContentTitle(notifications.size() - + " " - + mXmppConnectionService - .getString(R.string.unread_conversations)); - StringBuilder names = new StringBuilder(); - Conversation conversation = null; - for (ArrayList messages : notifications.values()) { - if (messages.size() > 0) { - conversation = messages.get(0).getConversation(); - String name = conversation.getName(); - style.addLine(Html.fromHtml("" + name + " " - + getReadableBody(messages.get(0)))); - names.append(name); - names.append(", "); - } - } - if (names.length() >= 2) { - names.delete(names.length() - 2, names.length()); - } - mBuilder.setContentTitle(notifications.size() - + " " - + mXmppConnectionService - .getString(R.string.unread_conversations)); - mBuilder.setContentText(names.toString()); - mBuilder.setStyle(style); - if (conversation != null) { - mBuilder.setContentIntent(createContentIntent(conversation - .getUuid())); - } + mBuilder = buildMultipleConversation(); } if (notify) { if (vibrate) { @@ -185,6 +117,7 @@ public class NotificationService { mBuilder.setSound(Uri.parse(ringtone)); } } + mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); mBuilder.setLights(0xffffffff, 2000, 4000); Notification notification = mBuilder.build(); @@ -192,6 +125,122 @@ public class NotificationService { } } + private Builder buildMultipleConversation() { + Builder mBuilder = new NotificationCompat.Builder( + mXmppConnectionService); + NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle(); + style.setBigContentTitle(notifications.size() + + " " + + mXmppConnectionService + .getString(R.string.unread_conversations)); + StringBuilder names = new StringBuilder(); + Conversation conversation = null; + for (ArrayList messages : notifications.values()) { + if (messages.size() > 0) { + conversation = messages.get(0).getConversation(); + String name = conversation.getName(); + style.addLine(Html.fromHtml("" + name + " " + + getReadableBody(messages.get(0)))); + names.append(name); + names.append(", "); + } + } + if (names.length() >= 2) { + names.delete(names.length() - 2, names.length()); + } + mBuilder.setContentTitle(notifications.size() + + " " + + mXmppConnectionService + .getString(R.string.unread_conversations)); + mBuilder.setContentText(names.toString()); + mBuilder.setStyle(style); + if (conversation != null) { + mBuilder.setContentIntent(createContentIntent(conversation + .getUuid())); + } + return mBuilder; + } + + private Builder buildSingleConversations(boolean notify) { + Builder mBuilder = new NotificationCompat.Builder( + mXmppConnectionService); + ArrayList messages = notifications.values().iterator().next(); + if (messages.size() >= 1) { + Conversation conversation = messages.get(0).getConversation(); + mBuilder.setLargeIcon(mXmppConnectionService.getAvatarService() + .get(conversation, getPixel(64))); + mBuilder.setContentTitle(conversation.getName()); + Message message; + if ((message = getImage(messages)) != null) { + modifyForImage(mBuilder, message, messages, notify); + } else { + modifyForTextOnly(mBuilder, messages, notify); + } + mBuilder.setContentIntent(createContentIntent(conversation + .getUuid())); + } + return mBuilder; + + } + + private void modifyForImage(Builder builder, Message message, + ArrayList messages, boolean notify) { + try { + Bitmap bitmap = mXmppConnectionService.getFileBackend() + .getThumbnail(message, getPixel(288), false); + ArrayList tmp = new ArrayList(); + for (Message msg : messages) { + if (msg.getType() == Message.TYPE_TEXT + && msg.getDownloadable() == null) { + tmp.add(msg); + } + } + BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); + bigPictureStyle.bigPicture(bitmap); + if (tmp.size() > 0) { + bigPictureStyle.setSummaryText(getMergedBodies(tmp)); + builder.setContentText(getReadableBody(tmp.get(0))); + } else { + builder.setContentText(mXmppConnectionService.getString(R.string.image_file)); + } + builder.setStyle(bigPictureStyle); + } catch (FileNotFoundException e) { + modifyForTextOnly(builder, messages, notify); + } + } + + private void modifyForTextOnly(Builder builder, + ArrayList messages, boolean notify) { + builder.setStyle(new NotificationCompat.BigTextStyle() + .bigText(getMergedBodies(messages))); + builder.setContentText(getReadableBody(messages.get(0))); + if (notify) { + builder.setTicker(getReadableBody(messages.get(messages.size() - 1))); + } + } + + private Message getImage(ArrayList messages) { + for (Message message : messages) { + if (message.getType() == Message.TYPE_IMAGE + && message.getDownloadable() == null + && message.getEncryption() != Message.ENCRYPTION_PGP) { + return message; + } + } + return null; + } + + private String getMergedBodies(ArrayList messages) { + StringBuilder text = new StringBuilder(); + for (int i = 0; i < messages.size(); ++i) { + text.append(getReadableBody(messages.get(i))); + if (i != messages.size() - 1) { + text.append("\n"); + } + } + return text.toString(); + } + private String getReadableBody(Message message) { if (message.getDownloadable() != null && (message.getDownloadable().getStatus() == Downloadable.STATUS_OFFER || message -- cgit v1.2.3 From 8fb898541286d737491ac156e8b327b534d4e2a3 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 24 Oct 2014 19:30:03 +0200 Subject: added message option to download images --- src/eu/siacs/conversations/ui/ConversationFragment.java | 14 ++++++++++++++ src/eu/siacs/conversations/ui/EditAccountActivity.java | 2 -- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 4c8d27e9..147a7a5f 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -355,6 +355,7 @@ public class ConversationFragment extends Fragment { MenuItem shareImage = menu.findItem(R.id.share_image); MenuItem sendAgain = menu.findItem(R.id.send_again); MenuItem copyUrl = menu.findItem(R.id.copy_url); + MenuItem downloadImage = menu.findItem(R.id.download_image); if (this.selectedMessage.getType() != Message.TYPE_TEXT || this.selectedMessage.getDownloadable() != null) { copyText.setVisible(false); @@ -372,6 +373,12 @@ public class ConversationFragment extends Fragment { || this.selectedMessage.getImageParams().url == null) { copyUrl.setVisible(false); } + + if (this.selectedMessage.getType() != Message.TYPE_TEXT + || this.selectedMessage.getDownloadable() != null + || !this.selectedMessage.bodyContainsDownloadable()) { + downloadImage.setVisible(false); + } } } @@ -390,6 +397,8 @@ public class ConversationFragment extends Fragment { case R.id.copy_url: copyUrl(selectedMessage); return true; + case R.id.download_image: + downloadImage(selectedMessage); default: return super.onContextItemSelected(item); } @@ -427,6 +436,11 @@ public class ConversationFragment extends Fragment { } } + private void downloadImage(Message message) { + activity.xmppConnectionService.getHttpConnectionManager() + .createNewConnection(message); + } + protected void privateMessageWith(String counterpart) { this.mEditMessage.setText(""); this.conversation.setNextPresence(counterpart); diff --git a/src/eu/siacs/conversations/ui/EditAccountActivity.java b/src/eu/siacs/conversations/ui/EditAccountActivity.java index 89c06592..58ca49cc 100644 --- a/src/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/eu/siacs/conversations/ui/EditAccountActivity.java @@ -1,8 +1,6 @@ package eu.siacs.conversations.ui; import android.app.PendingIntent; -import android.content.ClipData; -import android.content.ClipboardManager; import android.content.Intent; import android.os.Bundle; import android.text.Editable; -- cgit v1.2.3 From 8171633eb9f43e43f39fd1687467d85cdb132b0c Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 24 Oct 2014 23:18:19 +0200 Subject: don't merge downloadable messages --- src/eu/siacs/conversations/entities/Message.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index 68a71d4a..212eb049 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -327,7 +327,9 @@ public class Message extends AbstractEntity { .getStatus() == Message.STATUS_SEND_RECEIVED) && (message .getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_SEND || message - .getStatus() == Message.STATUS_SEND_DISPLAYED))))); + .getStatus() == Message.STATUS_SEND_DISPLAYED)))) + && !message.bodyContainsDownloadable() + && !this.bodyContainsDownloadable()); } public String getMergedBody() { -- cgit v1.2.3 From 8dae4b1eb922f4b79dbf1e1158b16afb51210a53 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 26 Oct 2014 18:30:58 +0100 Subject: fix possible fallthrough. --- src/eu/siacs/conversations/ui/ConversationFragment.java | 1 + src/eu/siacs/conversations/ui/ManageAccountActivity.java | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 147a7a5f..fe3f79cb 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -399,6 +399,7 @@ public class ConversationFragment extends Fragment { return true; case R.id.download_image: downloadImage(selectedMessage); + return true; default: return super.onContextItemSelected(item); } diff --git a/src/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/eu/siacs/conversations/ui/ManageAccountActivity.java index 5b5b0608..77f8b68a 100644 --- a/src/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -123,6 +123,7 @@ public class ManageAccountActivity extends XmppActivity { return true; case R.id.mgmt_account_announce_pgp: publishOpenPGPPublicKey(selectedAccount); + return true; default: return super.onContextItemSelected(item); } -- cgit v1.2.3 From 020dc863b17a1c9f9c6cb9ff5798d8fcc79a406e Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 26 Oct 2014 18:54:10 +0100 Subject: remove some unused cast --- .../conversations/ui/ChooseContactActivity.java | 2 +- .../ui/ConferenceDetailsActivity.java | 2 +- .../conversations/ui/ContactDetailsActivity.java | 6 ++---- .../conversations/ui/ConversationActivity.java | 22 +++++++++------------- .../ui/StartConversationActivity.java | 6 +++--- src/eu/siacs/conversations/ui/XmppActivity.java | 5 ++--- .../conversations/ui/adapter/AccountAdapter.java | 2 +- .../ui/adapter/ConversationAdapter.java | 2 +- .../conversations/ui/adapter/ListItemAdapter.java | 2 +- .../conversations/ui/adapter/MessageAdapter.java | 8 ++++---- 10 files changed, 25 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/eu/siacs/conversations/ui/ChooseContactActivity.java index 62a2cbe1..f14da352 100644 --- a/src/eu/siacs/conversations/ui/ChooseContactActivity.java +++ b/src/eu/siacs/conversations/ui/ChooseContactActivity.java @@ -113,7 +113,7 @@ public class ChooseContactActivity extends XmppActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.choose_contact, menu); - MenuItem menuSearchView = (MenuItem) menu.findItem(R.id.action_search); + MenuItem menuSearchView = menu.findItem(R.id.action_search); View mSearchView = menuSearchView.getActionView(); mSearchEditText = (EditText) mSearchView .findViewById(R.id.search_field); diff --git a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 6b4642cb..52687c81 100644 --- a/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -227,7 +227,7 @@ public class ConferenceDetailsActivity extends XmppActivity { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); membersView.removeAllViews(); for (final User user : conversation.getMucOptions().getUsers()) { - View view = (View) inflater.inflate(R.layout.contact, membersView, + View view = inflater.inflate(R.layout.contact, membersView, false); TextView name = (TextView) view .findViewById(R.id.contact_display_name); diff --git a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java index ae26466e..4c52c609 100644 --- a/src/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -325,8 +325,7 @@ public class ContactDetailsActivity extends XmppActivity { .iterator(); iterator.hasNext();) { hasKeys = true; final String otrFingerprint = iterator.next(); - View view = (View) inflater.inflate(R.layout.contact_key, keys, - false); + View view = inflater.inflate(R.layout.contact_key, keys, false); TextView key = (TextView) view.findViewById(R.id.key); TextView keyType = (TextView) view.findViewById(R.id.key_type); ImageButton remove = (ImageButton) view @@ -345,8 +344,7 @@ public class ContactDetailsActivity extends XmppActivity { } if (contact.getPgpKeyId() != 0) { hasKeys = true; - View view = (View) inflater.inflate(R.layout.contact_key, keys, - false); + View view = inflater.inflate(R.layout.contact_key, keys, false); TextView key = (TextView) view.findViewById(R.id.key); TextView keyType = (TextView) view.findViewById(R.id.key_type); keyType.setText("PGP Key ID"); diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 28325eea..8a10a782 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -241,19 +241,15 @@ public class ConversationActivity extends XmppActivity implements @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.conversations, menu); - MenuItem menuSecure = (MenuItem) menu.findItem(R.id.action_security); - MenuItem menuArchive = (MenuItem) menu.findItem(R.id.action_archive); - MenuItem menuMucDetails = (MenuItem) menu - .findItem(R.id.action_muc_details); - MenuItem menuContactDetails = (MenuItem) menu - .findItem(R.id.action_contact_details); - MenuItem menuAttach = (MenuItem) menu.findItem(R.id.action_attach_file); - MenuItem menuClearHistory = (MenuItem) menu - .findItem(R.id.action_clear_history); - MenuItem menuAdd = (MenuItem) menu.findItem(R.id.action_add); - MenuItem menuInviteContact = (MenuItem) menu - .findItem(R.id.action_invite); - MenuItem menuMute = (MenuItem) menu.findItem(R.id.action_mute); + MenuItem menuSecure = menu.findItem(R.id.action_security); + MenuItem menuArchive = menu.findItem(R.id.action_archive); + MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details); + MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details); + MenuItem menuAttach = menu.findItem(R.id.action_attach_file); + MenuItem menuClearHistory = menu.findItem(R.id.action_clear_history); + MenuItem menuAdd = menu.findItem(R.id.action_add); + MenuItem menuInviteContact = menu.findItem(R.id.action_invite); + MenuItem menuMute = menu.findItem(R.id.action_mute); if (isConversationsOverviewVisable() && isConversationsOverviewHideable()) { diff --git a/src/eu/siacs/conversations/ui/StartConversationActivity.java b/src/eu/siacs/conversations/ui/StartConversationActivity.java index a1a2d4c2..416e926a 100644 --- a/src/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/eu/siacs/conversations/ui/StartConversationActivity.java @@ -463,11 +463,11 @@ public class StartConversationActivity extends XmppActivity { public boolean onCreateOptionsMenu(Menu menu) { this.mOptionsMenu = menu; getMenuInflater().inflate(R.menu.start_conversation, menu); - MenuItem menuCreateContact = (MenuItem) menu + MenuItem menuCreateContact = menu .findItem(R.id.action_create_contact); - MenuItem menuCreateConference = (MenuItem) menu + MenuItem menuCreateConference = menu .findItem(R.id.action_join_conference); - mMenuSearchView = (MenuItem) menu.findItem(R.id.action_search); + mMenuSearchView = menu.findItem(R.id.action_search); mMenuSearchView.setOnActionExpandListener(mOnActionExpandListener); View mSearchView = mMenuSearchView.getActionView(); mSearchEditText = (EditText) mSearchView diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index 02157e74..222f3295 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -402,8 +402,7 @@ public abstract class XmppActivity extends Activity { private void quickEdit(final String previousValue, final OnValueEdited callback, boolean password) { AlertDialog.Builder builder = new AlertDialog.Builder(this); - View view = (View) getLayoutInflater() - .inflate(R.layout.quickedit, null); + View view = getLayoutInflater().inflate(R.layout.quickedit, null); final EditText editor = (EditText) view.findViewById(R.id.editor); OnClickListener mClickListener = new OnClickListener() { @@ -450,7 +449,7 @@ public abstract class XmppActivity extends Activity { listener.onPresenceSelected(); } } else if (presences.size() == 1) { - String presence = (String) presences.asStringArray()[0]; + String presence = presences.asStringArray()[0]; conversation.setNextPresence(presence); listener.onPresenceSelected(); } else { diff --git a/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java index 4ca21a3b..e13b3204 100644 --- a/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -28,7 +28,7 @@ public class AccountAdapter extends ArrayAdapter { if (view == null) { LayoutInflater inflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = (View) inflater.inflate(R.layout.account_row, parent, false); + view = inflater.inflate(R.layout.account_row, parent, false); } TextView jid = (TextView) view.findViewById(R.id.account_jid); jid.setText(account.getJid()); diff --git a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index b2e5dd07..b5c20dc5 100644 --- a/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -35,7 +35,7 @@ public class ConversationAdapter extends ArrayAdapter { if (view == null) { LayoutInflater inflater = (LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = (View) inflater.inflate(R.layout.conversation_list_row, + view = inflater.inflate(R.layout.conversation_list_row, parent, false); } Conversation conversation = getItem(position); diff --git a/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 977aa7b5..efc6b4d9 100644 --- a/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -28,7 +28,7 @@ public class ListItemAdapter extends ArrayAdapter { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); ListItem item = getItem(position); if (view == null) { - view = (View) inflater.inflate(R.layout.contact, parent, false); + view = inflater.inflate(R.layout.contact, parent, false); } TextView name = (TextView) view.findViewById(R.id.contact_display_name); TextView jid = (TextView) view.findViewById(R.id.contact_jid); diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 4e04e315..2b4263e8 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -314,11 +314,11 @@ public class MessageAdapter extends ArrayAdapter { viewHolder = new ViewHolder(); switch (type) { case NULL: - view = (View) activity.getLayoutInflater().inflate( + view = activity.getLayoutInflater().inflate( R.layout.message_null, parent, false); break; case SENT: - view = (View) activity.getLayoutInflater().inflate( + view = activity.getLayoutInflater().inflate( R.layout.message_sent, parent, false); viewHolder.message_box = (LinearLayout) view .findViewById(R.id.message_box); @@ -343,7 +343,7 @@ public class MessageAdapter extends ArrayAdapter { view.setTag(viewHolder); break; case RECEIVED: - view = (View) activity.getLayoutInflater().inflate( + view = activity.getLayoutInflater().inflate( R.layout.message_received, parent, false); viewHolder.message_box = (LinearLayout) view .findViewById(R.id.message_box); @@ -367,7 +367,7 @@ public class MessageAdapter extends ArrayAdapter { view.setTag(viewHolder); break; case STATUS: - view = (View) activity.getLayoutInflater().inflate( + view = activity.getLayoutInflater().inflate( R.layout.message_status, parent, false); viewHolder.contact_picture = (ImageView) view .findViewById(R.id.message_photo); -- cgit v1.2.3 From b045dea5497b53c775ea3c5748d640066a088e9a Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 26 Oct 2014 20:18:57 +0100 Subject: set divider for image meta information to '|' to not conflict with URL. breaks images downloaded in between 0.7.3 and now --- src/eu/siacs/conversations/crypto/PgpEngine.java | 16 ++++++++-- src/eu/siacs/conversations/entities/Message.java | 37 ++++++++++++++++++++-- .../siacs/conversations/http/HttpConnection.java | 4 +-- .../xmpp/jingle/JingleConnection.java | 4 +-- 4 files changed, 53 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index 2696c7d2..c3935ff5 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -8,6 +8,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URL; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpSignatureResult; @@ -101,14 +102,25 @@ public class PgpEngine { switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { case OpenPgpApi.RESULT_CODE_SUCCESS: + URL url = message.getImageParams().url; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile( outputFile.getAbsolutePath(), options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; - message.setBody(Long.toString(outputFile.getSize()) - + ',' + imageWidth + ',' + imageHeight); + if (url == null) { + message.setBody(Long.toString(outputFile + .getSize()) + + '|' + + imageWidth + + '|' + + imageHeight); + } else { + message.setBody(url.toString() + "|" + + Long.toString(outputFile.getSize()) + + '|' + imageWidth + '|' + imageHeight); + } message.setEncryption(Message.ENCRYPTION_DECRYPTED); PgpEngine.this.mXmppConnectionService .updateMessage(message); diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index 212eb049..79b9b5ba 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -7,6 +7,7 @@ import java.util.Arrays; import eu.siacs.conversations.Config; import android.content.ContentValues; import android.database.Cursor; +import android.util.Log; public class Message extends AbstractEntity { @@ -405,14 +406,18 @@ public class Message extends AbstractEntity { } public ImageParams getImageParams() { - ImageParams params = new ImageParams(); + ImageParams params = getLegacyImageParams(); + if (params!=null) { + return params; + } + params = new ImageParams(); if (this.downloadable != null) { params.size = this.downloadable.getFileSize(); } if (body == null) { return params; } - String parts[] = body.split(","); + String parts[] = body.split("\\|"); if (parts.length == 1) { try { params.size = Long.parseLong(parts[0]); @@ -465,6 +470,34 @@ public class Message extends AbstractEntity { } return params; } + + public ImageParams getLegacyImageParams() { + ImageParams params = new ImageParams(); + if (body == null) { + return params; + } + String parts[] = body.split(","); + if (parts.length == 3) { + try { + params.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + return null; + } + try { + params.width = Integer.parseInt(parts[1]); + } catch (NumberFormatException e) { + return null; + } + try { + params.height = Integer.parseInt(parts[2]); + } catch (NumberFormatException e) { + return null; + } + return params; + } else { + return null; + } + } public class ImageParams { public URL url; diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 9b04decc..29837880 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -244,8 +244,8 @@ public class HttpConnection implements Downloadable { BitmapFactory.decodeFile(file.getAbsolutePath(), options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; - message.setBody(mUrl.toString() + "," + file.getSize() + ',' - + imageWidth + ',' + imageHeight); + message.setBody(mUrl.toString() + "|" + file.getSize() + '|' + + imageWidth + '|' + imageHeight); message.setType(Message.TYPE_IMAGE); mXmppConnectionService.updateMessage(message); } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index a0b2feb2..7e803f0b 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -98,8 +98,8 @@ public class JingleConnection implements Downloadable { BitmapFactory.decodeFile(file.getAbsolutePath(), options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; - message.setBody(Long.toString(file.getSize()) + ',' - + imageWidth + ',' + imageHeight); + message.setBody(Long.toString(file.getSize()) + '|' + + imageWidth + '|' + imageHeight); mXmppConnectionService.databaseBackend.createMessage(message); mXmppConnectionService.markMessage(message, Message.STATUS_RECEIVED); -- cgit v1.2.3 From da822ebae89ad3b010a58cdf3b812d26de4b2aa4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 27 Oct 2014 11:00:03 +0100 Subject: check for links in pgp encrypted messages as well --- src/eu/siacs/conversations/crypto/PgpEngine.java | 4 ++++ src/eu/siacs/conversations/entities/Message.java | 11 +++++------ src/eu/siacs/conversations/http/HttpConnection.java | 2 ++ src/eu/siacs/conversations/parser/MessageParser.java | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index c3935ff5..f1a698db 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -61,6 +61,10 @@ public class PgpEngine { if (message.getEncryption() == Message.ENCRYPTION_PGP) { message.setBody(os.toString()); message.setEncryption(Message.ENCRYPTION_DECRYPTED); + if (message.trusted() && message.bodyContainsDownloadable()) { + mXmppConnectionService.getHttpConnectionManager() + .createNewConnection(message); + } callback.success(message); } } catch (IOException e) { diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index 79b9b5ba..a089dd64 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -7,7 +7,6 @@ import java.util.Arrays; import eu.siacs.conversations.Config; import android.content.ContentValues; import android.database.Cursor; -import android.util.Log; public class Message extends AbstractEntity { @@ -367,13 +366,13 @@ public class Message extends AbstractEntity { return prev.mergable(this); } } + + public boolean trusted() { + Contact contact = this.getContact(); + return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); + } public boolean bodyContainsDownloadable() { - Contact contact = this.getContact(); - if (status <= STATUS_RECEIVED - && (contact == null || !contact.trusted())) { - return false; - } try { URL url = new URL(this.getBody()); if (!url.getProtocol().equalsIgnoreCase("http") diff --git a/src/eu/siacs/conversations/http/HttpConnection.java b/src/eu/siacs/conversations/http/HttpConnection.java index 29837880..0810e167 100644 --- a/src/eu/siacs/conversations/http/HttpConnection.java +++ b/src/eu/siacs/conversations/http/HttpConnection.java @@ -65,6 +65,8 @@ public class HttpConnection implements Downloadable { String path = mUrl.getPath(); if (path != null && (path.endsWith(".pgp") || path.endsWith(".gpg"))) { this.message.setEncryption(Message.ENCRYPTION_PGP); + } else if (message.getEncryption() != Message.ENCRYPTION_OTR) { + this.message.setEncryption(Message.ENCRYPTION_NONE); } this.file = mXmppConnectionService.getFileBackend().getFile( message, false); diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index 26841f43..1d80ec5c 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -484,7 +484,7 @@ public class MessageParser extends AbstractParser implements mXmppConnectionService.databaseBackend.createMessage(message); } } - if (message.bodyContainsDownloadable()) { + if (message.trusted() && message.bodyContainsDownloadable()) { this.mXmppConnectionService.getHttpConnectionManager() .createNewConnection(message); notify = false; -- cgit v1.2.3 From f45a841caff20692586e19933ed1571d3e6cbf21 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 27 Oct 2014 21:47:17 +0100 Subject: fixed url parsing --- src/eu/siacs/conversations/entities/Message.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index a089dd64..dd88c126 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -383,7 +383,12 @@ public class Message extends AbstractEntity { return false; } String[] pathParts = url.getPath().split("/"); - String filename = pathParts[pathParts.length - 1]; + String filename; + if (pathParts.length > 0) { + filename = pathParts[pathParts.length - 1]; + } else { + filename = pathParts[0]; + } String[] extensionParts = filename.split("\\."); if (extensionParts.length == 2 && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains( -- cgit v1.2.3 From 698572d21829e463957051eae7745cda61624a37 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 27 Oct 2014 21:47:41 +0100 Subject: proper cleanup after pgp image decryption --- src/eu/siacs/conversations/crypto/PgpEngine.java | 25 +++++++++--------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/crypto/PgpEngine.java b/src/eu/siacs/conversations/crypto/PgpEngine.java index f1a698db..9a2b4a11 100644 --- a/src/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/eu/siacs/conversations/crypto/PgpEngine.java @@ -10,12 +10,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URL; -import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback; -import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; @@ -27,7 +25,7 @@ import eu.siacs.conversations.ui.UiCallback; import android.app.PendingIntent; import android.content.Intent; import android.graphics.BitmapFactory; -import android.util.Log; +import android.net.Uri; public class PgpEngine { private OpenPgpApi api; @@ -40,7 +38,6 @@ public class PgpEngine { public void decrypt(final Message message, final UiCallback callback) { - Log.d(Config.LOGTAG, "decrypting message " + message.getUuid()); Intent params = new Intent(); params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message @@ -79,10 +76,6 @@ public class PgpEngine { message); return; case OpenPgpApi.RESULT_CODE_ERROR: - OpenPgpError error = result - .getParcelableExtra(OpenPgpApi.RESULT_ERROR); - Log.d(Config.LOGTAG, - "openpgp error: " + error.getMessage()); callback.error(R.string.openpgp_error, message); return; default: @@ -128,7 +121,10 @@ public class PgpEngine { message.setEncryption(Message.ENCRYPTION_DECRYPTED); PgpEngine.this.mXmppConnectionService .updateMessage(message); - ; + inputFile.delete(); + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(Uri.fromFile(outputFile)); + mXmppConnectionService.sendBroadcast(intent); callback.success(message); return; case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: @@ -242,9 +238,11 @@ public class PgpEngine { } }); } catch (FileNotFoundException e) { - Log.d(Config.LOGTAG, "file not found: " + e.getMessage()); + callback.error(R.string.openpgp_error, message); + return; } catch (IOException e) { - Log.d(Config.LOGTAG, "io exception during file encrypt"); + callback.error(R.string.openpgp_error, message); + return; } } } @@ -288,11 +286,6 @@ public class PgpEngine { case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: return 0; case OpenPgpApi.RESULT_CODE_ERROR: - Log.d(Config.LOGTAG, - "openpgp error: " - + ((OpenPgpError) result - .getParcelableExtra(OpenPgpApi.RESULT_ERROR)) - .getMessage()); return 0; } return 0; -- cgit v1.2.3 From 915def24f9f47bc4de401ea67373bfb098681a7f Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 27 Oct 2014 21:48:09 +0100 Subject: removed unnecessary logging from avatar service --- src/eu/siacs/conversations/services/AvatarService.java | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/AvatarService.java b/src/eu/siacs/conversations/services/AvatarService.java index c0668a19..c5bdd101 100644 --- a/src/eu/siacs/conversations/services/AvatarService.java +++ b/src/eu/siacs/conversations/services/AvatarService.java @@ -17,7 +17,6 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.net.Uri; -import android.util.Log; public class AvatarService { @@ -43,7 +42,6 @@ public class AvatarService { if (avatar != null) { return avatar; } - Log.d(Config.LOGTAG, "no cache hit for " + KEY); avatar = mXmppConnectionService.getFileBackend().getAvatar( contact.getAvatar(), size); if (avatar == null) { @@ -116,7 +114,6 @@ public class AvatarService { if (bitmap != null) { return bitmap; } - Log.d(Config.LOGTAG, "no cache hit for " + KEY); List users = mucOptions.getUsers(); int count = users.size(); bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); @@ -178,7 +175,6 @@ public class AvatarService { if (avatar != null) { return avatar; } - Log.d(Config.LOGTAG, "no cache hit for " + KEY); avatar = mXmppConnectionService.getFileBackend().getAvatar( account.getAvatar(), size); if (avatar == null) { @@ -211,7 +207,6 @@ public class AvatarService { if (bitmap != null) { return bitmap; } - Log.d(Config.LOGTAG, "no cache hit for " + KEY); bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); String letter = name.substring(0, 1); -- cgit v1.2.3 From 7dcce220cbbac3a9cd23df825c2a81043fc2f68c Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 27 Oct 2014 21:48:25 +0100 Subject: reworked dns retry --- src/eu/siacs/conversations/utils/DNSHelper.java | 50 ++++++---------- .../siacs/conversations/xmpp/XmppConnection.java | 67 +++++++++++----------- 2 files changed, 51 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/utils/DNSHelper.java b/src/eu/siacs/conversations/utils/DNSHelper.java index c51a75ac..f101e883 100644 --- a/src/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/eu/siacs/conversations/utils/DNSHelper.java @@ -33,7 +33,7 @@ public class DNSHelper { for (String dnsserver : dns) { InetAddress ip = InetAddress.getByName(dnsserver); Bundle b = queryDNS(host, ip); - if (b.containsKey("name")) { + if (b.containsKey("values")) { return b; } else if (b.containsKey("error") && "nosrv".equals(b.getString("error", null))) { @@ -45,7 +45,7 @@ public class DNSHelper { } public static Bundle queryDNS(String host, InetAddress dnsServer) { - Bundle namePort = new Bundle(); + Bundle bundle = new Bundle(); try { String qname = "_xmpp-client._tcp." + host; Log.d(Config.LOGTAG, @@ -133,42 +133,28 @@ public class DNSHelper { } if (result.size() == 0) { - namePort.putString("error", "nosrv"); - return namePort; + bundle.putString("error", "nosrv"); + return bundle; } - // we now have a list of servers to try :-) - - // classic name/port pair - String resultName = result.get(0).getName(); - namePort.putString("name", resultName); - namePort.putInt("port", result.get(0).getPort()); - - if (ips4.containsKey(resultName)) { - // we have an ip! - ArrayList ip = ips4.get(resultName); - Collections.shuffle(ip, rnd); - namePort.putString("ipv4", ip.get(0)); - } - if (ips6.containsKey(resultName)) { - ArrayList ip = ips6.get(resultName); - Collections.shuffle(ip, rnd); - namePort.putString("ipv6", ip.get(0)); - } - - // add all other records - int i = 0; + ArrayList values = new ArrayList(); for (SRV srv : result) { - namePort.putString("name" + i, srv.getName()); - namePort.putInt("port" + i, srv.getPort()); - i++; + Bundle namePort = new Bundle(); + namePort.putString("name", srv.getName()); + namePort.putInt("port", srv.getPort()); + if (ips4.containsKey(srv.getName())) { + ArrayList ip = ips4.get(srv.getName()); + Collections.shuffle(ip, rnd); + namePort.putString("ipv4", ip.get(0)); + } + values.add(namePort); } - + bundle.putParcelableArrayList("values", values); } catch (SocketTimeoutException e) { - namePort.putString("error", "timeout"); + bundle.putString("error", "timeout"); } catch (Exception e) { - namePort.putString("error", "unhandled"); + bundle.putString("error", "unhandled"); } - return namePort; + return bundle; } final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 903dc59d..39dcb362 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; @@ -32,6 +33,7 @@ import de.duenndns.ssl.MemorizingTrustManager; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Parcelable; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; @@ -155,50 +157,47 @@ public class XmppConnection implements Runnable { tagWriter = new TagWriter(); packetCallbacks.clear(); this.changeStatus(Account.STATUS_CONNECTING); - Bundle namePort = DNSHelper.getSRVRecord(account.getServer()); - if ("timeout".equals(namePort.getString("error"))) { + Bundle result = DNSHelper.getSRVRecord(account.getServer()); + ArrayList values = result.getParcelableArrayList("values"); + if ("timeout".equals(result.getString("error"))) { Log.d(Config.LOGTAG, account.getJid() + ": dns timeout"); this.changeStatus(Account.STATUS_OFFLINE); return; - } - String srvRecordServer = namePort.getString("name"); - String srvIpServer = namePort.getString("ipv4"); - int srvRecordPort = namePort.getInt("port"); - if (srvRecordServer != null) { - if (srvIpServer != null) { - Log.d(Config.LOGTAG, account.getJid() - + ": using values from dns " + srvRecordServer - + "[" + srvIpServer + "]:" + srvRecordPort); - socket = new Socket(srvIpServer, srvRecordPort); - } else { + } else if (values != null) { + int i = 0; boolean socketError = true; - int srvIndex = 0; - while (socketError - && namePort.containsKey("name" + srvIndex)) { + while (socketError && values.size() > i) { + Bundle namePort = (Bundle) values.get(i); try { - srvRecordServer = namePort.getString("name" - + srvIndex); - srvRecordPort = namePort.getInt("port" + srvIndex); - Log.d(Config.LOGTAG, account.getJid() - + ": using values from dns " - + srvRecordServer + ":" + srvRecordPort); - socket = new Socket(srvRecordServer, srvRecordPort); + String srvRecordServer = namePort.getString("name"); + int srvRecordPort = namePort.getInt("port"); + String srvIpServer = namePort.getString("ipv4"); + InetSocketAddress addr; + if (srvIpServer!=null) { + addr = new InetSocketAddress(srvIpServer, srvRecordPort); + Log.d(Config.LOGTAG, account.getJid() + + ": using values from dns " + srvRecordServer + + "[" + srvIpServer + "]:" + srvRecordPort); + } else { + addr = new InetSocketAddress(srvRecordServer, srvRecordPort); + Log.d(Config.LOGTAG, account.getJid() + + ": using values from dns " + + srvRecordServer + ":" + srvRecordPort); + } + socket = new Socket(); + socket.connect(addr, 20000); socketError = false; } catch (UnknownHostException e) { - srvIndex++; - if (!namePort.containsKey("name" + srvIndex)) { - throw e; - } + i++; } catch (IOException e) { - srvIndex++; - if (!namePort.containsKey("name" + srvIndex)) { - throw e; - } + i++; } } - } - } else if (namePort.containsKey("error") - && "nosrv".equals(namePort.getString("error", null))) { + if (socketError) { + throw new IOException(); + } + } else if (result.containsKey("error") + && "nosrv".equals(result.getString("error", null))) { socket = new Socket(account.getServer(), 5222); } else { Log.d(Config.LOGTAG, account.getJid() -- cgit v1.2.3 From 161623eca28a6e80849aeabbd719d349a4696697 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 28 Oct 2014 17:15:13 +0100 Subject: always show verify fingerprint if there is an active otr session --- src/eu/siacs/conversations/ui/ConversationFragment.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index fe3f79cb..9c0c453e 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -569,7 +569,7 @@ public class ConversationFragment extends Fragment { this.messageListAdapter.notifyDataSetChanged(); if (conversation.getMode() == Conversation.MODE_SINGLE) { if (messageList.size() >= 1) { - makeFingerprintWarning(conversation.getLatestEncryption()); + makeFingerprintWarning(); } } else { if (!conversation.getMucOptions().online() @@ -721,14 +721,13 @@ public class ConversationFragment extends Fragment { } } - protected void makeFingerprintWarning(int latestEncryption) { + protected void makeFingerprintWarning() { Set knownFingerprints = conversation.getContact() .getOtrFingerprints(); - if ((latestEncryption == Message.ENCRYPTION_OTR) - && (conversation.hasValidOtrSession() + if (conversation.hasValidOtrSession() && (!conversation.isMuted()) && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints - .contains(conversation.getOtrFingerprint())))) { + .contains(conversation.getOtrFingerprint()))) { showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, new OnClickListener() { -- cgit v1.2.3 From f256a466d812744937f50e4270bd915d34be536d Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 28 Oct 2014 17:15:35 +0100 Subject: improvements on findConversation --- src/eu/siacs/conversations/services/XmppConnectionService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 6d6c672e..25ca48f2 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -922,9 +922,9 @@ public class XmppConnectionService extends Service { public Conversation find(List haystack, Account account, String jid) { for (Conversation conversation : haystack) { - if ((account == null || conversation.getAccount().equals(account)) + if ((account == null || conversation.getAccount() == account) && (conversation.getContactJid().split("/", 2)[0] - .equals(jid))) { + .equalsIgnoreCase(jid))) { return conversation; } } -- cgit v1.2.3 From 962e8183f641b839a47a39635083c4a91c0fb329 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 28 Oct 2014 18:02:12 +0100 Subject: end otr session if plain text message from another instance is being received --- src/eu/siacs/conversations/parser/MessageParser.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index 1d80ec5c..383ac89a 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -256,7 +256,6 @@ public class MessageParser extends AbstractParser implements return null; } } - return finishedMessage; } @@ -478,6 +477,14 @@ public class MessageParser extends AbstractParser implements } Conversation conversation = message.getConversation(); conversation.add(message); + + if (message.getStatus() == Message.STATUS_RECEIVED + && conversation.getOtrSession() != null + && !conversation.getOtrSession().getSessionID().getUserID() + .equals(message.getPresence())) { + conversation.endOtrIfNeeded(); + } + if (packet.getType() != MessagePacket.TYPE_ERROR) { if (message.getEncryption() == Message.ENCRYPTION_NONE || mXmppConnectionService.saveEncryptedMessages()) { -- cgit v1.2.3 From bb26a842694d1fd53fb2f5b579e22521f0c76e31 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 29 Oct 2014 09:57:03 +0100 Subject: fixed intent managment --- src/eu/siacs/conversations/ui/ConversationActivity.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 8a10a782..1d7364d6 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -244,7 +244,8 @@ public class ConversationActivity extends XmppActivity implements MenuItem menuSecure = menu.findItem(R.id.action_security); MenuItem menuArchive = menu.findItem(R.id.action_archive); MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details); - MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details); + MenuItem menuContactDetails = menu + .findItem(R.id.action_contact_details); MenuItem menuAttach = menu.findItem(R.id.action_attach_file); MenuItem menuClearHistory = menu.findItem(R.id.action_clear_history); MenuItem menuAdd = menu.findItem(R.id.action_add); @@ -625,8 +626,7 @@ public class ConversationActivity extends XmppActivity implements @Override protected void onNewIntent(Intent intent) { if (xmppConnectionServiceBound) { - if (intent != null - && VIEW_CONVERSATION.equals(getIntent().getType())) { + if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) { handleViewConversationIntent(intent); } } else { @@ -679,6 +679,10 @@ public class ConversationActivity extends XmppActivity implements } else if (conversationList.size() <= 0) { startActivity(new Intent(this, StartConversationActivity.class)); finish(); + } else if (getIntent() != null + && VIEW_CONVERSATION.equals(getIntent().getType())) { + handleViewConversationIntent(getIntent()); + setIntent(null); } else if (mOpenConverstaion != null) { selectConversationByUuid(mOpenConverstaion); paneShouldBeOpen = mPanelOpen; @@ -687,10 +691,6 @@ public class ConversationActivity extends XmppActivity implements } swapConversationFragment(); mOpenConverstaion = null; - } else if (getIntent() != null - && VIEW_CONVERSATION.equals(getIntent().getType())) { - handleViewConversationIntent(getIntent()); - setIntent(null); } else { showConversationsOverview(); ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager() @@ -711,7 +711,7 @@ public class ConversationActivity extends XmppActivity implements } ExceptionHelper.checkForCrash(this, this.xmppConnectionService); } - + private void handleViewConversationIntent(Intent intent) { String uuid = (String) intent.getExtras().get(CONVERSATION); String text = intent.getExtras().getString(TEXT, null); -- cgit v1.2.3 From 64209829f779214ae7fc0c6ab35de4d006c745c4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 29 Oct 2014 09:57:34 +0100 Subject: fixed 'share image' context menu --- src/eu/siacs/conversations/ui/ConversationFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index 9c0c453e..bb72711b 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -361,8 +361,7 @@ public class ConversationFragment extends Fragment { copyText.setVisible(false); } if (this.selectedMessage.getType() != Message.TYPE_IMAGE - || (this.selectedMessage.getDownloadable() != null && this.selectedMessage - .getDownloadable().getStatus() == Downloadable.STATUS_DELETED)) { + || this.selectedMessage.getDownloadable() != null) { shareImage.setVisible(false); } if (this.selectedMessage.getStatus() != Message.STATUS_SEND_FAILED) { -- cgit v1.2.3 From 03593ba56fe0a15312e3ae231dfdaf3be6c7548a Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 29 Oct 2014 11:31:03 +0100 Subject: proper error state for images --- src/eu/siacs/conversations/entities/Message.java | 1 - src/eu/siacs/conversations/ui/ConversationFragment.java | 1 - .../siacs/conversations/ui/adapter/MessageAdapter.java | 9 +++++---- .../conversations/xmpp/jingle/JingleConnection.java | 16 ++++------------ .../xmpp/jingle/JingleConnectionManager.java | 9 +++++++-- 5 files changed, 16 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java index dd88c126..8a83c465 100644 --- a/src/eu/siacs/conversations/entities/Message.java +++ b/src/eu/siacs/conversations/entities/Message.java @@ -16,7 +16,6 @@ public class Message extends AbstractEntity { public static final int STATUS_UNSEND = 1; public static final int STATUS_SEND = 2; public static final int STATUS_SEND_FAILED = 3; - public static final int STATUS_SEND_REJECTED = 4; public static final int STATUS_WAITING = 5; public static final int STATUS_OFFERED = 6; public static final int STATUS_SEND_RECEIVED = 7; diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index bb72711b..20eeeb30 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -11,7 +11,6 @@ import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 2b4263e8..a24f90d7 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -100,6 +100,9 @@ public class MessageAdapter extends ArrayAdapter { if (params.size != 0) { filesize = params.size / 1024 + " KB"; } + if (message.getDownloadable() != null && message.getDownloadable().getStatus() == Downloadable.STATUS_FAILED) { + error = true; + } } switch (message.getMergedStatus()) { case Message.STATUS_WAITING: @@ -125,10 +128,6 @@ public class MessageAdapter extends ArrayAdapter { info = getContext().getString(R.string.send_failed); error = true; break; - case Message.STATUS_SEND_REJECTED: - info = getContext().getString(R.string.send_rejected); - error = true; - break; default: if (multiReceived) { Contact contact = message.getContact(); @@ -484,6 +483,8 @@ public class MessageAdapter extends ArrayAdapter { && d.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) { displayDownloadableMessage(viewHolder, item, R.string.check_image_filesize); + } else if (d != null && d.getStatus() == Downloadable.STATUS_FAILED) { + displayInfoMessage(viewHolder, R.string.image_transmission_failed); } else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED) || (item.getEncryption() == Message.ENCRYPTION_NONE) || (item.getEncryption() == Message.ENCRYPTION_OTR)) { diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index 7e803f0b..6b9ca9aa 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -73,11 +73,7 @@ public class JingleConnection implements Downloadable { @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.getType() == IqPacket.TYPE_ERROR) { - if (initiator.equals(account.getFullJid())) { - mXmppConnectionService.markMessage(message, - Message.STATUS_SEND_FAILED); - } - mJingleStatus = JINGLE_STATUS_FAILED; + cancel(); } } }; @@ -354,6 +350,7 @@ public class JingleConnection implements Downloadable { } private void sendInitRequest() { + this.mXmppConnectionService.markMessage(this.message, Message.STATUS_OFFERED); JinglePacket packet = this.bootstrapPacket("session-initiate"); Content content = new Content(this.contentCreator, this.contentName); if (message.getType() == Message.TYPE_IMAGE) { @@ -716,13 +713,8 @@ public class JingleConnection implements Downloadable { this.mStatus = Downloadable.STATUS_FAILED; this.mXmppConnectionService.updateConversationUi(); } else { - if (this.mJingleStatus == JINGLE_STATUS_INITIATED) { - this.mXmppConnectionService.markMessage(this.message, - Message.STATUS_SEND_REJECTED); - } else { - this.mXmppConnectionService.markMessage(this.message, - Message.STATUS_SEND_FAILED); - } + this.mXmppConnectionService.markMessage(this.message, + Message.STATUS_SEND_FAILED); } } this.mJingleConnectionManager.finishConnection(this); diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 1e7c84d4..d937146a 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -44,8 +44,13 @@ public class JingleConnectionManager extends AbstractConnectionManager { return; } } - account.getXmppConnection().sendIqPacket( - packet.generateRespone(IqPacket.TYPE_ERROR), null); + IqPacket response = packet.generateRespone(IqPacket.TYPE_ERROR); + Element error = response.addChild("error"); + error.setAttribute("type", "cancel"); + error.addChild("item-not-found", + "urn:ietf:params:xml:ns:xmpp-stanzas"); + error.addChild("unknown-session", "urn:xmpp:jingle:errors:1"); + account.getXmppConnection().sendIqPacket(response, null); } } -- cgit v1.2.3 From 1b62d94093256493ec4dd7c4a6aa9ba137d5e338 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 29 Oct 2014 18:12:32 +0100 Subject: replace the exif interface with a small static class from 3d gallery --- .../conversations/persistance/FileBackend.java | 23 +-- src/eu/siacs/conversations/utils/ExifHelper.java | 161 +++++++++++++++++++++ 2 files changed, 167 insertions(+), 17 deletions(-) create mode 100644 src/eu/siacs/conversations/utils/ExifHelper.java (limited to 'src') diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index b891e9ef..5eccf15c 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -20,7 +20,6 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; -import android.media.ExifInterface; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; @@ -34,6 +33,7 @@ import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.utils.ExifHelper; import eu.siacs.conversations.xmpp.pep.Avatar; public class FileBackend { @@ -181,23 +181,12 @@ public class FileBackend { return -1; } } else { - ExifInterface exif; try { - exif = new ExifInterface(image.toString()); - if (exif.getAttribute(ExifInterface.TAG_ORIENTATION) - .equalsIgnoreCase("6")) { - return 90; - } else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION) - .equalsIgnoreCase("8")) { - return 270; - } else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION) - .equalsIgnoreCase("3")) { - return 180; - } else { - return 0; - } - } catch (IOException e) { - return -1; + InputStream is = mXmppConnectionService.getContentResolver() + .openInputStream(image); + return ExifHelper.getOrientation(is); + } catch (FileNotFoundException e) { + return 0; } } } diff --git a/src/eu/siacs/conversations/utils/ExifHelper.java b/src/eu/siacs/conversations/utils/ExifHelper.java new file mode 100644 index 00000000..ceda7293 --- /dev/null +++ b/src/eu/siacs/conversations/utils/ExifHelper.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.siacs.conversations.utils; + +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; + +public class ExifHelper { + private static final String TAG = "CameraExif"; + + public static int getOrientation(InputStream is) { + if (is == null) { + return 0; + } + + byte[] buf = new byte[8]; + int length = 0; + + // ISO/IEC 10918-1:1993(E) + while (read(is, buf, 2) && (buf[0] & 0xFF) == 0xFF) { + int marker = buf[1] & 0xFF; + + // Check if the marker is a padding. + if (marker == 0xFF) { + continue; + } + + // Check if the marker is SOI or TEM. + if (marker == 0xD8 || marker == 0x01) { + continue; + } + // Check if the marker is EOI or SOS. + if (marker == 0xD9 || marker == 0xDA) { + return 0; + } + + // Get the length and check if it is reasonable. + if (!read(is, buf, 2)) { + return 0; + } + length = pack(buf, 0, 2, false); + if (length < 2) { + Log.e(TAG, "Invalid length"); + return 0; + } + length -= 2; + + // Break if the marker is EXIF in APP1. + if (marker == 0xE1 && length >= 6) { + if (!read(is, buf, 6)) return 0; + length -= 6; + if (pack(buf, 0, 4, false) == 0x45786966 && + pack(buf, 4, 2, false) == 0) { + break; + } + } + + // Skip other markers. + try { + is.skip(length); + } catch (IOException ex) { + return 0; + } + length = 0; + } + + // JEITA CP-3451 Exif Version 2.2 + if (length > 8) { + int offset = 0; + byte[] jpeg = new byte[length]; + if (!read(is, jpeg, length)) { + return 0; + } + + // Identify the byte order. + int tag = pack(jpeg, offset, 4, false); + if (tag != 0x49492A00 && tag != 0x4D4D002A) { + Log.e(TAG, "Invalid byte order"); + return 0; + } + boolean littleEndian = (tag == 0x49492A00); + + // Get the offset and check if it is reasonable. + int count = pack(jpeg, offset + 4, 4, littleEndian) + 2; + if (count < 10 || count > length) { + Log.e(TAG, "Invalid offset"); + return 0; + } + offset += count; + length -= count; + + // Get the count and go through all the elements. + count = pack(jpeg, offset - 2, 2, littleEndian); + while (count-- > 0 && length >= 12) { + // Get the tag and check if it is orientation. + tag = pack(jpeg, offset, 2, littleEndian); + if (tag == 0x0112) { + // We do not really care about type and count, do we? + int orientation = pack(jpeg, offset + 8, 2, littleEndian); + switch (orientation) { + case 1: + return 0; + case 3: + return 180; + case 6: + return 90; + case 8: + return 270; + } + Log.i(TAG, "Unsupported orientation"); + return 0; + } + offset += 12; + length -= 12; + } + } + + Log.i(TAG, "Orientation not found"); + return 0; + } + + private static int pack(byte[] bytes, int offset, int length, + boolean littleEndian) { + int step = 1; + if (littleEndian) { + offset += length - 1; + step = -1; + } + + int value = 0; + while (length-- > 0) { + value = (value << 8) | (bytes[offset] & 0xFF); + offset += step; + } + return value; + } + + private static boolean read(InputStream is, byte[] buf, int length) { + try { + return is.read(buf, 0, length) == length; + } catch (IOException ex) { + return false; + } + } +} -- cgit v1.2.3 From e4567e7a62b4ae4773844b47a6a945aa7565f5b9 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 30 Oct 2014 00:31:44 +0100 Subject: cleanup for clear conversation history. small otr fixes --- .../conversations/persistance/DatabaseBackend.java | 18 ++++++++++++++++++ .../conversations/persistance/FileBackend.java | 22 ---------------------- .../conversations/services/AvatarService.java | 1 - .../services/XmppConnectionService.java | 7 ++++--- 4 files changed, 22 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/eu/siacs/conversations/persistance/DatabaseBackend.java index b49cf4e6..12e5e251 100644 --- a/src/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -332,4 +332,22 @@ public class DatabaseBackend extends SQLiteOpenHelper { cursor.moveToFirst(); return Account.fromCursor(cursor); } + + public List getImageMessages(Conversation conversation) { + ArrayList list = new ArrayList(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor cursor; + String[] selectionArgs = { conversation.getUuid(), String.valueOf(Message.TYPE_IMAGE) }; + cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION + + "=? AND "+Message.TYPE+"=?", selectionArgs, null, null,null); + if (cursor.getCount() > 0) { + cursor.moveToLast(); + do { + Message message = Message.fromCursor(cursor); + message.setConversation(conversation); + list.add(message); + } while (cursor.moveToPrevious()); + } + return list; + } } diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java index 5eccf15c..13daa27b 100644 --- a/src/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/eu/siacs/conversations/persistance/FileBackend.java @@ -28,7 +28,6 @@ import android.util.Base64OutputStream; import android.util.Log; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; @@ -215,27 +214,6 @@ public class FileBackend { return thumbnail; } - public void removeFiles(Conversation conversation) { - String prefix = mXmppConnectionService.getFilesDir().getAbsolutePath(); - String path = prefix + "/" + conversation.getAccount().getJid() + "/" - + conversation.getContactJid(); - File file = new File(path); - try { - this.deleteFile(file); - } catch (IOException e) { - Log.d(Config.LOGTAG, - "error deleting file: " + file.getAbsolutePath()); - } - } - - private void deleteFile(File f) throws IOException { - if (f.isDirectory()) { - for (File c : f.listFiles()) - deleteFile(c); - } - f.delete(); - } - public Uri getTakePhotoUri() { StringBuilder pathBuilder = new StringBuilder(); pathBuilder.append(Environment diff --git a/src/eu/siacs/conversations/services/AvatarService.java b/src/eu/siacs/conversations/services/AvatarService.java index c5bdd101..bd27b555 100644 --- a/src/eu/siacs/conversations/services/AvatarService.java +++ b/src/eu/siacs/conversations/services/AvatarService.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 25ca48f2..ece110e5 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -567,13 +567,14 @@ public class XmppConnectionService extends Service { && conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { mJingleConnectionManager .createNewConnection(message); - } else if (message.getPresence() == null) { - message.setStatus(Message.STATUS_WAITING); } } else { mJingleConnectionManager.createNewConnection(message); } } else { + if (message.getEncryption() == Message.ENCRYPTION_OTR) { + conv.startOtrIfNeeded(); + } message.setStatus(Message.STATUS_WAITING); } } else { @@ -590,6 +591,7 @@ public class XmppConnectionService extends Service { send = true; } else if (message.getPresence() == null) { + conv.startOtrIfNeeded(); message.setStatus(Message.STATUS_WAITING); } } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { @@ -991,7 +993,6 @@ public class XmppConnectionService extends Service { public void clearConversationHistory(Conversation conversation) { this.databaseBackend.deleteMessagesInConversation(conversation); - this.fileBackend.removeFiles(conversation); conversation.getMessages().clear(); updateConversationUi(); } -- cgit v1.2.3 From 7b4f3637db8c99d84fe3c825d583bfc0fa91fada Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 30 Oct 2014 10:59:41 +0100 Subject: only end otr session if there is more than one contact presence. reset otherwise --- src/eu/siacs/conversations/services/XmppConnectionService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index ece110e5..be73e07f 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -127,7 +127,11 @@ public class XmppConnectionService extends Service { public void onContactStatusChanged(Contact contact, boolean online) { Conversation conversation = find(getConversations(), contact); if (conversation != null) { - conversation.endOtrIfNeeded(); + if (online && contact.getPresences().size() > 1) { + conversation.endOtrIfNeeded(); + } else { + conversation.resetOtrSession(); + } if (online && (contact.getPresences().size() == 1)) { sendUnsendMessages(conversation); } -- cgit v1.2.3