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 | 137 |
1 files changed, 111 insertions, 26 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index d04dff87..8d0571a4 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -8,6 +8,7 @@ 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.MimeUtils; import eu.siacs.conversations.utils.UIHelper; @@ -34,6 +35,7 @@ public class Message extends AbstractEntity { public static final int ENCRYPTION_OTR = 2; public static final int ENCRYPTION_DECRYPTED = 3; public static final int ENCRYPTION_DECRYPTION_FAILED = 4; + public static final int ENCRYPTION_AXOLOTL = 5; public static final int TYPE_TEXT = 0; public static final int TYPE_IMAGE = 1; @@ -49,9 +51,12 @@ public class Message extends AbstractEntity { public static final String ENCRYPTION = "encryption"; public static final String STATUS = "status"; public static final String TYPE = "type"; + public static final String CARBON = "carbon"; public static final String REMOTE_MSG_ID = "remoteMsgId"; public static final String SERVER_MSG_ID = "serverMsgId"; public static final String RELATIVE_FILE_PATH = "relativeFilePath"; + public static final String FINGERPRINT = "axolotl_fingerprint"; + public static final String READ = "read"; public static final String ME_COMMAND = "/me "; @@ -59,12 +64,13 @@ public class Message extends AbstractEntity { protected String conversationUuid; protected Jid counterpart; protected Jid trueCounterpart; - private String body; + protected String body; protected String encryptedBody; protected long timeSent; protected int encryption; protected int status; protected int type; + protected boolean carbon = false; protected String relativeFilePath; protected boolean read = true; protected String remoteMsgId = null; @@ -73,6 +79,7 @@ public class Message extends AbstractEntity { protected Transferable transferable = null; private Message mNextMessage = null; private Message mPreviousMessage = null; + private String axolotlFingerprint = null; private Message() { @@ -92,16 +99,20 @@ public class Message extends AbstractEntity { encryption, status, TYPE_TEXT, + false, null, null, - null); + null, + null, + true); this.conversation = conversation; } private Message(final String uuid, final String conversationUUid, final Jid counterpart, final Jid trueCounterpart, final String body, final long timeSent, - final int encryption, final int status, final int type, final String remoteMsgId, - final String relativeFilePath, final String serverMsgId) { + final int encryption, final int status, final int type, final boolean carbon, + final String remoteMsgId, final String relativeFilePath, + final String serverMsgId, final String fingerprint, final boolean read) { this.uuid = uuid; this.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -111,9 +122,12 @@ public class Message extends AbstractEntity { this.encryption = encryption; this.status = status; this.type = type; + this.carbon = carbon; this.remoteMsgId = remoteMsgId; this.relativeFilePath = relativeFilePath; this.serverMsgId = serverMsgId; + this.axolotlFingerprint = fingerprint; + this.read = read; } public static Message fromCursor(Cursor cursor) { @@ -148,13 +162,16 @@ public class Message extends AbstractEntity { cursor.getInt(cursor.getColumnIndex(ENCRYPTION)), cursor.getInt(cursor.getColumnIndex(STATUS)), cursor.getInt(cursor.getColumnIndex(TYPE)), + cursor.getInt(cursor.getColumnIndex(CARBON))>0, cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)), cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)), - cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID))); + cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)), + cursor.getString(cursor.getColumnIndex(FINGERPRINT)), + cursor.getInt(cursor.getColumnIndex(READ)) > 0); } public static Message createStatusMessage(Conversation conversation, String body) { - Message message = new Message(); + final Message message = new Message(); message.setType(Message.TYPE_STATUS); message.setConversation(conversation); message.setBody(body); @@ -181,9 +198,12 @@ public class Message extends AbstractEntity { values.put(ENCRYPTION, encryption); values.put(STATUS, status); values.put(TYPE, type); + values.put(CARBON, carbon ? 1 : 0); values.put(REMOTE_MSG_ID, remoteMsgId); values.put(RELATIVE_FILE_PATH, relativeFilePath); values.put(SERVER_MSG_ID, serverMsgId); + values.put(FINGERPRINT, axolotlFingerprint); + values.put(READ,read); return values; } @@ -304,6 +324,14 @@ public class Message extends AbstractEntity { this.type = type; } + public boolean isCarbon() { + return carbon; + } + + public void setCarbon(boolean carbon) { + this.carbon = carbon; + } + public void setTrueCounterpart(Jid trueCounterpart) { this.trueCounterpart = trueCounterpart; } @@ -333,7 +361,9 @@ public class Message extends AbstractEntity { if (message.getRemoteMsgId() != null) { return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) && this.counterpart.equals(message.getCounterpart()) - && body.equals(otherBody); + && (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()) @@ -390,6 +420,7 @@ public class Message extends AbstractEntity { this.treatAsDownloadable() == Decision.NEVER && !message.getBody().startsWith(ME_COMMAND) && !this.getBody().startsWith(ME_COMMAND) + this.isTrusted() == message.isTrusted() ); } @@ -405,11 +436,14 @@ public class Message extends AbstractEntity { } public String getMergedBody() { - final Message next = this.next(); - if (this.mergeable(next)) { - return getBody() + MERGE_SEPARATOR + next.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()); } - return getBody(); + return body.toString(); } public boolean hasMeCommand() { @@ -417,20 +451,23 @@ public class Message extends AbstractEntity { } public int getMergedStatus() { - final Message next = this.next(); - if (this.mergeable(next)) { - return next.getStatus(); + int status = this.status; + Message current = this; + while(current.mergeable(current.next())) { + current = current.next(); + status = current.status; } - return getStatus(); + return status; } public long getMergedTimeSent() { - Message next = this.next(); - if (this.mergeable(next)) { - return next.getMergedTimeSent(); - } else { - return getTimeSent(); + long time = this.timeSent; + Message current = this; + while(current.mergeable(current.next())) { + current = current.next(); + time = current.timeSent; } + return time; } public boolean wasMergedIntoPrevious() { @@ -478,18 +515,15 @@ public class Message extends AbstractEntity { if (path == null || path.isEmpty()) { return null; } - + String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); - int dotPosition = filename.lastIndexOf("."); - if (dotPosition != -1) - { + if (dotPosition != -1) { String extension = filename.substring(dotPosition + 1); - // we want the real file extension, not the crypto one if (Arrays.asList(Transferable.VALID_CRYPTO_EXTENSIONS).contains(extension)) { - return extractRelevantExtension(path.substring(0,dotPosition)); + return extractRelevantExtension(filename.substring(0,dotPosition)); } else { return extension; } @@ -673,4 +707,55 @@ public class Message extends AbstractEntity { public int width = 0; public int height = 0; } + + public void setAxolotlFingerprint(String fingerprint) { + this.axolotlFingerprint = fingerprint; + } + + public String getAxolotlFingerprint() { + return axolotlFingerprint; + } + + public boolean isTrusted() { + XmppAxolotlSession.Trust t = conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint); + return t != null && t.trusted(); + } + + private int getPreviousEncryption() { + for (Message iterator = this.prev(); iterator != null; iterator = iterator.prev()){ + if( iterator.isCarbon() || iterator.getStatus() == STATUS_RECEIVED ) { + continue; + } + return iterator.getEncryption(); + } + return ENCRYPTION_NONE; + } + + private int getNextEncryption() { + for (Message iterator = this.next(); iterator != null; iterator = iterator.next()){ + if( iterator.isCarbon() || iterator.getStatus() == STATUS_RECEIVED ) { + continue; + } + return iterator.getEncryption(); + } + return conversation.getNextEncryption(); + } + + public boolean isValidInSession() { + int pastEncryption = getCleanedEncryption(this.getPreviousEncryption()); + int futureEncryption = getCleanedEncryption(this.getNextEncryption()); + + boolean inUnencryptedSession = pastEncryption == ENCRYPTION_NONE + || futureEncryption == ENCRYPTION_NONE + || pastEncryption != futureEncryption; + + return inUnencryptedSession || getCleanedEncryption(this.getEncryption()) == pastEncryption; + } + + private static int getCleanedEncryption(int encryption) { + if (encryption == ENCRYPTION_DECRYPTED || encryption == ENCRYPTION_DECRYPTION_FAILED) { + return ENCRYPTION_PGP; + } + return encryption; + } } |