diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/entities/Message.java')
-rw-r--r-- | src/main/java/eu/siacs/conversations/entities/Message.java | 235 |
1 files changed, 86 insertions, 149 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index be9d3d92..5fafb6c8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -5,13 +5,10 @@ import android.database.Cursor; import java.net.MalformedURLException; import java.net.URL; -import java.util.Arrays; -import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; -import eu.siacs.conversations.utils.GeoHelper; +import eu.siacs.conversations.utils.FileUtils; import eu.siacs.conversations.utils.MimeUtils; -import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -66,7 +63,7 @@ public class Message extends AbstractEntity { protected String conversationUuid; protected Jid counterpart; protected Jid trueCounterpart; - protected String body; + private String body; protected String encryptedBody; protected long timeSent; protected int encryption; @@ -84,6 +81,7 @@ public class Message extends AbstractEntity { private Message mNextMessage = null; private Message mPreviousMessage = null; private String axolotlFingerprint = null; + private Decision mTreatAsDownloadAble = Decision.NOT_DECIDED; private Message() { @@ -189,14 +187,6 @@ public class Message extends AbstractEntity { return message; } - public static Message createLoadMoreMessage(Conversation conversation) { - final Message message = new Message(); - message.setType(Message.TYPE_STATUS); - message.setConversation(conversation); - message.setBody("LOAD_MORE"); - return message; - } - @Override public ContentValues getContentValues() { ContentValues values = new ContentValues(); @@ -353,10 +343,6 @@ public class Message extends AbstractEntity { this.carbon = carbon; } - public void setEdited(String edited) { - this.edited = edited; - } - public boolean edited() { return this.edited != null; } @@ -365,10 +351,6 @@ public class Message extends AbstractEntity { this.trueCounterpart = trueCounterpart; } - public Jid getTrueCounterpart() { - return this.trueCounterpart; - } - public Transferable getTransferable() { return this.transferable; } @@ -378,30 +360,40 @@ public class Message extends AbstractEntity { } public boolean equals(Message message) { - if (this.serverMsgId != null && message.getServerMsgId() != null) { - return this.serverMsgId.equals(message.getServerMsgId()); - } else if (this.body == null || this.counterpart == null) { + if (this.getServerMsgId() != null && message.getServerMsgId() != null) { + return this.getServerMsgId().equals(message.getServerMsgId()); + } else if (this.getBody() == null || this.getCounterpart() == null + || message.getBody() == null || message.getCounterpart() == null) { return false; } else { String body, otherBody; if (this.hasFileOnRemoteHost()) { - body = getFileParams().url.toString(); - otherBody = message.body == null ? null : message.body.trim(); + body = this.getFileParams().url.toString(); } else { - body = this.body; - otherBody = message.body; + body = this.getBody(); } - if (message.getRemoteMsgId() != null) { - return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) - && this.counterpart.equals(message.getCounterpart()) + if (message.hasFileOnRemoteHost()) { + otherBody = message.getFileParams().url.toString(); + } else { + otherBody = message.getBody(); + } + + if (message.getRemoteMsgId() != null && this.getRemoteMsgId() != null) { + return (message.getRemoteMsgId().equals(this.getRemoteMsgId()) + || message.getRemoteMsgId().equals(this.getUuid()) + || message.getUuid().equals(this.getRemoteMsgId())) + && this.getCounterpart().equals(message.getCounterpart()) && (body.equals(otherBody) ||(message.getEncryption() == Message.ENCRYPTION_PGP && message.getRemoteMsgId().matches("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))) ; } else { - return this.remoteMsgId == null - && this.counterpart.equals(message.getCounterpart()) - && body.equals(otherBody) - && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000; + // existing (send) message with no remoteMsgId and MAM message with remoteMsgId + return ((this.getRemoteMsgId() == null && message.getRemoteMsgId() != null) + || (this.getRemoteMsgId() != null && message.getRemoteMsgId() == null) + // both null is also acceptable + || (this.getRemoteMsgId() == null && message.getRemoteMsgId() == null)) + && this.getCounterpart().equals(message.getCounterpart()) + && body.equals(otherBody); } } } @@ -434,97 +426,16 @@ public class Message extends AbstractEntity { } } - public boolean isLastCorrectableMessage() { - Message next = next(); - while(next != null) { - if (next.isCorrectable()) { - return false; - } - next = next.next(); - } - return isCorrectable(); - } - - private boolean isCorrectable() { - return getStatus() != STATUS_RECEIVED && !isCarbon(); - } - - public boolean mergeable(final Message message) { - return message != null && - (message.getType() == Message.TYPE_TEXT && - this.getTransferable() == null && - message.getTransferable() == null && - message.getEncryption() != Message.ENCRYPTION_PGP && - message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED && - this.getType() == message.getType() && - //this.getStatus() == message.getStatus() && - isStatusMergeable(this.getStatus(), message.getStatus()) && - this.getEncryption() == message.getEncryption() && - this.getCounterpart() != null && - this.getCounterpart().equals(message.getCounterpart()) && - this.edited() == message.edited() && - (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && - !GeoHelper.isGeoUri(message.getBody()) && - !GeoHelper.isGeoUri(this.body) && - message.treatAsDownloadable() == Decision.NEVER && - this.treatAsDownloadable() == Decision.NEVER && - !message.getBody().startsWith(ME_COMMAND) && - !this.getBody().startsWith(ME_COMMAND) && - !this.bodyIsHeart() && - !message.bodyIsHeart() && - this.isTrusted() == message.isTrusted() - ); - } - - private static boolean isStatusMergeable(int a, int b) { - return a == b || ( - (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_UNSEND) - || (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_SEND) - || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND) - || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND_RECEIVED) - || (a == Message.STATUS_SEND && b == Message.STATUS_UNSEND) - || (a == Message.STATUS_SEND && b == Message.STATUS_SEND_RECEIVED) - ); - } - - public String getMergedBody() { - StringBuilder body = new StringBuilder(this.body.trim()); - Message current = this; - while(current.mergeable(current.next())) { - current = current.next(); - body.append(MERGE_SEPARATOR); - body.append(current.getBody().trim()); - } - return body.toString(); - } - public boolean hasMeCommand() { - return getMergedBody().startsWith(ME_COMMAND); + return getBody().startsWith(ME_COMMAND); } - public int getMergedStatus() { - int status = this.status; - Message current = this; - while(current.mergeable(current.next())) { - current = current.next(); - status = current.status; - } - return status; - } - - public long getMergedTimeSent() { - long time = this.timeSent; - Message current = this; - while(current.mergeable(current.next())) { - current = current.next(); - time = current.timeSent; + public String getBodyReplacedMeCommand(String replaceString) { + try { + return getBody().replaceAll("^" + Message.ME_COMMAND, replaceString + " "); + } catch (ArrayIndexOutOfBoundsException e) { + return getBody(); } - return time; - } - - public boolean wasMergedIntoPrevious() { - Message prev = this.prev(); - return prev != null && prev.mergeable(this); } public boolean trusted() { @@ -568,28 +479,33 @@ public class Message extends AbstractEntity { MUST, SHOULD, NEVER, + NOT_DECIDED, } - private static String extractRelevantExtension(URL url) { + private String extractRelevantExtension(URL url) { + if (url == null) { + return null; + } String path = url.getPath(); return extractRelevantExtension(path); } - private static String extractRelevantExtension(String path) { + private String extractRelevantExtension(String path) { if (path == null || path.isEmpty()) { return null; } String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); - int dotPosition = filename.lastIndexOf("."); - if (dotPosition != -1) { - String extension = filename.substring(dotPosition + 1); + final String lastPart = FileUtils.getLastExtension(filename); + + if (!lastPart.isEmpty()) { // we want the real file extension, not the crypto one - if (Transferable.VALID_CRYPTO_EXTENSIONS.contains(extension)) { - return extractRelevantExtension(filename.substring(0,dotPosition)); + final String secondToLastPart = FileUtils.getSecondToLastExtension(filename); + if (!secondToLastPart.isEmpty() && Transferable.VALID_CRYPTO_EXTENSIONS.contains(lastPart)) { + return secondToLastPart; } else { - return extension; + return lastPart; } } return null; @@ -605,53 +521,74 @@ public class Message extends AbstractEntity { } } else { try { - return MimeUtils.guessMimeTypeFromExtension(extractRelevantExtension(new URL(body.trim()))); + return MimeUtils.guessMimeTypeFromExtension(extractRelevantExtension(new URL(this.getBody()))); } catch (MalformedURLException e) { return null; } } } + /** + * in case of later found error with decision, set it to a value which does not affect anything, hopefully + */ + public void setNoDownloadable() { + mTreatAsDownloadAble = Decision.NEVER; + } + public Decision treatAsDownloadable() { - if (body.trim().contains(" ")) { - return Decision.NEVER; + // only test this ones, body will not change + if (mTreatAsDownloadAble != Decision.NOT_DECIDED) { + return mTreatAsDownloadAble; + } + /** + * there are a few cases where spaces result in an unwanted behavior, e.g. + * "http://example.com/image.jpg" text that will not be shown /abc.png" + * or more than one image link in one message. + */ + if (getBody().contains(" ")) { + mTreatAsDownloadAble = Decision.NEVER; + return mTreatAsDownloadAble; } try { URL url = new URL(body); if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { - return Decision.NEVER; + mTreatAsDownloadAble = Decision.NEVER; + return mTreatAsDownloadAble; } else if (oob) { - return Decision.MUST; + mTreatAsDownloadAble = Decision.MUST; + return mTreatAsDownloadAble; } String extension = extractRelevantExtension(url); if (extension == null) { - return Decision.NEVER; + mTreatAsDownloadAble = Decision.NEVER; + return mTreatAsDownloadAble; } String ref = url.getRef(); boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}"); if (encrypted) { if (MimeUtils.guessMimeTypeFromExtension(extension) != null) { - return Decision.MUST; + mTreatAsDownloadAble = Decision.MUST; + return mTreatAsDownloadAble; } else { - return Decision.NEVER; + mTreatAsDownloadAble = Decision.NEVER; + return mTreatAsDownloadAble; } } else if (Transferable.VALID_IMAGE_EXTENSIONS.contains(extension) || Transferable.WELL_KNOWN_EXTENSIONS.contains(extension)) { - return Decision.SHOULD; + mTreatAsDownloadAble = Decision.SHOULD; + return mTreatAsDownloadAble; } else { - return Decision.NEVER; + mTreatAsDownloadAble = Decision.NEVER; + return mTreatAsDownloadAble; } } catch (MalformedURLException e) { - return Decision.NEVER; + mTreatAsDownloadAble = Decision.NEVER; + return mTreatAsDownloadAble; } } - public boolean bodyIsHeart() { - return body != null && UIHelper.HEARTS.contains(body.trim()); - } - public FileParams getFileParams() { FileParams params = getLegacyFileParams(); if (params != null) { @@ -661,10 +598,10 @@ public class Message extends AbstractEntity { if (this.transferable != null) { params.size = this.transferable.getFileSize(); } - if (body == null) { + if (this.getBody() == null) { return params; } - String parts[] = body.split("\\|"); + String parts[] = this.getBody().split("\\|"); switch (parts.length) { case 1: try { @@ -723,10 +660,10 @@ public class Message extends AbstractEntity { public FileParams getLegacyFileParams() { FileParams params = new FileParams(); - if (body == null) { + if (this.getBody() == null) { return params; } - String parts[] = body.split(","); + String parts[] = this.getBody().split(","); if (parts.length == 3) { try { params.size = Long.parseLong(parts[0]); |