From faa7320dd538ec7acd900613491abe33864bdb8b Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 4 Oct 2022 14:25:22 -0500 Subject: [PATCH] Reply to requests for BOB data --- .../com/cheogram/android/BobTransfer.java | 5 ++- .../conversations/generator/IqGenerator.java | 43 ++++++++++++++++++- .../siacs/conversations/parser/IqParser.java | 7 ++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/cheogram/java/com/cheogram/android/BobTransfer.java b/src/cheogram/java/com/cheogram/android/BobTransfer.java index cbe30a302674891129c61620f970d0cb215d2625..11ef425c9e860907fd59ddb5f60fcb0dfcb5475c 100644 --- a/src/cheogram/java/com/cheogram/android/BobTransfer.java +++ b/src/cheogram/java/com/cheogram/android/BobTransfer.java @@ -37,7 +37,10 @@ public class BobTransfer implements Transferable { public static Cid cid(URI uri) { if (!uri.getScheme().equals("cid")) return null; - String bobCid = uri.getSchemeSpecificPart(); + return cid(uri.getSchemeSpecificPart()); + } + + public static Cid cid(String bobCid) { if (!bobCid.contains("@") || !bobCid.contains("+")) return null; String[] cidParts = bobCid.split("@")[0].split("\\+"); try { diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index ed831d784628f43e6d38ef0ce4d72d915b15a668..c6b0d04cee2684e980db5036e9b300e2357992ed 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -1,15 +1,22 @@ package eu.siacs.conversations.generator; - import android.os.Bundle; import android.util.Base64; +import android.util.Base64OutputStream; import android.util.Log; +import com.cheogram.android.BobTransfer; + +import com.google.common.io.ByteStreams; + import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.ecc.ECPublicKey; import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyRecord; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; @@ -20,6 +27,8 @@ import java.util.Set; import java.util.TimeZone; import java.util.UUID; +import io.ipfs.cid.Cid; + import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; @@ -569,4 +578,36 @@ public class IqGenerator extends AbstractGenerator { packet.addChild("query",Namespace.DISCO_INFO); return packet; } + + public IqPacket bobResponse(IqPacket request) { + try { + String bobCid = request.findChild("data", "urn:xmpp:bob").getAttribute("cid"); + Cid cid = BobTransfer.cid(bobCid); + DownloadableFile f = mXmppConnectionService.getFileForCid(cid); + if (f == null || !f.canRead()) { + throw new IOException("No such file"); + } else if (f.getSize() > 129000) { + final IqPacket response = request.generateResponse(IqPacket.TYPE.ERROR); + final Element error = response.addChild("error"); + error.setAttribute("type", "cancel"); + error.addChild("policy-violation", "urn:ietf:params:xml:ns:xmpp-stanzas"); + return response; + } else { + final IqPacket response = request.generateResponse(IqPacket.TYPE.RESULT); + final Element data = response.addChild("data", "urn:xmpp:bob"); + data.setAttribute("cid", bobCid); + data.setAttribute("type", f.getMimeType()); + ByteArrayOutputStream b64 = new ByteArrayOutputStream((int) f.getSize() * 2); + ByteStreams.copy(new FileInputStream(f), new Base64OutputStream(b64, Base64.NO_WRAP)); + data.setContent(b64.toString("utf-8")); + return response; + } + } catch (final IOException | IllegalStateException e) { + final IqPacket response = request.generateResponse(IqPacket.TYPE.ERROR); + final Element error = response.addChild("error"); + error.setAttribute("type", "cancel"); + error.addChild("item-not-found", "urn:ietf:params:xml:ns:xmpp-stanzas"); + return response; + } + } } diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index d02d69ddca3e6fbba2086a12a03162102f6b1a62..23e1df85b9c7f622797337e5af42a2575f44ebd5 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -31,6 +31,7 @@ import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Room; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; @@ -453,7 +454,11 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { } mXmppConnectionService.sendIqPacket(account, response, null); } else { - if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) { + final Contact contact = account.getRoster().getContact(packet.getFrom()); + final Conversation conversation = mXmppConnectionService.find(account, packet.getFrom()); + if (packet.hasChild("data", "urn:xmpp:bob") && isGet && (conversation == null ? contact != null && contact.canInferPresence() : conversation.canInferPresence())) { + mXmppConnectionService.sendIqPacket(account, mXmppConnectionService.getIqGenerator().bobResponse(packet), null); + } else if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) { final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); final Element error = response.addChild("error"); error.setAttribute("type", "cancel");