aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu/siacs/conversations/entities')
-rw-r--r--src/eu/siacs/conversations/entities/Account.java51
-rw-r--r--src/eu/siacs/conversations/entities/Bookmark.java18
-rw-r--r--src/eu/siacs/conversations/entities/Contact.java26
-rw-r--r--src/eu/siacs/conversations/entities/Conversation.java69
-rw-r--r--src/eu/siacs/conversations/entities/Downloadable.java18
-rw-r--r--src/eu/siacs/conversations/entities/DownloadableFile.java154
-rw-r--r--src/eu/siacs/conversations/entities/ListItem.java5
-rw-r--r--src/eu/siacs/conversations/entities/Message.java222
-rw-r--r--src/eu/siacs/conversations/entities/MucOptions.java17
-rw-r--r--src/eu/siacs/conversations/entities/Roster.java5
10 files changed, 434 insertions, 151 deletions
diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java
index eacd172c..80a9d62f 100644
--- a/src/eu/siacs/conversations/entities/Account.java
+++ b/src/eu/siacs/conversations/entities/Account.java
@@ -11,16 +11,14 @@ 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;
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 {
@@ -64,16 +62,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<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>();
-
public List<Conversation> pendingConferenceJoins = new CopyOnWriteArrayList<Conversation>();
public List<Conversation> pendingConferenceLeaves = new CopyOnWriteArrayList<Conversation>();
@@ -160,8 +156,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) {
@@ -341,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;
@@ -397,4 +383,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/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 b1ebe662..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 {
@@ -374,4 +360,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/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java
index b4c99dc1..9d4c36db 100644
--- a/src/eu/siacs/conversations/entities/Conversation.java
+++ b/src/eu/siacs/conversations/entities/Conversation.java
@@ -1,14 +1,13 @@
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;
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 {
@@ -57,8 +54,8 @@ public class Conversation extends AbstractEntity {
private String nextPresence;
- private transient CopyOnWriteArrayList<Message> messages = null;
- private transient Account account = null;
+ protected ArrayList<Message> messages = new ArrayList<Message>();
+ protected Account account = null;
private transient SessionImpl otrSession;
@@ -68,12 +65,10 @@ public class Conversation extends AbstractEntity {
private transient MucOptions mucOptions = null;
- //private transient String latestMarkableMessageId;
+ // private transient String latestMarkableMessageId;
private byte[] symmetricKey;
- private boolean otrSessionNeedsStarting = false;
-
private Bookmark bookmark;
public Conversation(String name, Account account, String contactJid,
@@ -106,17 +101,6 @@ public class Conversation extends AbstractEntity {
}
public List<Message> getMessages() {
- if (messages == null) {
- this.messages = new CopyOnWriteArrayList<Message>(); // prevent null
- // pointer
- }
-
- // populate with Conversation (this)
-
- for (Message msg : messages) {
- msg.setConversation(this);
- }
-
return messages;
}
@@ -142,8 +126,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 {
@@ -166,7 +151,7 @@ public class Conversation extends AbstractEntity {
}
}
- public void setMessages(CopyOnWriteArrayList<Message> msgs) {
+ public void setMessages(ArrayList<Message> msgs) {
this.messages = msgs;
}
@@ -263,10 +248,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) {
@@ -282,12 +264,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) {
@@ -296,18 +278,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;
}
}
@@ -339,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;
}
@@ -438,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)) {
@@ -506,4 +484,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<Message> messages) {
+ synchronized (this.messages) {
+ this.messages.addAll(index, messages);
+ }
+ }
}
diff --git a/src/eu/siacs/conversations/entities/Downloadable.java b/src/eu/siacs/conversations/entities/Downloadable.java
index 8fb4977e..70516b20 100644
--- a/src/eu/siacs/conversations/entities/Downloadable.java
+++ b/src/eu/siacs/conversations/entities/Downloadable.java
@@ -1,5 +1,21 @@
package eu.siacs.conversations.entities;
public interface Downloadable {
- public void start();
+
+ 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 static final int STATUS_DELETED = 0x205;
+ public static final int STATUS_OFFER_CHECK_FILESIZE = 0x206;
+
+ public boolean 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
new file mode 100644
index 00000000..1605c75b
--- /dev/null
+++ b/src/eu/siacs/conversations/entities/DownloadableFile.java
@@ -0,0 +1,154 @@
+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 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) {
+ if (this.expectedSize == 0) {
+ return 0;
+ } else {
+ 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 == 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");
+ } else if (key.length >= 16) {
+ byte[] secretKey = new byte[16];
+ System.arraycopy(key, 0, secretKey, 0, 16);
+ this.aeskey = new SecretKeySpec(secretKey, "AES");
+ }
+ }
+
+ 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(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");
+ 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/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<ListItem> {
public String getDisplayName();
public String getJid();
-
- public Bitmap getImage(int dpSize, Context context);
}
diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java
index 49482bbc..8a83c465 100644
--- a/src/eu/siacs/conversations/entities/Message.java
+++ b/src/eu/siacs/conversations/entities/Message.java
@@ -1,23 +1,21 @@
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;
public class Message extends AbstractEntity {
public static final String TABLENAME = "messages";
- 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;
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;
@@ -61,6 +59,9 @@ public class Message extends AbstractEntity {
protected Downloadable downloadable = null;
public boolean markable = false;
+ private Message mNextMessage = null;
+ private Message mPreviousMessage = null;
+
private Message() {
}
@@ -131,14 +132,8 @@ public class Message extends AbstractEntity {
if (this.trueCounterpart == null) {
return null;
} else {
- Account account = this.conversation.getAccount();
- Contact contact = account.getRoster().getContact(
- this.trueCounterpart);
- if (contact.showInRoster()) {
- return contact;
- } else {
- return null;
- }
+ return this.conversation.getAccount().getRoster()
+ .getContactFromRoster(this.trueCounterpart);
}
}
}
@@ -147,22 +142,6 @@ public class Message extends AbstractEntity {
return body;
}
- public String getReadableBody(Context context) {
- if ((encryption == ENCRYPTION_PGP) && (type == TYPE_TEXT)) {
- 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) {
- return context.getText(R.string.image_file).toString();
- } else {
- return body.trim();
- }
- }
-
public long getTimeSent() {
return timeSent;
}
@@ -301,21 +280,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) {
@@ -323,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()
@@ -332,7 +326,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() {
@@ -369,4 +365,148 @@ 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() {
+ 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;
+ 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(
+ extensionParts[extensionParts.length - 1])) {
+ return true;
+ } else if (extensionParts.length == 3
+ && Arrays
+ .asList(Downloadable.VALID_CRYPTO_EXTENSIONS)
+ .contains(extensionParts[extensionParts.length - 1])
+ && Arrays.asList(Downloadable.VALID_EXTENSIONS).contains(
+ extensionParts[extensionParts.length - 2])) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (MalformedURLException e) {
+ return false;
+ }
+ }
+
+ public ImageParams getImageParams() {
+ 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("\\|");
+ if (parts.length == 1) {
+ try {
+ 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 {
+ 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.url = new URL(parts[0]);
+ } catch (MalformedURLException e1) {
+ params.url = null;
+ }
+ 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 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;
+ public long size = 0;
+ public int width = 0;
+ public int height = 0;
+ public String origin;
+ }
}
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 b6908793..3267b15a 100644
--- a/src/eu/siacs/conversations/entities/Roster.java
+++ b/src/eu/siacs/conversations/entities/Roster.java
@@ -14,7 +14,10 @@ public class Roster {
this.account = account;
}
- public Contact getContactAsShownInRoster(String jid) {
+ 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()) {