show p1s3 attchments with download button

This commit is contained in:
Daniel Gultsch 2018-05-25 13:18:25 +02:00
parent 70d95c7903
commit 4626bdf8d8
6 changed files with 45 additions and 22 deletions

View file

@ -123,9 +123,16 @@ public class MessageGenerator extends AbstractGenerator {
public MessagePacket generatePgpChat(Message message) { public MessagePacket generatePgpChat(Message message) {
MessagePacket packet = preparePacket(message); MessagePacket packet = preparePacket(message);
if (message.hasFileOnRemoteHost()) { if (message.hasFileOnRemoteHost()) {
final String url = message.getFileParams().url.toString(); Message.FileParams fileParams = message.getFileParams();
packet.setBody(url); final URL url = fileParams.url;
packet.addChild("x", Namespace.OOB).addChild("url").setContent(url); if (P1S3UrlStreamHandler.PROTOCOL_NAME.equals(url.getProtocol())) {
Element x = packet.addChild("x", Namespace.P1_S3_FILE_TRANSFER);
x.setAttribute("name", url.getFile());
x.setAttribute("fileid", url.getHost());
} else {
packet.setBody(url.toString());
packet.addChild("x", Namespace.OOB).addChild("url").setContent(url.toString());
}
} else { } else {
if (Config.supportUnencrypted()) { if (Config.supportUnencrypted()) {
packet.setBody(PGP_FALLBACK_MESSAGE); packet.setBody(PGP_FALLBACK_MESSAGE);

View file

@ -1,18 +1,14 @@
package eu.siacs.conversations.http; package eu.siacs.conversations.http;
import android.os.PowerManager; import android.os.PowerManager;
import android.renderscript.ScriptGroup;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import org.bouncycastle.jce.exception.ExtIOException;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -26,17 +22,12 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.AbstractConnectionManager;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.Checksum; import eu.siacs.conversations.utils.Checksum;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.WakeLockHelper; import eu.siacs.conversations.utils.WakeLockHelper;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import rocks.xmpp.addr.Jid;
public class HttpUploadConnection implements Transferable { public class HttpUploadConnection implements Transferable {
@ -50,15 +41,13 @@ public class HttpUploadConnection implements Transferable {
private final XmppConnectionService mXmppConnectionService; private final XmppConnectionService mXmppConnectionService;
private final SlotRequester mSlotRequester; private final SlotRequester mSlotRequester;
private final Method method; private final Method method;
private final boolean mUseTor;
private boolean canceled = false; private boolean canceled = false;
private boolean delayed = false; private boolean delayed = false;
private DownloadableFile file; private DownloadableFile file;
private Message message; private Message message;
private String mime; private String mime;
private SlotRequester.Slot slot; private SlotRequester.Slot slot;
private final boolean mUseTor;
private byte[] key = null; private byte[] key = null;
private long transmitted = 0; private long transmitted = 0;
@ -156,7 +145,6 @@ public class HttpUploadConnection implements Transferable {
public void success(SlotRequester.Slot slot) { public void success(SlotRequester.Slot slot) {
if (!canceled) { if (!canceled) {
HttpUploadConnection.this.slot = slot; HttpUploadConnection.this.slot = slot;
Log.d(Config.LOGTAG,"not starting upload to "+slot.getPutUrl());
new Thread(HttpUploadConnection.this::upload).start(); new Thread(HttpUploadConnection.this::upload).start();
} }
} }
@ -225,7 +213,11 @@ public class HttpUploadConnection implements Transferable {
Log.d(Config.LOGTAG, "finished uploading file"); Log.d(Config.LOGTAG, "finished uploading file");
final URL get; final URL get;
if (key != null) { if (key != null) {
get = CryptoHelper.toAesGcmUrl(new URL(slot.getGetUrl().toString() + "#" + CryptoHelper.bytesToHex(key))); if (method == Method.P1_S3) {
get = new URL(slot.getGetUrl().toString()+"#"+CryptoHelper.bytesToHex(key));
} else {
get = CryptoHelper.toAesGcmUrl(new URL(slot.getGetUrl().toString() + "#" + CryptoHelper.bytesToHex(key)));
}
} else { } else {
get = slot.getGetUrl(); get = slot.getGetUrl();
} }

View file

@ -29,12 +29,13 @@
package eu.siacs.conversations.http; package eu.siacs.conversations.http;
import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLStreamHandler; import java.net.URLStreamHandler;
import eu.siacs.conversations.xml.Element;
public class P1S3UrlStreamHandler extends URLStreamHandler { public class P1S3UrlStreamHandler extends URLStreamHandler {
public static final String PROTOCOL_NAME = "p1s3"; public static final String PROTOCOL_NAME = "p1s3";
@ -45,6 +46,17 @@ public class P1S3UrlStreamHandler extends URLStreamHandler {
} }
public static URL of(String fileId, String filename) throws MalformedURLException { public static URL of(String fileId, String filename) throws MalformedURLException {
if (fileId == null || filename == null) {
throw new MalformedURLException("Paramaters must not be null");
}
return new URL(PROTOCOL_NAME+"://" + fileId + "/" + filename); return new URL(PROTOCOL_NAME+"://" + fileId + "/" + filename);
} }
public static URL of(Element x) {
try {
return of(x.getAttribute("fileid"),x.getAttribute("name"));
} catch (MalformedURLException e) {
return null;
}
}
} }

View file

@ -3,6 +3,7 @@ package eu.siacs.conversations.parser;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import java.net.URL;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -27,6 +28,7 @@ import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.ReadByMarker; import eu.siacs.conversations.entities.ReadByMarker;
import eu.siacs.conversations.entities.ReceiptRequest; import eu.siacs.conversations.entities.ReceiptRequest;
import eu.siacs.conversations.http.HttpConnectionManager; import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.MessageArchiveService;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
@ -277,6 +279,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted"); final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted");
final Element replaceElement = packet.findChild("replace", "urn:xmpp:message-correct:0"); final Element replaceElement = packet.findChild("replace", "urn:xmpp:message-correct:0");
final Element oob = packet.findChild("x", Namespace.OOB); final Element oob = packet.findChild("x", Namespace.OOB);
final Element xP1S3 = packet.findChild("x", Namespace.P1_S3_FILE_TRANSFER);
final URL xP1S3url = xP1S3 == null ? null : P1S3UrlStreamHandler.of(xP1S3);
final String oobUrl = oob != null ? oob.findChildContent("url") : null; final String oobUrl = oob != null ? oob.findChildContent("url") : null;
final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id"); final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id");
final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX); final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX);
@ -324,7 +328,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
return; return;
} }
if ((body != null || pgpEncrypted != null || (axolotlEncrypted != null && axolotlEncrypted.hasChild("payload")) || oobUrl != null) && !isMucStatusMessage) { if ((body != null || pgpEncrypted != null || (axolotlEncrypted != null && axolotlEncrypted.hasChild("payload")) || oobUrl != null || xP1S3 != null) && !isMucStatusMessage) {
final boolean conversationIsProbablyMuc = isTypeGroupChat || mucUserElement != null || account.getXmppConnection().getMucServersWithholdAccount().contains(counterpart.getDomain()); final boolean conversationIsProbablyMuc = isTypeGroupChat || mucUserElement != null || account.getXmppConnection().getMucServersWithholdAccount().contains(counterpart.getDomain());
final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.asBareJid(), conversationIsProbablyMuc, false, query, false); final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.asBareJid(), conversationIsProbablyMuc, false, query, false);
final boolean conversationMultiMode = conversation.getMode() == Conversation.MODE_MULTI; final boolean conversationMultiMode = conversation.getMode() == Conversation.MODE_MULTI;
@ -362,7 +366,13 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
} }
} }
final Message message; final Message message;
if (pgpEncrypted != null && Config.supportOpenPgp()) { if (xP1S3url != null) {
message = new Message(conversation, xP1S3url.toString(), Message.ENCRYPTION_NONE, status);
message.setOob(true);
if (CryptoHelper.isPgpEncryptedUrl(xP1S3url.toString())) {
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
}
} else if (pgpEncrypted != null && Config.supportOpenPgp()) {
message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status); message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status);
} else if (axolotlEncrypted != null && Config.supportOmemo()) { } else if (axolotlEncrypted != null && Config.supportOmemo()) {
Jid origin; Jid origin;

View file

@ -276,6 +276,6 @@ public final class CryptoHelper {
return false; return false;
} }
final String u = url.toLowerCase(); final String u = url.toLowerCase();
return !u.contains(" ") && (u.startsWith("https://") || u.startsWith("http://")) && u.endsWith(".pgp"); return !u.contains(" ") && (u.startsWith("https://") || u.startsWith("http://") || u.startsWith("p1s3://")) && u.endsWith(".pgp");
} }
} }

View file

@ -35,6 +35,7 @@ import java.util.regex.Pattern;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.http.AesGcmURLStreamHandler; import eu.siacs.conversations.http.AesGcmURLStreamHandler;
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
public class MessageUtils { public class MessageUtils {
@ -79,7 +80,8 @@ public class MessageUtils {
final boolean encrypted = ref != null && AesGcmURLStreamHandler.IV_KEY.matcher(ref).matches(); final boolean encrypted = ref != null && AesGcmURLStreamHandler.IV_KEY.matcher(ref).matches();
final boolean followedByDataUri = lines.length == 2 && lines[1].startsWith("data:"); final boolean followedByDataUri = lines.length == 2 && lines[1].startsWith("data:");
final boolean validAesGcm = AesGcmURLStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted && (lines.length == 1 || followedByDataUri); final boolean validAesGcm = AesGcmURLStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted && (lines.length == 1 || followedByDataUri);
final boolean validOob = ("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) && (oob || encrypted) && lines.length == 1; final boolean validProtocol = "http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol) || P1S3UrlStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol);
final boolean validOob = validProtocol && (oob || encrypted) && lines.length == 1;
return validAesGcm || validOob; return validAesGcm || validOob;
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
return false; return false;