aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/entities/Message.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/entities/Message.java')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/entities/Message.java223
1 files changed, 151 insertions, 72 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/entities/Message.java b/src/main/java/de/thedevstack/conversationsplus/entities/Message.java
index cd7556b3..68b47578 100644
--- a/src/main/java/de/thedevstack/conversationsplus/entities/Message.java
+++ b/src/main/java/de/thedevstack/conversationsplus/entities/Message.java
@@ -9,6 +9,8 @@ import java.util.Arrays;
import de.thedevstack.conversationsplus.Config;
import de.thedevstack.conversationsplus.utils.GeoHelper;
+import de.thedevstack.conversationsplus.utils.MimeUtils;
+import de.thedevstack.conversationsplus.utils.UIHelper;
import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException;
import de.thedevstack.conversationsplus.xmpp.jid.Jid;
@@ -16,6 +18,8 @@ public class Message extends AbstractEntity {
public static final String TABLENAME = "messages";
+ public static final String MERGE_SEPARATOR = " \u200B\n\n";
+
public static final int STATUS_RECEIVED = 0;
public static final int STATUS_UNSEND = 1;
public static final int STATUS_SEND = 2;
@@ -66,7 +70,7 @@ public class Message extends AbstractEntity {
protected String remoteMsgId = null;
protected String serverMsgId = null;
protected Conversation conversation = null;
- protected Downloadable downloadable = null;
+ protected Transferable transferable = null;
private Message mNextMessage = null;
private Message mPreviousMessage = null;
@@ -304,12 +308,12 @@ public class Message extends AbstractEntity {
this.trueCounterpart = trueCounterpart;
}
- public Downloadable getDownloadable() {
- return this.downloadable;
+ public Transferable getTransferable() {
+ return this.transferable;
}
- public void setDownloadable(Downloadable downloadable) {
- this.downloadable = downloadable;
+ public void setTransferable(Transferable transferable) {
+ this.transferable = transferable;
}
public boolean equals(Message message) {
@@ -317,15 +321,25 @@ public class Message extends AbstractEntity {
return this.serverMsgId.equals(message.getServerMsgId());
} else if (this.body == null || this.counterpart == null) {
return false;
- } else if (message.getRemoteMsgId() != null) {
+ } else {
+ String body, otherBody;
+ if (this.hasFileOnRemoteHost()) {
+ body = getFileParams().url.toString();
+ otherBody = message.body == null ? null : message.body.trim();
+ } else {
+ body = this.body;
+ otherBody = message.body;
+ }
+ if (message.getRemoteMsgId() != null) {
return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid))
&& this.counterpart.equals(message.getCounterpart())
- && this.body.equals(message.getBody());
+ && body.equals(otherBody);
} else {
return this.remoteMsgId == null
&& this.counterpart.equals(message.getCounterpart())
- && this.body.equals(message.getBody())
- && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.PING_TIMEOUT * 500;
+ && body.equals(otherBody)
+ && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000;
+ }
}
}
@@ -360,8 +374,8 @@ public class Message extends AbstractEntity {
public boolean mergeable(final Message message) {
return message != null &&
(message.getType() == Message.TYPE_TEXT &&
- this.getDownloadable() == null &&
- message.getDownloadable() == null &&
+ this.getTransferable() == null &&
+ message.getTransferable() == null &&
message.getEncryption() != Message.ENCRYPTION_PGP &&
this.getType() == message.getType() &&
//this.getStatus() == message.getStatus() &&
@@ -372,10 +386,12 @@ public class Message extends AbstractEntity {
(message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) &&
!GeoHelper.isGeoUri(message.getBody()) &&
!GeoHelper.isGeoUri(this.body) &&
- !message.bodyContainsDownloadable() &&
- !this.bodyContainsDownloadable() &&
+ message.treatAsDownloadable() == Decision.NEVER &&
+ this.treatAsDownloadable() == Decision.NEVER &&
!message.getBody().startsWith(ME_COMMAND) &&
- !this.getBody().startsWith(ME_COMMAND)
+ !this.getBody().startsWith(ME_COMMAND) &&
+ !this.bodyIsHeart() &&
+ !message.bodyIsHeart()
);
}
@@ -393,7 +409,7 @@ public class Message extends AbstractEntity {
public String getMergedBody() {
final Message next = this.next();
if (this.mergeable(next)) {
- return getBody() + '\n' + next.getMergedBody();
+ return getBody() + MERGE_SEPARATOR + next.getMergedBody();
}
return getBody();
}
@@ -429,119 +445,175 @@ public class Message extends AbstractEntity {
return (status > STATUS_RECEIVED || (contact != null && contact.trusted()));
}
- public boolean bodyContainsDownloadable() {
- /**
- * there are a few cases where spaces result in an unwanted behavior, e.g.
- * "http://upload.mitsu-freunde-bw.de/uploads/2015/03/i43b4bpr8.png /abc.png"
- * or more than one image link in one message.
- */
- if (body.contains(" ")) {
+ public boolean fixCounterpart() {
+ Presences presences = conversation.getContact().getPresences();
+ if (counterpart != null && presences.has(counterpart.getResourcepart())) {
+ return true;
+ } else if (presences.size() >= 1) {
+ try {
+ counterpart = Jid.fromParts(conversation.getJid().getLocalpart(),
+ conversation.getJid().getDomainpart(),
+ presences.asStringArray()[0]);
+ return true;
+ } catch (InvalidJidException e) {
+ counterpart = null;
return false;
}
- try {
- URL url = new URL(body);
- if (!url.getProtocol().equalsIgnoreCase("http")
- && !url.getProtocol().equalsIgnoreCase("https")) {
+ } else {
+ counterpart = null;
return false;
}
+ }
- String sUrlPath = url.getPath();
- if (sUrlPath == null || sUrlPath.isEmpty()) {
- return false;
+ public enum Decision {
+ MUST,
+ SHOULD,
+ NEVER,
}
- int iSlashIndex = sUrlPath.lastIndexOf('/') + 1;
+ private static String extractRelevantExtension(URL url) {
+ String path = url.getPath();
+ if (path == null || path.isEmpty()) {
+ return null;
+ }
+ String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase();
+ String[] extensionParts = filename.split("\\.");
+ if (extensionParts.length == 2) {
+ return extensionParts[extensionParts.length - 1];
+ } else if (extensionParts.length == 3 && Arrays
+ .asList(Transferable.VALID_CRYPTO_EXTENSIONS)
+ .contains(extensionParts[extensionParts.length - 1])) {
+ return extensionParts[extensionParts.length -2];
+ }
+ return null;
+ }
- String sLastUrlPath = sUrlPath.substring(iSlashIndex).toLowerCase();
+ public String getMimeType() {
+ if (relativeFilePath != null) {
+ int start = relativeFilePath.lastIndexOf('.') + 1;
+ if (start < relativeFilePath.length()) {
+ return MimeUtils.guessMimeTypeFromExtension(relativeFilePath.substring(start));
+ } else {
+ return null;
+ }
+ } else {
+ try {
+ return MimeUtils.guessMimeTypeFromExtension(extractRelevantExtension(new URL(body.trim())));
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+ }
- String[] extensionParts = sLastUrlPath.split("\\.");
- if (extensionParts.length == 2
- && Arrays.asList(Downloadable.VALID_IMAGE_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_IMAGE_EXTENSIONS).contains(
- extensionParts[extensionParts.length - 2])) {
- return true;
+ public Decision treatAsDownloadable() {
+ if (body.trim().contains(" ")) {
+ return Decision.NEVER;
+ }
+ try {
+ URL url = new URL(body);
+ if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) {
+ return Decision.NEVER;
+ }
+ String extension = extractRelevantExtension(url);
+ if (extension == null) {
+ return Decision.NEVER;
+ }
+ 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;
} else {
- return false;
+ return Decision.NEVER;
}
+ } else if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)
+ || Arrays.asList(Transferable.WELL_KNOWN_EXTENSIONS).contains(extension)) {
+ return Decision.SHOULD;
+ } else {
+ return Decision.NEVER;
+ }
+
} catch (MalformedURLException e) {
- return false;
+ return Decision.NEVER;
+ }
}
+
+ public boolean bodyIsHeart() {
+ return body != null && UIHelper.HEARTS.contains(body.trim());
}
- public ImageParams getImageParams() {
- ImageParams params = getLegacyImageParams();
+ public FileParams getFileParams() {
+ FileParams params = getLegacyFileParams();
if (params != null) {
return params;
}
- params = new ImageParams();
- if (this.downloadable != null) {
- params.size = this.downloadable.getFileSize();
+ params = new FileParams();
+ if (this.transferable != null) {
+ params.size = this.transferable.getFileSize();
}
if (body == null) {
return params;
}
String parts[] = body.split("\\|");
- if (parts.length == 1) {
+ switch (parts.length) {
+ case 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) {
+ break;
+ case 2:
+ case 4:
try {
- params.size = Long.parseLong(parts[0]);
+ 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[1]);
- } catch (NumberFormatException e) {
+ params.width = Integer.parseInt(parts[2]);
+ } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
params.width = 0;
}
try {
- params.height = Integer.parseInt(parts[2]);
- } catch (NumberFormatException e) {
+ params.height = Integer.parseInt(parts[3]);
+ } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
params.height = 0;
}
- } else if (parts.length == 4) {
- params.origin = parts[0];
+ break;
+ case 3:
try {
- params.url = new URL(parts[0]);
- } catch (MalformedURLException e1) {
- params.url = null;
- }
- try {
- params.size = Long.parseLong(parts[1]);
+ params.size = Long.parseLong(parts[0]);
} catch (NumberFormatException e) {
params.size = 0;
}
try {
- params.width = Integer.parseInt(parts[2]);
+ params.width = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
params.width = 0;
}
try {
- params.height = Integer.parseInt(parts[3]);
+ params.height = Integer.parseInt(parts[2]);
} catch (NumberFormatException e) {
params.height = 0;
}
+ break;
}
return params;
}
- public ImageParams getLegacyImageParams() {
- ImageParams params = new ImageParams();
+ public FileParams getLegacyFileParams() {
+ FileParams params = new FileParams();
if (body == null) {
return params;
}
@@ -577,11 +649,18 @@ public class Message extends AbstractEntity {
return type == TYPE_FILE || type == TYPE_IMAGE;
}
- public class ImageParams {
+ public boolean hasFileOnRemoteHost() {
+ return isFileOrImage() && getFileParams().url != null;
+ }
+
+ public boolean needsUploading() {
+ return isFileOrImage() && getFileParams().url == null;
+ }
+
+ public class FileParams {
public URL url;
public long size = 0;
public int width = 0;
public int height = 0;
- public String origin;
}
}