Change summary
src/cheogram/java/com/cheogram/android/BobTransfer.java | 5
src/main/java/eu/siacs/conversations/generator/IqGenerator.java | 43 ++
src/main/java/eu/siacs/conversations/parser/IqParser.java | 7
3 files changed, 52 insertions(+), 3 deletions(-)
Detailed changes
@@ -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 {
@@ -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;
+ }
+ }
}
@@ -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");