aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs/conversations/xmpp
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2016-07-29 19:52:37 +0200
committerChristian Schneppe <christian@pix-art.de>2016-07-29 19:52:37 +0200
commit94933e21cd08c53a23e5ec6c12bc1dc383b1f3ce (patch)
tree4fa096547d0917f603252c9a279e4208ba4ef711 /src/main/java/eu/siacs/conversations/xmpp
parent50889004f3c679387d95ba9c49a53a8f882ba33c (diff)
changed package id inside manifest and project
Diffstat (limited to 'src/main/java/eu/siacs/conversations/xmpp')
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnBindListener.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnContactStatusChanged.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnIqPacketReceived.java8
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnKeyStatusUpdated.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java8
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnNewKeysAvailable.java0
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java8
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnStatusChanged.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/OnUpdateBlocklist.java13
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/PacketReceived.java5
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java1647
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java32
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/forms/Data.java99
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/forms/Field.java81
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java49
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java226
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java147
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java1076
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java171
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java239
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java210
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleTransport.java15
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java9
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java9
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/OnPrimaryCandidateFound.java5
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/OnTransportConnected.java7
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java129
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java96
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java13
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java102
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractAcknowledgeableStanza.java31
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java50
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java69
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java99
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java8
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java10
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java10
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java13
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java13
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java12
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java14
43 files changed, 0 insertions, 4775 deletions
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java b/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java
deleted file mode 100644
index e45eba73e..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnAdvancedStreamFeaturesLoaded.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-
-public interface OnAdvancedStreamFeaturesLoaded {
- public void onAdvancedStreamFeaturesAvailable(final Account account);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnBindListener.java b/src/main/java/eu/siacs/conversations/xmpp/OnBindListener.java
deleted file mode 100644
index f09cf33dd..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnBindListener.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-
-public interface OnBindListener {
- public void onBind(Account account);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnContactStatusChanged.java b/src/main/java/eu/siacs/conversations/xmpp/OnContactStatusChanged.java
deleted file mode 100644
index 20b17f021..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnContactStatusChanged.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Contact;
-
-public interface OnContactStatusChanged {
- public void onContactStatusChanged(final Contact contact, final boolean online);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnIqPacketReceived.java b/src/main/java/eu/siacs/conversations/xmpp/OnIqPacketReceived.java
deleted file mode 100644
index a4cff9863..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnIqPacketReceived.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-
-public interface OnIqPacketReceived extends PacketReceived {
- public void onIqPacketReceived(Account account, IqPacket packet);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnKeyStatusUpdated.java b/src/main/java/eu/siacs/conversations/xmpp/OnKeyStatusUpdated.java
deleted file mode 100644
index e7fc582e4..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnKeyStatusUpdated.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.crypto.axolotl.AxolotlService;
-
-public interface OnKeyStatusUpdated {
- public void onKeyStatusUpdated(AxolotlService.FetchStatus report);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java b/src/main/java/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java
deleted file mode 100644
index 5f670d933..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-
-public interface OnMessageAcknowledged {
- public void onMessageAcknowledged(Account account, String id);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java b/src/main/java/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java
deleted file mode 100644
index 325e945f0..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
-
-public interface OnMessagePacketReceived extends PacketReceived {
- public void onMessagePacketReceived(Account account, MessagePacket packet);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnNewKeysAvailable.java b/src/main/java/eu/siacs/conversations/xmpp/OnNewKeysAvailable.java
deleted file mode 100644
index e69de29bb..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnNewKeysAvailable.java
+++ /dev/null
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java b/src/main/java/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java
deleted file mode 100644
index 95c1acfcc..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
-
-public interface OnPresencePacketReceived extends PacketReceived {
- public void onPresencePacketReceived(Account account, PresencePacket packet);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnStatusChanged.java b/src/main/java/eu/siacs/conversations/xmpp/OnStatusChanged.java
deleted file mode 100644
index ad1d98cb9..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnStatusChanged.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import eu.siacs.conversations.entities.Account;
-
-public interface OnStatusChanged {
- public void onStatusChanged(Account account);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/OnUpdateBlocklist.java b/src/main/java/eu/siacs/conversations/xmpp/OnUpdateBlocklist.java
deleted file mode 100644
index 92e72cfa8..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/OnUpdateBlocklist.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-public interface OnUpdateBlocklist {
- // Use an enum instead of a boolean to make sure we don't run into the boolean trap
- // (`onUpdateBlocklist(true)' doesn't read well, and could be confusing).
- public static enum Status {
- BLOCKED,
- UNBLOCKED
- }
-
- @SuppressWarnings("MethodNameSameAsClassName")
- public void OnUpdateBlocklist(final Status status);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/PacketReceived.java b/src/main/java/eu/siacs/conversations/xmpp/PacketReceived.java
deleted file mode 100644
index d4502d734..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/PacketReceived.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-public abstract interface PacketReceived {
-
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
deleted file mode 100644
index fec96969b..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ /dev/null
@@ -1,1647 +0,0 @@
-package eu.siacs.conversations.xmpp;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.os.SystemClock;
-import android.security.KeyChain;
-import android.util.Base64;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.ConnectException;
-import java.net.IDN;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-
-import de.duenndns.ssl.MemorizingTrustManager;
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.crypto.XmppDomainVerifier;
-import eu.siacs.conversations.crypto.sasl.DigestMd5;
-import eu.siacs.conversations.crypto.sasl.External;
-import eu.siacs.conversations.crypto.sasl.Plain;
-import eu.siacs.conversations.crypto.sasl.SaslMechanism;
-import eu.siacs.conversations.crypto.sasl.ScramSha1;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.entities.ServiceDiscoveryResult;
-import eu.siacs.conversations.generator.IqGenerator;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.utils.DNSHelper;
-import eu.siacs.conversations.utils.SSLSocketHelper;
-import eu.siacs.conversations.utils.SocksSocketFactory;
-import eu.siacs.conversations.utils.Xmlns;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xml.Tag;
-import eu.siacs.conversations.xml.TagWriter;
-import eu.siacs.conversations.xml.XmlReader;
-import eu.siacs.conversations.xmpp.forms.Data;
-import eu.siacs.conversations.xmpp.forms.Field;
-import eu.siacs.conversations.xmpp.jid.InvalidJidException;
-import eu.siacs.conversations.xmpp.jid.Jid;
-import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
-import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
-import eu.siacs.conversations.xmpp.stanzas.AbstractAcknowledgeableStanza;
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
-import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
-import eu.siacs.conversations.xmpp.stanzas.csi.ActivePacket;
-import eu.siacs.conversations.xmpp.stanzas.csi.InactivePacket;
-import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket;
-import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket;
-import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket;
-import eu.siacs.conversations.xmpp.stanzas.streammgmt.ResumePacket;
-
-public class XmppConnection implements Runnable {
-
- private static final int PACKET_IQ = 0;
- private static final int PACKET_MESSAGE = 1;
- private static final int PACKET_PRESENCE = 2;
- protected Account account;
- private final WakeLock wakeLock;
- private Socket socket;
- private XmlReader tagReader;
- private TagWriter tagWriter;
- private final Features features = new Features(this);
- private boolean needsBinding = true;
- private boolean shouldAuthenticate = true;
- private Element streamFeatures;
- private final HashMap<Jid, ServiceDiscoveryResult> disco = new HashMap<>();
-
- private String streamId = null;
- private int smVersion = 3;
- private final SparseArray<AbstractAcknowledgeableStanza> mStanzaQueue = new SparseArray<>();
-
- private int stanzasReceived = 0;
- private int stanzasSent = 0;
- private long lastPacketReceived = 0;
- private long lastPingSent = 0;
- private long lastConnect = 0;
- private long lastSessionStarted = 0;
- private long lastDiscoStarted = 0;
- private AtomicInteger mPendingServiceDiscoveries = new AtomicInteger(0);
- private AtomicBoolean mWaitForDisco = new AtomicBoolean(true);
- private boolean mInteractive = false;
- private int attempt = 0;
- private final Hashtable<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>();
- private OnPresencePacketReceived presenceListener = null;
- private OnJinglePacketReceived jingleListener = null;
- private OnIqPacketReceived unregisteredIqListener = null;
- private OnMessagePacketReceived messageListener = null;
- private OnStatusChanged statusListener = null;
- private OnBindListener bindListener = null;
- private final ArrayList<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new ArrayList<>();
- private OnMessageAcknowledged acknowledgedListener = null;
- private XmppConnectionService mXmppConnectionService = null;
-
- private SaslMechanism saslMechanism;
-
- private X509KeyManager mKeyManager = new X509KeyManager() {
- @Override
- public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
- return account.getPrivateKeyAlias();
- }
-
- @Override
- public String chooseServerAlias(String s, Principal[] principals, Socket socket) {
- return null;
- }
-
- @Override
- public X509Certificate[] getCertificateChain(String alias) {
- try {
- return KeyChain.getCertificateChain(mXmppConnectionService, alias);
- } catch (Exception e) {
- return new X509Certificate[0];
- }
- }
-
- @Override
- public String[] getClientAliases(String s, Principal[] principals) {
- return new String[0];
- }
-
- @Override
- public String[] getServerAliases(String s, Principal[] principals) {
- return new String[0];
- }
-
- @Override
- public PrivateKey getPrivateKey(String alias) {
- try {
- return KeyChain.getPrivateKey(mXmppConnectionService, alias);
- } catch (Exception e) {
- return null;
- }
- }
- };
- private Identity mServerIdentity = Identity.UNKNOWN;
-
- public final OnIqPacketReceived registrationResponseListener = new OnIqPacketReceived() {
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- if (packet.getType() == IqPacket.TYPE.RESULT) {
- account.setOption(Account.OPTION_REGISTER, false);
- forceCloseSocket();
- changeStatus(Account.State.REGISTRATION_SUCCESSFUL);
- } else {
- final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList(
- "The password is too weak",
- "Please use a longer password.");
- Element error = packet.findChild("error");
- Account.State state = Account.State.REGISTRATION_FAILED;
- if (error != null) {
- if (error.hasChild("conflict")) {
- state = Account.State.REGISTRATION_CONFLICT;
- } else if (error.hasChild("resource-constraint")
- && "wait".equals(error.getAttribute("type"))) {
- state = Account.State.REGISTRATION_PLEASE_WAIT;
- } else if (error.hasChild("not-acceptable")
- && PASSWORD_TOO_WEAK_MSGS.contains(error.findChildContent("text"))) {
- state = Account.State.REGISTRATION_PASSWORD_TOO_WEAK;
- }
- }
- changeStatus(state);
- forceCloseSocket();
- }
- }
- };
-
- public XmppConnection(final Account account, final XmppConnectionService service) {
- this.account = account;
- this.wakeLock = service.getPowerManager().newWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, account.getJid().toBareJid().toString());
- tagWriter = new TagWriter();
- mXmppConnectionService = service;
- }
-
- protected void changeStatus(final Account.State nextStatus) {
- if (account.getStatus() != nextStatus) {
- if ((nextStatus == Account.State.OFFLINE)
- && (account.getStatus() != Account.State.CONNECTING)
- && (account.getStatus() != Account.State.ONLINE)
- && (account.getStatus() != Account.State.DISABLED)) {
- return;
- }
- if (nextStatus == Account.State.ONLINE) {
- this.attempt = 0;
- }
- account.setStatus(nextStatus);
- if (statusListener != null) {
- statusListener.onStatusChanged(account);
- }
- }
- }
-
- public void prepareNewConnection() {
- this.lastConnect = SystemClock.elapsedRealtime();
- this.lastPingSent = SystemClock.elapsedRealtime();
- this.lastDiscoStarted = Long.MAX_VALUE;
- this.changeStatus(Account.State.CONNECTING);
- }
-
- protected void connect() {
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": connecting");
- features.encryptionEnabled = false;
- this.attempt++;
- switch (account.getJid().getDomainpart()) {
- case "chat.facebook.com":
- mServerIdentity = Identity.FACEBOOK;
- break;
- case "nimbuzz.com":
- mServerIdentity = Identity.NIMBUZZ;
- break;
- default:
- mServerIdentity = Identity.UNKNOWN;
- break;
- }
- try {
- shouldAuthenticate = needsBinding = !account.isOptionSet(Account.OPTION_REGISTER);
- tagReader = new XmlReader(wakeLock);
- tagWriter = new TagWriter();
- this.changeStatus(Account.State.CONNECTING);
- final boolean useTor = mXmppConnectionService.useTorToConnect() || account.isOnion();
- final boolean extended = mXmppConnectionService.showExtendedConnectionOptions();
- if (Config.XMPP_IP != null && Config.XMPP_Ports != null) {
- Integer[] XMPP_Port = Config.XMPP_Ports;
- Integer Port = XMPP_Port[new Random().nextInt(XMPP_Port.length)];
- socket = new Socket();
- try {
- socket.connect(new InetSocketAddress(Config.XMPP_IP, Port), Config.SOCKET_TIMEOUT * 1000);
- } catch (IOException e) {
- throw new IOException();
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": connect to " + Config.XMPP_IP + ":" + Port);
- startXmpp();
- }
- else if (useTor) {
- String destination;
- if (account.getHostname() == null || account.getHostname().isEmpty()) {
- destination = account.getServer().toString();
- } else {
- destination = account.getHostname();
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": connect to " + destination + " via TOR");
- socket = SocksSocketFactory.createSocketOverTor(destination, account.getPort());
- startXmpp();
- } else if (extended && account.getHostname() != null && !account.getHostname().isEmpty()) {
- socket = new Socket();
- try {
- socket.connect(new InetSocketAddress(account.getHostname(), account.getPort()), Config.SOCKET_TIMEOUT * 1000);
- } catch (IOException e) {
- throw new UnknownHostException();
- }
- startXmpp();
- } else if (DNSHelper.isIp(account.getServer().toString())) {
- socket = new Socket();
- try {
- socket.connect(new InetSocketAddress(account.getServer().toString(), 5222), Config.SOCKET_TIMEOUT * 1000);
- } catch (IOException e) {
- throw new UnknownHostException();
- }
- startXmpp();
- } else {
- final Bundle result = DNSHelper.getSRVRecord(account.getServer(), mXmppConnectionService);
- final ArrayList<Parcelable>values = result.getParcelableArrayList("values");
- for(Iterator<Parcelable> iterator = values.iterator(); iterator.hasNext();) {
- if (Thread.currentThread().isInterrupted()) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": Thread was interrupted");
- return;
- }
- final Bundle namePort = (Bundle) iterator.next();
- try {
- String srvRecordServer;
- try {
- srvRecordServer = IDN.toASCII(namePort.getString("name"));
- } catch (final IllegalArgumentException e) {
- // TODO: Handle me?`
- srvRecordServer = "";
- }
- final int srvRecordPort = namePort.getInt("port");
- final String srvIpServer = namePort.getString("ip");
- // if tls is true, encryption is implied and must not be started
- features.encryptionEnabled = namePort.getBoolean("tls");
- final InetSocketAddress addr;
- if (srvIpServer != null) {
- addr = new InetSocketAddress(srvIpServer, srvRecordPort);
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
- + ": using values from dns " + srvRecordServer
- + "[" + srvIpServer + "]:" + srvRecordPort + " tls: " + features.encryptionEnabled);
- } else {
- addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
- + ": using values from dns "
- + srvRecordServer + ":" + srvRecordPort + " tls: " + features.encryptionEnabled);
- }
-
- if (!features.encryptionEnabled) {
- socket = new Socket();
- socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
- } else {
- final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
- socket = tlsFactoryVerifier.factory.createSocket();
-
- if (socket == null) {
- throw new IOException("could not initialize ssl socket");
- }
-
- SSLSocketHelper.setSecurity((SSLSocket) socket);
- SSLSocketHelper.setSNIHost(tlsFactoryVerifier.factory, (SSLSocket) socket, account.getServer().getDomainpart());
- SSLSocketHelper.setAlpnProtocol(tlsFactoryVerifier.factory, (SSLSocket) socket, "xmpp-client");
-
- socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
-
- if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), ((SSLSocket) socket).getSession())) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
- throw new SecurityException();
- }
- }
-
- if (startXmpp())
- break; // successfully connected to server that speaks xmpp
- } catch(final SecurityException e) {
- throw e;
- } catch (final Throwable e) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage() +"("+e.getClass().getName()+")");
- if (!iterator.hasNext()) {
- throw new UnknownHostException();
- }
- }
- }
- }
- processStream();
- } catch (final IncompatibleServerException e) {
- this.changeStatus(Account.State.INCOMPATIBLE_SERVER);
- } catch (final SecurityException e) {
- this.changeStatus(Account.State.SECURITY_ERROR);
- } catch (final UnauthorizedException e) {
- this.changeStatus(Account.State.UNAUTHORIZED);
- } catch (final UnknownHostException | ConnectException e) {
- this.changeStatus(Account.State.SERVER_NOT_FOUND);
- } catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
- this.changeStatus(Account.State.TOR_NOT_AVAILABLE);
- } catch(final StreamErrorHostUnknown e) {
- this.changeStatus(Account.State.HOST_UNKNOWN);
- } catch(final StreamErrorPolicyViolation e) {
- this.changeStatus(Account.State.POLICY_VIOLATION);
- } catch(final StreamError e) {
- this.changeStatus(Account.State.STREAM_ERROR);
- } catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
- this.changeStatus(Account.State.OFFLINE);
- this.attempt = Math.max(0, this.attempt - 1);
- } finally {
- forceCloseSocket();
- if (wakeLock.isHeld()) {
- try {
- wakeLock.release();
- } catch (final RuntimeException ignored) {
- }
- }
- }
- }
-
- /**
- * Starts xmpp protocol, call after connecting to socket
- * @return true if server returns with valid xmpp, false otherwise
- * @throws IOException Unknown tag on connect
- * @throws XmlPullParserException Bad Xml
- * @throws NoSuchAlgorithmException Other error
- */
- private boolean startXmpp() throws IOException, XmlPullParserException, NoSuchAlgorithmException {
- tagWriter.setOutputStream(socket.getOutputStream());
- tagReader.setInputStream(socket.getInputStream());
- tagWriter.beginDocument();
- sendStartStream();
- Tag nextTag;
- while ((nextTag = tagReader.readTag()) != null) {
- if (nextTag.isStart("stream")) {
- return true;
- } else {
- throw new IOException("unknown tag on connect");
- }
- }
- if (socket.isConnected()) {
- socket.close();
- }
- return false;
- }
-
- private static class TlsFactoryVerifier {
- private final SSLSocketFactory factory;
- private final HostnameVerifier verifier;
-
- public TlsFactoryVerifier(final SSLSocketFactory factory, final HostnameVerifier verifier) throws IOException {
- this.factory = factory;
- this.verifier = verifier;
- if (factory == null || verifier == null) {
- throw new IOException("could not setup ssl");
- }
- }
- }
-
- private TlsFactoryVerifier getTlsFactoryVerifier() throws NoSuchAlgorithmException, KeyManagementException, IOException {
- final SSLContext sc = SSLSocketHelper.getSSLContext();
- MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
- KeyManager[] keyManager;
- if (account.getPrivateKeyAlias() != null && account.getPassword().isEmpty()) {
- keyManager = new KeyManager[]{mKeyManager};
- } else {
- keyManager = null;
- }
- sc.init(keyManager, new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()}, mXmppConnectionService.getRNG());
- final SSLSocketFactory factory = sc.getSocketFactory();
- final HostnameVerifier verifier;
- if (mInteractive) {
- verifier = trustManager.wrapHostnameVerifier(new XmppDomainVerifier());
- } else {
- verifier = trustManager.wrapHostnameVerifierNonInteractive(new XmppDomainVerifier());
- }
-
- return new TlsFactoryVerifier(factory, verifier);
- }
-
- @Override
- public void run() {
- forceCloseSocket();
- connect();
- }
-
- private void processStream() throws XmlPullParserException, IOException, NoSuchAlgorithmException {
- Tag nextTag = tagReader.readTag();
- while (nextTag != null && !nextTag.isEnd("stream")) {
- if (nextTag.isStart("error")) {
- processStreamError(nextTag);
- } else if (nextTag.isStart("features")) {
- processStreamFeatures(nextTag);
- } else if (nextTag.isStart("proceed")) {
- switchOverToTls(nextTag);
- } else if (nextTag.isStart("success")) {
- final String challenge = tagReader.readElement(nextTag).getContent();
- try {
- saslMechanism.getResponse(challenge);
- } catch (final SaslMechanism.AuthenticationException e) {
- disconnect(true);
- Log.e(Config.LOGTAG, String.valueOf(e));
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": logged in");
- account.setKey(Account.PINNED_MECHANISM_KEY,
- String.valueOf(saslMechanism.getPriority()));
- tagReader.reset();
- sendStartStream();
- final Tag tag = tagReader.readTag();
- if (tag != null && tag.isStart("stream")) {
- processStream();
- } else {
- throw new IOException("server didn't restart stream after successful auth");
- }
- break;
- } else if (nextTag.isStart("failure")) {
- throw new UnauthorizedException();
- } else if (nextTag.isStart("challenge")) {
- final String challenge = tagReader.readElement(nextTag).getContent();
- final Element response = new Element("response");
- response.setAttribute("xmlns",
- "urn:ietf:params:xml:ns:xmpp-sasl");
- try {
- response.setContent(saslMechanism.getResponse(challenge));
- } catch (final SaslMechanism.AuthenticationException e) {
- // TODO: Send auth abort tag.
- Log.e(Config.LOGTAG, e.toString());
- }
- tagWriter.writeElement(response);
- } else if (nextTag.isStart("enabled")) {
- final Element enabled = tagReader.readElement(nextTag);
- if ("true".equals(enabled.getAttribute("resume"))) {
- this.streamId = enabled.getAttribute("id");
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
- + ": stream management(" + smVersion
- + ") enabled (resumable)");
- } else {
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
- + ": stream management(" + smVersion + ") enabled");
- }
- this.stanzasReceived = 0;
- final RequestPacket r = new RequestPacket(smVersion);
- tagWriter.writeStanzaAsync(r);
- } else if (nextTag.isStart("resumed")) {
- lastPacketReceived = SystemClock.elapsedRealtime();
- final Element resumed = tagReader.readElement(nextTag);
- final String h = resumed.getAttribute("h");
- try {
- ArrayList<AbstractAcknowledgeableStanza> failedStanzas = new ArrayList<>();
- synchronized (this.mStanzaQueue) {
- final int serverCount = Integer.parseInt(h);
- if (serverCount != stanzasSent) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
- + ": session resumed with lost packages");
- stanzasSent = serverCount;
- } else {
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": session resumed");
- }
- acknowledgeStanzaUpTo(serverCount);
- for (int i = 0; i < this.mStanzaQueue.size(); ++i) {
- failedStanzas.add(mStanzaQueue.valueAt(i));
- }
- mStanzaQueue.clear();
- }
- Log.d(Config.LOGTAG, "resending " + failedStanzas.size() + " stanzas");
- for (AbstractAcknowledgeableStanza packet : failedStanzas) {
- if (packet instanceof MessagePacket) {
- MessagePacket message = (MessagePacket) packet;
- mXmppConnectionService.markMessage(account,
- message.getTo().toBareJid(),
- message.getId(),
- Message.STATUS_UNSEND);
- }
- sendPacket(packet);
- }
- } catch (final NumberFormatException ignored) {
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid()+ ": online with resource " + account.getResource());
- changeStatus(Account.State.ONLINE);
- } else if (nextTag.isStart("r")) {
- tagReader.readElement(nextTag);
- if (Config.EXTENDED_SM_LOGGING) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": acknowledging stanza #" + this.stanzasReceived);
- }
- final AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
- tagWriter.writeStanzaAsync(ack);
- } else if (nextTag.isStart("a")) {
- final Element ack = tagReader.readElement(nextTag);
- lastPacketReceived = SystemClock.elapsedRealtime();
- try {
- synchronized (this.mStanzaQueue) {
- final int serverSequence = Integer.parseInt(ack.getAttribute("h"));
- acknowledgeStanzaUpTo(serverSequence);
- }
- } catch (NumberFormatException | NullPointerException e) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": server send ack without sequence number");
- }
- } else if (nextTag.isStart("failed")) {
- Element failed = tagReader.readElement(nextTag);
- try {
- final int serverCount = Integer.parseInt(failed.getAttribute("h"));
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed but server acknowledged stanza #"+serverCount);
- synchronized (this.mStanzaQueue) {
- acknowledgeStanzaUpTo(serverCount);
- }
- } catch (NumberFormatException | NullPointerException e) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": resumption failed");
- }
- resetStreamId();
- if (account.getStatus() != Account.State.ONLINE) {
- sendBindRequest();
- }
- } else if (nextTag.isStart("iq")) {
- processIq(nextTag);
- } else if (nextTag.isStart("message")) {
- processMessage(nextTag);
- } else if (nextTag.isStart("presence")) {
- processPresence(nextTag);
- }
- nextTag = tagReader.readTag();
- }
- }
-
- private void acknowledgeStanzaUpTo(int serverCount) {
- for (int i = 0; i < mStanzaQueue.size(); ++i) {
- if (serverCount >= mStanzaQueue.keyAt(i)) {
- if (Config.EXTENDED_SM_LOGGING) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server acknowledged stanza #" + mStanzaQueue.keyAt(i));
- }
- AbstractAcknowledgeableStanza stanza = mStanzaQueue.valueAt(i);
- if (stanza instanceof MessagePacket && acknowledgedListener != null) {
- MessagePacket packet = (MessagePacket) stanza;
- acknowledgedListener.onMessageAcknowledged(account, packet.getId());
- }
- mStanzaQueue.removeAt(i);
- i--;
- }
- }
- }
-
- private Element processPacket(final Tag currentTag, final int packetType)
- throws XmlPullParserException, IOException {
- Element element;
- switch (packetType) {
- case PACKET_IQ:
- element = new IqPacket();
- break;
- case PACKET_MESSAGE:
- element = new MessagePacket();
- break;
- case PACKET_PRESENCE:
- element = new PresencePacket();
- break;
- default:
- return null;
- }
- element.setAttributes(currentTag.getAttributes());
- Tag nextTag = tagReader.readTag();
- if (nextTag == null) {
- throw new IOException("interrupted mid tag");
- }
- while (!nextTag.isEnd(element.getName())) {
- if (!nextTag.isNo()) {
- final Element child = tagReader.readElement(nextTag);
- final String type = currentTag.getAttribute("type");
- if (packetType == PACKET_IQ
- && "jingle".equals(child.getName())
- && ("set".equalsIgnoreCase(type) || "get"
- .equalsIgnoreCase(type))) {
- element = new JinglePacket();
- element.setAttributes(currentTag.getAttributes());
- }
- element.addChild(child);
- }
- nextTag = tagReader.readTag();
- if (nextTag == null) {
- throw new IOException("interrupted mid tag");
- }
- }
- if (stanzasReceived == Integer.MAX_VALUE) {
- resetStreamId();
- throw new IOException("time to restart the session. cant handle >2 billion pcks");
- }
- ++stanzasReceived;
- lastPacketReceived = SystemClock.elapsedRealtime();
- if (Config.BACKGROUND_STANZA_LOGGING && mXmppConnectionService.checkListeners()) {
- Log.d(Config.LOGTAG,"[background stanza] "+element);
- }
- return element;
- }
-
- private void processIq(final Tag currentTag) throws XmlPullParserException, IOException {
- final IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
-
- if (packet.getId() == null) {
- return; // an iq packet without id is definitely invalid
- }
-
- if (packet instanceof JinglePacket) {
- if (this.jingleListener != null) {
- this.jingleListener.onJinglePacketReceived(account,(JinglePacket) packet);
- }
- } else {
- OnIqPacketReceived callback = null;
- synchronized (this.packetCallbacks) {
- if (packetCallbacks.containsKey(packet.getId())) {
- final Pair<IqPacket, OnIqPacketReceived> packetCallbackDuple = packetCallbacks.get(packet.getId());
- // Packets to the server should have responses from the server
- if (packetCallbackDuple.first.toServer(account)) {
- if (packet.fromServer(account) || mServerIdentity == Identity.FACEBOOK) {
- callback = packetCallbackDuple.second;
- packetCallbacks.remove(packet.getId());
- } else {
- Log.e(Config.LOGTAG, account.getJid().toBareJid().toString() + ": ignoring spoofed iq packet");
- }
- } else {
- if (packet.getFrom().equals(packetCallbackDuple.first.getTo())) {
- callback = packetCallbackDuple.second;
- packetCallbacks.remove(packet.getId());
- } else {
- Log.e(Config.LOGTAG, account.getJid().toBareJid().toString() + ": ignoring spoofed iq packet");
- }
- }
- } else if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) {
- callback = this.unregisteredIqListener;
- }
- }
- if (callback != null) {
- callback.onIqPacketReceived(account,packet);
- }
- }
- }
-
- private void processMessage(final Tag currentTag) throws XmlPullParserException, IOException {
- final MessagePacket packet = (MessagePacket) processPacket(currentTag,PACKET_MESSAGE);
- this.messageListener.onMessagePacketReceived(account, packet);
- }
-
- private void processPresence(final Tag currentTag) throws XmlPullParserException, IOException {
- PresencePacket packet = (PresencePacket) processPacket(currentTag, PACKET_PRESENCE);
- this.presenceListener.onPresencePacketReceived(account, packet);
- }
-
- private void sendStartTLS() throws IOException {
- final Tag startTLS = Tag.empty("starttls");
- startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
- tagWriter.writeTag(startTLS);
- }
-
-
-
- private void switchOverToTls(final Tag currentTag) throws XmlPullParserException, IOException {
- tagReader.readTag();
- try {
- final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
- final InetAddress address = socket == null ? null : socket.getInetAddress();
-
- if (address == null) {
- throw new IOException("could not setup ssl");
- }
-
- final SSLSocket sslSocket = (SSLSocket) tlsFactoryVerifier.factory.createSocket(socket, address.getHostAddress(), socket.getPort(), true);
-
- if (sslSocket == null) {
- throw new IOException("could not initialize ssl socket");
- }
-
- SSLSocketHelper.setSecurity(sslSocket);
-
- if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), sslSocket.getSession())) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
- throw new SecurityException();
- }
- tagReader.setInputStream(sslSocket.getInputStream());
- tagWriter.setOutputStream(sslSocket.getOutputStream());
- sendStartStream();
- Log.d(Config.LOGTAG, account.getJid().toBareJid()+ ": TLS connection established");
- features.encryptionEnabled = true;
- final Tag tag = tagReader.readTag();
- if (tag != null && tag.isStart("stream")) {
- processStream();
- } else {
- throw new IOException("server didn't restart stream after STARTTLS");
- }
- sslSocket.close();
- } catch (final NoSuchAlgorithmException | KeyManagementException e1) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
- throw new SecurityException();
- }
- }
-
- private void processStreamFeatures(final Tag currentTag)
- throws XmlPullParserException, IOException {
- this.streamFeatures = tagReader.readElement(currentTag);
- if (this.streamFeatures.hasChild("starttls") && !features.encryptionEnabled) {
- sendStartTLS();
- } else if (this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) {
- if (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS) {
- sendRegistryRequest();
- } else {
- throw new IncompatibleServerException();
- }
- } else if (!this.streamFeatures.hasChild("register")
- && account.isOptionSet(Account.OPTION_REGISTER)) {
- forceCloseSocket();
- changeStatus(Account.State.REGISTRATION_NOT_SUPPORTED);
- } else if (this.streamFeatures.hasChild("mechanisms")
- && shouldAuthenticate
- && (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS)) {
- authenticate();
- } else if (this.streamFeatures.hasChild("sm", "urn:xmpp:sm:" + smVersion) && streamId != null) {
- if (Config.EXTENDED_SM_LOGGING) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": resuming after stanza #"+stanzasReceived);
- }
- final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived, smVersion);
- this.tagWriter.writeStanzaAsync(resume);
- } else if (needsBinding) {
- if (this.streamFeatures.hasChild("bind")) {
- sendBindRequest();
- } else {
- throw new IncompatibleServerException();
- }
- }
- }
-
- private void authenticate() throws IOException {
- final List<String> mechanisms = extractMechanisms(streamFeatures
- .findChild("mechanisms"));
- final Element auth = new Element("auth");
- auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
- if (mechanisms.contains("EXTERNAL") && account.getPrivateKeyAlias() != null) {
- saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG());
- } else if (mechanisms.contains("SCRAM-SHA-1")) {
- saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
- } else if (mechanisms.contains("PLAIN")) {
- saslMechanism = new Plain(tagWriter, account);
- } else if (mechanisms.contains("DIGEST-MD5")) {
- saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
- }
- if (saslMechanism != null) {
- final JSONObject keys = account.getKeys();
- try {
- if (keys.has(Account.PINNED_MECHANISM_KEY) &&
- keys.getInt(Account.PINNED_MECHANISM_KEY) > saslMechanism.getPriority()) {
- Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() +
- " has lower priority (" + String.valueOf(saslMechanism.getPriority()) +
- ") than pinned priority (" + keys.getInt(Account.PINNED_MECHANISM_KEY) +
- "). Possible downgrade attack?");
- throw new SecurityException();
- }
- } catch (final JSONException e) {
- Log.d(Config.LOGTAG, "Parse error while checking pinned auth mechanism");
- }
- Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism());
- auth.setAttribute("mechanism", saslMechanism.getMechanism());
- if (!saslMechanism.getClientFirstMessage().isEmpty()) {
- auth.setContent(saslMechanism.getClientFirstMessage());
- }
- tagWriter.writeElement(auth);
- } else {
- throw new IncompatibleServerException();
- }
- }
-
- private List<String> extractMechanisms(final Element stream) {
- final ArrayList<String> mechanisms = new ArrayList<>(stream
- .getChildren().size());
- for (final Element child : stream.getChildren()) {
- mechanisms.add(child.getContent());
- }
- return mechanisms;
- }
-
- private void sendRegistryRequest() {
- final IqPacket register = new IqPacket(IqPacket.TYPE.GET);
- register.query("jabber:iq:register");
- register.setTo(account.getServer());
- sendIqPacket(register, new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(final Account account, final IqPacket packet) {
- boolean failed = false;
- if (packet.getType() == IqPacket.TYPE.RESULT
- && packet.query().hasChild("username")
- && (packet.query().hasChild("password"))) {
- final IqPacket register = new IqPacket(IqPacket.TYPE.SET);
- final Element username = new Element("username").setContent(account.getUsername());
- final Element password = new Element("password").setContent(account.getPassword());
- register.query("jabber:iq:register").addChild(username);
- register.query().addChild(password);
- sendIqPacket(register, registrationResponseListener);
- } else if (packet.getType() == IqPacket.TYPE.RESULT
- && (packet.query().hasChild("x", "jabber:x:data"))) {
- final Data data = Data.parse(packet.query().findChild("x", "jabber:x:data"));
- final Element blob = packet.query().findChild("data", "urn:xmpp:bob");
- final String id = packet.getId();
-
- Bitmap captcha = null;
- if (blob != null) {
- try {
- final String base64Blob = blob.getContent();
- final byte[] strBlob = Base64.decode(base64Blob, Base64.DEFAULT);
- InputStream stream = new ByteArrayInputStream(strBlob);
- captcha = BitmapFactory.decodeStream(stream);
- } catch (Exception e) {
- //ignored
- }
- } else {
- try {
- Field url = data.getFieldByName("url");
- String urlString = url.findChildContent("value");
- URL uri = new URL(urlString);
- captcha = BitmapFactory.decodeStream(uri.openConnection().getInputStream());
- } catch (IOException e) {
- Log.e(Config.LOGTAG, e.toString());
- }
- }
-
- if (captcha != null) {
- failed = !mXmppConnectionService.displayCaptchaRequest(account, id, data, captcha);
- }
- } else {
- failed = true;
- }
-
- if (failed) {
- final Element instructions = packet.query().findChild("instructions");
- setAccountCreationFailed((instructions != null) ? instructions.getContent() : "");
- }
- }
- });
- }
-
- private void setAccountCreationFailed(String instructions) {
- changeStatus(Account.State.REGISTRATION_FAILED);
- disconnect(true);
- Log.d(Config.LOGTAG, account.getJid().toBareJid()
- + ": could not register. instructions are"
- + instructions);
- }
-
- public void resetEverything() {
- resetAttemptCount();
- resetStreamId();
- clearIqCallbacks();
- mStanzaQueue.clear();
- synchronized (this.disco) {
- disco.clear();
- }
- }
-
- private void sendBindRequest() {
- while(!mXmppConnectionService.areMessagesInitialized() && socket != null && !socket.isClosed()) {
- try {
- Thread.sleep(500);
- } catch (final InterruptedException ignored) {
- }
- }
- needsBinding = false;
- clearIqCallbacks();
- final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
- iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind")
- .addChild("resource").setContent(account.getResource());
- this.sendUnmodifiedIqPacket(iq, new OnIqPacketReceived() {
- @Override
- public void onIqPacketReceived(final Account account, final IqPacket packet) {
- if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
- return;
- }
- final Element bind = packet.findChild("bind");
- if (bind != null && packet.getType() == IqPacket.TYPE.RESULT) {
- final Element jid = bind.findChild("jid");
- if (jid != null && jid.getContent() != null) {
- try {
- account.setResource(Jid.fromString(jid.getContent()).getResourcepart());
- if (streamFeatures.hasChild("session")
- && !streamFeatures.findChild("session").hasChild("optional")) {
- sendStartSession();
- } else {
- sendPostBindInitialization();
- }
- return;
- } catch (final InvalidJidException e) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": server reported invalid jid ("+jid.getContent()+") on bind");
- }
- } else {
- Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure. (no jid)");
- }
- } else {
- Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure (" + packet.toString());
- }
- forceCloseSocket();
- changeStatus(Account.State.BIND_FAILURE);
- }
- });
- }
-
- private void clearIqCallbacks() {
- final IqPacket failurePacket = new IqPacket(IqPacket.TYPE.TIMEOUT);
- final ArrayList<OnIqPacketReceived> callbacks = new ArrayList<>();
- synchronized (this.packetCallbacks) {
- if (this.packetCallbacks.size() == 0) {
- return;
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": clearing "+this.packetCallbacks.size()+" iq callbacks");
- final Iterator<Pair<IqPacket, OnIqPacketReceived>> iterator = this.packetCallbacks.values().iterator();
- while (iterator.hasNext()) {
- Pair<IqPacket, OnIqPacketReceived> entry = iterator.next();
- callbacks.add(entry.second);
- iterator.remove();
- }
- }
- for(OnIqPacketReceived callback : callbacks) {
- callback.onIqPacketReceived(account,failurePacket);
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": done clearing iq callbacks. " + this.packetCallbacks.size() + " left");
- }
-
- public void sendDiscoTimeout() {
- if (mWaitForDisco.compareAndSet(true, false)) {
- finalizeBind();
- }
- }
-
- private void sendStartSession() {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": sending legacy session to outdated server");
- final IqPacket startSession = new IqPacket(IqPacket.TYPE.SET);
- startSession.addChild("session", "urn:ietf:params:xml:ns:xmpp-session");
- this.sendUnmodifiedIqPacket(startSession, new OnIqPacketReceived() {
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- if (packet.getType() == IqPacket.TYPE.RESULT) {
- sendPostBindInitialization();
- } else if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions");
- disconnect(true);
- }
- }
- });
- }
-
- private void sendPostBindInitialization() {
- smVersion = 0;
- if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) {
- smVersion = 3;
- } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) {
- smVersion = 2;
- }
- if (smVersion != 0) {
- synchronized (this.mStanzaQueue) {
- final EnablePacket enable = new EnablePacket(smVersion);
- tagWriter.writeStanzaAsync(enable);
- stanzasSent = 0;
- mStanzaQueue.clear();
- }
- }
- features.carbonsEnabled = false;
- features.blockListRequested = false;
- synchronized (this.disco) {
- this.disco.clear();
- }
- mPendingServiceDiscoveries.set(0);
- mWaitForDisco.set(mServerIdentity != Identity.NIMBUZZ);
- lastDiscoStarted = SystemClock.elapsedRealtime();
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": starting service discovery");
- mXmppConnectionService.scheduleWakeUpCall(Config.CONNECT_DISCO_TIMEOUT, account.getUuid().hashCode());
- Element caps = streamFeatures.findChild("c");
- final String hash = caps == null ? null : caps.getAttribute("hash");
- final String ver = caps == null ? null : caps.getAttribute("ver");
- ServiceDiscoveryResult discoveryResult = null;
- if (hash != null && ver != null) {
- discoveryResult = mXmppConnectionService.getCachedServiceDiscoveryResult(new Pair<>(hash, ver));
- }
- if (discoveryResult == null) {
- sendServiceDiscoveryInfo(account.getServer());
- } else {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": server caps came from cache");
- disco.put(account.getServer(), discoveryResult);
- }
- sendServiceDiscoveryInfo(account.getJid().toBareJid());
- sendServiceDiscoveryItems(account.getServer());
-
- if (!mWaitForDisco.get()) {
- finalizeBind();
- }
- this.lastSessionStarted = SystemClock.elapsedRealtime();
- }
-
- private void sendServiceDiscoveryInfo(final Jid jid) {
- mPendingServiceDiscoveries.incrementAndGet();
- final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
- iq.setTo(jid);
- iq.query("http://jabber.org/protocol/disco#info");
- this.sendIqPacket(iq, new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(final Account account, final IqPacket packet) {
- if (packet.getType() == IqPacket.TYPE.RESULT) {
- boolean advancedStreamFeaturesLoaded;
- synchronized (XmppConnection.this.disco) {
- ServiceDiscoveryResult result = new ServiceDiscoveryResult(packet);
- for (final ServiceDiscoveryResult.Identity id : result.getIdentities()) {
- if (mServerIdentity == Identity.UNKNOWN && id.getType().equals("im") &&
- id.getCategory().equals("server") && id.getName() != null &&
- jid.equals(account.getServer())) {
- switch (id.getName()) {
- case "Prosody":
- mServerIdentity = Identity.PROSODY;
- break;
- case "ejabberd":
- mServerIdentity = Identity.EJABBERD;
- break;
- case "Slack-XMPP":
- mServerIdentity = Identity.SLACK;
- break;
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server name: " + id.getName());
- }
- }
- if (jid.equals(account.getServer())) {
- mXmppConnectionService.databaseBackend.insertDiscoveryResult(result);
- }
- disco.put(jid, result);
- advancedStreamFeaturesLoaded = disco.containsKey(account.getServer())
- && disco.containsKey(account.getJid().toBareJid());
- }
- if (advancedStreamFeaturesLoaded && (jid.equals(account.getServer()) || jid.equals(account.getJid().toBareJid()))) {
- enableAdvancedStreamFeatures();
- }
- } else {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not query disco info for " + jid.toString());
- }
- if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
- if (mPendingServiceDiscoveries.decrementAndGet() == 0
- && mWaitForDisco.compareAndSet(true, false)) {
- finalizeBind();
- }
- }
- }
- });
- }
-
- private void finalizeBind() {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": online with resource " + account.getResource());
- if (bindListener != null) {
- bindListener.onBind(account);
- }
- changeStatus(Account.State.ONLINE);
- }
-
- private void enableAdvancedStreamFeatures() {
- if (getFeatures().carbons() && !features.carbonsEnabled) {
- sendEnableCarbons();
- }
- if (getFeatures().blocking() && !features.blockListRequested) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": Requesting block list");
- this.sendIqPacket(getIqGenerator().generateGetBlockList(), mXmppConnectionService.getIqParser());
- }
- for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
- listener.onAdvancedStreamFeaturesAvailable(account);
- }
- }
-
- private void sendServiceDiscoveryItems(final Jid server) {
- mPendingServiceDiscoveries.incrementAndGet();
- final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
- iq.setTo(server.toDomainJid());
- iq.query("http://jabber.org/protocol/disco#items");
- this.sendIqPacket(iq, new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(final Account account, final IqPacket packet) {
- if (packet.getType() == IqPacket.TYPE.RESULT) {
- final List<Element> elements = packet.query().getChildren();
- for (final Element element : elements) {
- if (element.getName().equals("item")) {
- final Jid jid = element.getAttributeAsJid("jid");
- if (jid != null && !jid.equals(account.getServer())) {
- sendServiceDiscoveryInfo(jid);
- }
- }
- }
- } else {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not query disco items of " + server);
- }
- if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
- if (mPendingServiceDiscoveries.decrementAndGet() == 0
- && mWaitForDisco.compareAndSet(true, false)) {
- finalizeBind();
- }
- }
- }
- });
- }
-
- private void sendEnableCarbons() {
- final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
- iq.addChild("enable", "urn:xmpp:carbons:2");
- this.sendIqPacket(iq, new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(final Account account, final IqPacket packet) {
- if (!packet.hasChild("error")) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid()
- + ": successfully enabled carbons");
- features.carbonsEnabled = true;
- } else {
- Log.d(Config.LOGTAG, account.getJid().toBareJid()
- + ": error enableing carbons " + packet.toString());
- }
- }
- });
- }
-
- private void processStreamError(final Tag currentTag)
- throws XmlPullParserException, IOException {
- final Element streamError = tagReader.readElement(currentTag);
- if (streamError == null) {
- return;
- }
- if (streamError.hasChild("conflict")) {
- final String resource = account.getResource().split("\\.")[0];
- account.setResource(resource + "." + nextRandomId());
- Log.d(Config.LOGTAG,
- account.getJid().toBareJid() + ": switching resource due to conflict ("
- + account.getResource() + ")");
- throw new IOException();
- } else if (streamError.hasChild("host-unknown")) {
- throw new StreamErrorHostUnknown();
- } else if (streamError.hasChild("policy-violation")) {
- throw new StreamErrorPolicyViolation();
- } else {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString());
- throw new StreamError();
- }
- }
-
- private void sendStartStream() throws IOException {
- final Tag stream = Tag.start("stream:stream");
- stream.setAttribute("to", account.getServer().toString());
- stream.setAttribute("version", "1.0");
- stream.setAttribute("xml:lang", "en");
- stream.setAttribute("xmlns", "jabber:client");
- stream.setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
- tagWriter.writeTag(stream);
- }
-
- private String nextRandomId() {
- return new BigInteger(50, mXmppConnectionService.getRNG()).toString(32);
- }
-
- public String sendIqPacket(final IqPacket packet, final OnIqPacketReceived callback) {
- packet.setFrom(account.getJid());
- return this.sendUnmodifiedIqPacket(packet, callback);
- }
-
- private synchronized String sendUnmodifiedIqPacket(final IqPacket packet, final OnIqPacketReceived callback) {
- if (packet.getId() == null) {
- final String id = nextRandomId();
- packet.setAttribute("id", id);
- }
- if (callback != null) {
- synchronized (this.packetCallbacks) {
- packetCallbacks.put(packet.getId(), new Pair<>(packet, callback));
- }
- }
- this.sendPacket(packet);
- return packet.getId();
- }
-
- public void sendMessagePacket(final MessagePacket packet) {
- this.sendPacket(packet);
- }
-
- public void sendPresencePacket(final PresencePacket packet) {
- this.sendPacket(packet);
- }
-
- private synchronized void sendPacket(final AbstractStanza packet) {
- if (stanzasSent == Integer.MAX_VALUE) {
- resetStreamId();
- disconnect(true);
- return;
- }
- synchronized (this.mStanzaQueue) {
- tagWriter.writeStanzaAsync(packet);
- if (packet instanceof AbstractAcknowledgeableStanza) {
- AbstractAcknowledgeableStanza stanza = (AbstractAcknowledgeableStanza) packet;
- ++stanzasSent;
- this.mStanzaQueue.append(stanzasSent, stanza);
- if (stanza instanceof MessagePacket && stanza.getId() != null && getFeatures().sm()) {
- if (Config.EXTENDED_SM_LOGGING) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": requesting ack for message stanza #" + stanzasSent);
- }
- tagWriter.writeStanzaAsync(new RequestPacket(this.smVersion));
- }
- }
- }
- }
-
- public void sendPing() {
- if (!r()) {
- final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
- iq.setFrom(account.getJid());
- iq.addChild("ping", "urn:xmpp:ping");
- this.sendIqPacket(iq, null);
- }
- this.lastPingSent = SystemClock.elapsedRealtime();
- }
-
- public void setOnMessagePacketReceivedListener(
- final OnMessagePacketReceived listener) {
- this.messageListener = listener;
- }
-
- public void setOnUnregisteredIqPacketReceivedListener(
- final OnIqPacketReceived listener) {
- this.unregisteredIqListener = listener;
- }
-
- public void setOnPresencePacketReceivedListener(
- final OnPresencePacketReceived listener) {
- this.presenceListener = listener;
- }
-
- public void setOnJinglePacketReceivedListener(
- final OnJinglePacketReceived listener) {
- this.jingleListener = listener;
- }
-
- public void setOnStatusChangedListener(final OnStatusChanged listener) {
- this.statusListener = listener;
- }
-
- public void setOnBindListener(final OnBindListener listener) {
- this.bindListener = listener;
- }
-
- public void setOnMessageAcknowledgeListener(final OnMessageAcknowledged listener) {
- this.acknowledgedListener = listener;
- }
-
- public void addOnAdvancedStreamFeaturesAvailableListener(final OnAdvancedStreamFeaturesLoaded listener) {
- if (!this.advancedStreamFeaturesLoadedListeners.contains(listener)) {
- this.advancedStreamFeaturesLoadedListeners.add(listener);
- }
- }
-
- public void waitForPush() {
- if (tagWriter.isActive()) {
- tagWriter.finish();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- while(!tagWriter.finished()) {
- Thread.sleep(10);
- }
- socket.close();
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": closed tcp without closing stream");
- } catch (IOException | InterruptedException e) {
- return;
- }
- }
- }).start();
- } else {
- forceCloseSocket();
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": closed tcp without closing stream (no waiting)");
- }
- }
-
- private void forceCloseSocket() {
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- public void interrupt() {
- Thread.currentThread().interrupt();
- }
-
- public void disconnect(final boolean force) {
- interrupt();
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": disconnecting force="+Boolean.valueOf(force));
- if (force) {
- tagWriter.forceClose();
- forceCloseSocket();
- } else {
- if (tagWriter.isActive()) {
- tagWriter.finish();
- try {
- int i = 0;
- boolean warned = false;
- while (!tagWriter.finished() && socket.isConnected() && i <= 10) {
- if (!warned) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid()+": waiting for tag writer to finish");
- warned = true;
- }
- Thread.sleep(200);
- i++;
- }
- if (warned) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": tag writer has finished");
- }
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": closing stream");
- tagWriter.writeTag(Tag.end("stream:stream"));
- } catch (final IOException e) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": io exception during disconnect ("+e.getMessage()+")");
- } catch (final InterruptedException e) {
- Log.d(Config.LOGTAG, "interrupted");
- }
- }
- }
- }
-
- public void resetStreamId() {
- this.streamId = null;
- }
-
- private List<Entry<Jid, ServiceDiscoveryResult>> findDiscoItemsByFeature(final String feature) {
- synchronized (this.disco) {
- final List<Entry<Jid, ServiceDiscoveryResult>> items = new ArrayList<>();
- for (final Entry<Jid, ServiceDiscoveryResult> cursor : this.disco.entrySet()) {
- if (cursor.getValue().getFeatures().contains(feature)) {
- items.add(cursor);
- }
- }
- return items;
- }
- }
-
- public Jid findDiscoItemByFeature(final String feature) {
- final List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(feature);
- if (items.size() >= 1) {
- return items.get(0).getKey();
- }
- return null;
- }
-
- public boolean r() {
- if (getFeatures().sm()) {
- this.tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
- return true;
- } else {
- return false;
- }
- }
-
- public String getMucServer() {
- synchronized (this.disco) {
- for (final Entry<Jid, ServiceDiscoveryResult> cursor : disco.entrySet()) {
- final ServiceDiscoveryResult value = cursor.getValue();
- if (value.getFeatures().contains("http://jabber.org/protocol/muc")
- && !value.getFeatures().contains("jabber:iq:gateway")
- && !value.hasIdentity("conference", "irc")) {
- return cursor.getKey().toString();
- }
- }
- }
- return null;
- }
-
- public int getTimeToNextAttempt() {
- final int interval = Math.min((int) (25 * Math.pow(1.3, attempt)), 300);
- final int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
- return interval - secondsSinceLast;
- }
-
- public int getAttempt() {
- return this.attempt;
- }
-
- public Features getFeatures() {
- return this.features;
- }
-
- public long getLastSessionEstablished() {
- final long diff = SystemClock.elapsedRealtime() - this.lastSessionStarted;
- return System.currentTimeMillis() - diff;
- }
-
- public long getLastConnect() {
- return this.lastConnect;
- }
-
- public long getLastPingSent() {
- return this.lastPingSent;
- }
-
- public long getLastDiscoStarted() {
- return this.lastDiscoStarted;
- }
- public long getLastPacketReceived() {
- return this.lastPacketReceived;
- }
-
- public void sendActive() {
- this.sendPacket(new ActivePacket());
- }
-
- public void sendInactive() {
- this.sendPacket(new InactivePacket());
- }
-
- public void resetAttemptCount() {
- this.attempt = 0;
- this.lastConnect = 0;
- }
-
- public void setInteractive(boolean interactive) {
- this.mInteractive = interactive;
- }
-
- public Identity getServerIdentity() {
- return mServerIdentity;
- }
-
- private class UnauthorizedException extends IOException {
-
- }
-
- private class SecurityException extends IOException {
-
- }
-
- private class IncompatibleServerException extends IOException {
-
- }
-
- private class StreamErrorHostUnknown extends StreamError {
-
- }
-
- private class StreamErrorPolicyViolation extends StreamError {
-
- }
-
- private class StreamError extends IOException {
-
- }
-
- public enum Identity {
- FACEBOOK,
- SLACK,
- EJABBERD,
- PROSODY,
- NIMBUZZ,
- UNKNOWN
- }
-
- public class Features {
- XmppConnection connection;
- private boolean carbonsEnabled = false;
- private boolean encryptionEnabled = false;
- private boolean blockListRequested = false;
-
- public Features(final XmppConnection connection) {
- this.connection = connection;
- }
-
- private boolean hasDiscoFeature(final Jid server, final String feature) {
- synchronized (XmppConnection.this.disco) {
- return connection.disco.containsKey(server) &&
- connection.disco.get(server).getFeatures().contains(feature);
- }
- }
-
- public boolean carbons() {
- return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2");
- }
-
- public boolean blocking() {
- return hasDiscoFeature(account.getServer(), Xmlns.BLOCKING);
- }
-
- public boolean register() {
- return hasDiscoFeature(account.getServer(), Xmlns.REGISTER);
- }
-
- public boolean sm() {
- return streamId != null
- || (connection.streamFeatures != null && connection.streamFeatures.hasChild("sm"));
- }
-
- public boolean csi() {
- return connection.streamFeatures != null && connection.streamFeatures.hasChild("csi", "urn:xmpp:csi:0");
- }
-
- public boolean pep() {
- synchronized (XmppConnection.this.disco) {
- ServiceDiscoveryResult info = disco.get(account.getJid().toBareJid());
- return info != null && info.hasIdentity("pubsub", "pep");
- }
- }
-
- public boolean pepPersistent() {
- synchronized (XmppConnection.this.disco) {
- ServiceDiscoveryResult info = disco.get(account.getJid().toBareJid());
- return info != null && info.getFeatures().contains("http://jabber.org/protocol/pubsub#persistent-items");
- }
- }
-
- public boolean mam() {
- return hasDiscoFeature(account.getJid().toBareJid(), "urn:xmpp:mam:0")
- || hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
- }
-
- public boolean push() {
- return hasDiscoFeature(account.getJid().toBareJid(), "urn:xmpp:push:0")
- || hasDiscoFeature(account.getServer(), "urn:xmpp:push:0");
- }
-
- public boolean rosterVersioning() {
- return connection.streamFeatures != null && connection.streamFeatures.hasChild("ver");
- }
-
- public void setBlockListRequested(boolean value) {
- this.blockListRequested = value;
- }
-
- public boolean httpUpload(long filesize) {
- if (Config.DISABLE_HTTP_UPLOAD) {
- return false;
- } else {
- List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(Xmlns.HTTP_UPLOAD);
- if (items.size() > 0) {
- try {
- long maxsize = Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(Xmlns.HTTP_UPLOAD, "max-file-size"));
- if(filesize <= maxsize) {
- return true;
- } else {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": http upload is not available for files with size "+filesize+" (max is "+maxsize+")");
- return false;
- }
- } catch (Exception e) {
- return true;
- }
- } else {
- return false;
- }
- }
- }
-
- public long getMaxHttpUploadSize() {
- List<Entry<Jid, ServiceDiscoveryResult>> items = findDiscoItemsByFeature(Xmlns.HTTP_UPLOAD);
- if (items.size() > 0) {
- try {
- return Long.parseLong(items.get(0).getValue().getExtendedDiscoInformation(Xmlns.HTTP_UPLOAD, "max-file-size"));
- } catch (Exception e) {
- return -1;
- }
- } else {
- return -1;
- }
- }
- }
-
- private IqGenerator getIqGenerator() {
- return mXmppConnectionService.getIqGenerator();
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java b/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java
deleted file mode 100644
index 3e371562c..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package eu.siacs.conversations.xmpp.chatstate;
-
-import eu.siacs.conversations.xml.Element;
-
-public enum ChatState {
-
- ACTIVE, INACTIVE, GONE, COMPOSING, PAUSED;
-
- public static ChatState parse(Element element) {
- final String NAMESPACE = "http://jabber.org/protocol/chatstates";
- if (element.hasChild("active",NAMESPACE)) {
- return ACTIVE;
- } else if (element.hasChild("inactive",NAMESPACE)) {
- return INACTIVE;
- } else if (element.hasChild("composing",NAMESPACE)) {
- return COMPOSING;
- } else if (element.hasChild("gone",NAMESPACE)) {
- return GONE;
- } else if (element.hasChild("paused",NAMESPACE)) {
- return PAUSED;
- } else {
- return null;
- }
- }
-
- public static Element toElement(ChatState state) {
- final String NAMESPACE = "http://jabber.org/protocol/chatstates";
- final Element element = new Element(state.toString().toLowerCase());
- element.setAttribute("xmlns",NAMESPACE);
- return element;
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java
deleted file mode 100644
index c81c5a1f3..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/forms/Data.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package eu.siacs.conversations.xmpp.forms;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import eu.siacs.conversations.xml.Element;
-
-public class Data extends Element {
-
- public static final String FORM_TYPE = "FORM_TYPE";
-
- public Data() {
- super("x");
- this.setAttribute("xmlns","jabber:x:data");
- }
-
- public List<Field> getFields() {
- ArrayList<Field> fields = new ArrayList<Field>();
- for(Element child : getChildren()) {
- if (child.getName().equals("field")
- && !FORM_TYPE.equals(child.getAttribute("var"))) {
- fields.add(Field.parse(child));
- }
- }
- return fields;
- }
-
- public Field getFieldByName(String needle) {
- for(Element child : getChildren()) {
- if (child.getName().equals("field")
- && needle.equals(child.getAttribute("var"))) {
- return Field.parse(child);
- }
- }
- return null;
- }
-
- public void put(String name, String value) {
- Field field = getFieldByName(name);
- if (field == null) {
- field = new Field(name);
- this.addChild(field);
- }
- field.setValue(value);
- }
-
- public void put(String name, Collection<String> values) {
- Field field = getFieldByName(name);
- if (field == null) {
- field = new Field(name);
- this.addChild(field);
- }
- field.setValues(values);
- }
-
- public void submit() {
- this.setAttribute("type","submit");
- removeUnnecessaryChildren();
- for(Field field : getFields()) {
- field.removeNonValueChildren();
- }
- }
-
- private void removeUnnecessaryChildren() {
- for(Iterator<Element> iterator = this.children.iterator(); iterator.hasNext();) {
- Element element = iterator.next();
- if (!element.getName().equals("field") && !element.getName().equals("title")) {
- iterator.remove();
- }
- }
- }
-
- public static Data parse(Element element) {
- Data data = new Data();
- data.setAttributes(element.getAttributes());
- data.setChildren(element.getChildren());
- return data;
- }
-
- public void setFormType(String formType) {
- this.put(FORM_TYPE, formType);
- }
-
- public String getFormType() {
- String type = getValue(FORM_TYPE);
- return type == null ? "" : type;
- }
-
- public String getValue(String name) {
- Field field = this.getFieldByName(name);
- return field == null ? null : field.getValue();
- }
-
- public String getTitle() {
- return findChildContent("title");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java b/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java
deleted file mode 100644
index 020b34b90..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/forms/Field.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package eu.siacs.conversations.xmpp.forms;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import eu.siacs.conversations.xml.Element;
-
-public class Field extends Element {
-
- public Field(String name) {
- super("field");
- this.setAttribute("var",name);
- }
-
- private Field() {
- super("field");
- }
-
- public String getFieldName() {
- return this.getAttribute("var");
- }
-
- public void setValue(String value) {
- this.children.clear();
- this.addChild("value").setContent(value);
- }
-
- public void setValues(Collection<String> values) {
- this.children.clear();
- for(String value : values) {
- this.addChild("value").setContent(value);
- }
- }
-
- public void removeNonValueChildren() {
- for(Iterator<Element> iterator = this.children.iterator(); iterator.hasNext();) {
- Element element = iterator.next();
- if (!element.getName().equals("value")) {
- iterator.remove();
- }
- }
- }
-
- public static Field parse(Element element) {
- Field field = new Field();
- field.setAttributes(element.getAttributes());
- field.setChildren(element.getChildren());
- return field;
- }
-
- public String getValue() {
- return findChildContent("value");
- }
-
- public List<String> getValues() {
- List<String> values = new ArrayList<>();
- for(Element child : getChildren()) {
- if ("value".equals(child.getName())) {
- String content = child.getContent();
- if (content != null) {
- values.add(content);
- }
- }
- }
- return values;
- }
-
- public String getLabel() {
- return getAttribute("label");
- }
-
- public String getType() {
- return getAttribute("type");
- }
-
- public boolean isRequired() {
- return hasChild("required");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java
deleted file mode 100644
index 164e88495..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package eu.siacs.conversations.xmpp.jid;
-
-public class InvalidJidException extends Exception {
-
- // This is probably not the "Java way", but the "Java way" means we'd have a ton of extra tiny,
- // annoying classes floating around. I like this.
- public final static String INVALID_LENGTH = "JID must be between 0 and 3071 characters";
- public final static String INVALID_PART_LENGTH = "JID part must be between 0 and 1023 characters";
- public final static String INVALID_CHARACTER = "JID contains an invalid character";
- public final static String STRINGPREP_FAIL = "The STRINGPREP operation has failed for the given JID";
- public final static String IS_NULL = "JID can not be NULL";
-
- /**
- * Constructs a new {@code Exception} that includes the current stack trace.
- */
- public InvalidJidException() {
- }
-
- /**
- * Constructs a new {@code Exception} with the current stack trace and the
- * specified detail message.
- *
- * @param detailMessage the detail message for this exception.
- */
- public InvalidJidException(final String detailMessage) {
- super(detailMessage);
- }
-
- /**
- * Constructs a new {@code Exception} with the current stack trace, the
- * specified detail message and the specified cause.
- *
- * @param detailMessage the detail message for this exception.
- * @param throwable the cause of this exception.
- */
- public InvalidJidException(final String detailMessage, final Throwable throwable) {
- super(detailMessage, throwable);
- }
-
- /**
- * Constructs a new {@code Exception} with the current stack trace and the
- * specified cause.
- *
- * @param throwable the cause of this exception.
- */
- public InvalidJidException(final Throwable throwable) {
- super(throwable);
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
deleted file mode 100644
index a15abe14a..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package eu.siacs.conversations.xmpp.jid;
-
-import android.util.LruCache;
-
-import net.java.otr4j.session.SessionID;
-
-import java.net.IDN;
-
-import eu.siacs.conversations.Config;
-import gnu.inet.encoding.Stringprep;
-import gnu.inet.encoding.StringprepException;
-
-/**
- * The `Jid' class provides an immutable representation of a JID.
- */
-public final class Jid {
-
- private static LruCache<String,Jid> cache = new LruCache<>(1024);
-
- private final String localpart;
- private final String domainpart;
- private final String resourcepart;
-
- // It's much more efficient to store the ful JID as well as the parts instead of figuring them
- // all out every time (since some characters are displayed but aren't used for comparisons).
- private final String displayjid;
-
- public String getLocalpart() {
- return localpart;
- }
-
- public String getDomainpart() {
- return IDN.toUnicode(domainpart);
- }
-
- public String getResourcepart() {
- return resourcepart;
- }
-
- public static Jid fromSessionID(final SessionID id) throws InvalidJidException{
- if (id.getUserID().isEmpty()) {
- return Jid.fromString(id.getAccountID());
- } else {
- return Jid.fromString(id.getAccountID()+"/"+id.getUserID());
- }
- }
-
- public static Jid fromString(final String jid) throws InvalidJidException {
- return Jid.fromString(jid, false);
- }
-
- public static Jid fromString(final String jid, final boolean safe) throws InvalidJidException {
- return new Jid(jid, safe);
- }
-
- public static Jid fromParts(final String localpart,
- final String domainpart,
- final String resourcepart) throws InvalidJidException {
- String out;
- if (localpart == null || localpart.isEmpty()) {
- out = domainpart;
- } else {
- out = localpart + "@" + domainpart;
- }
- if (resourcepart != null && !resourcepart.isEmpty()) {
- out = out + "/" + resourcepart;
- }
- return new Jid(out, false);
- }
-
- private Jid(final String jid, final boolean safe) throws InvalidJidException {
- if (jid == null) throw new InvalidJidException(InvalidJidException.IS_NULL);
-
- Jid fromCache = Jid.cache.get(jid);
- if (fromCache != null) {
- displayjid = fromCache.displayjid;
- localpart = fromCache.localpart;
- domainpart = fromCache.domainpart;
- resourcepart = fromCache.resourcepart;
- return;
- }
-
- // Hackish Android way to count the number of chars in a string... should work everywhere.
- final int atCount = jid.length() - jid.replace("@", "").length();
- final int slashCount = jid.length() - jid.replace("/", "").length();
-
- // Throw an error if there's anything obvious wrong with the JID...
- if (jid.isEmpty() || jid.length() > 3071) {
- throw new InvalidJidException(InvalidJidException.INVALID_LENGTH);
- }
-
- // Go ahead and check if the localpart or resourcepart is empty.
- if (jid.startsWith("@") || (jid.endsWith("@") && slashCount == 0) || jid.startsWith("/") || (jid.endsWith("/") && slashCount < 2)) {
- throw new InvalidJidException(InvalidJidException.INVALID_CHARACTER);
- }
-
- String finaljid;
-
- final int domainpartStart;
- final int atLoc = jid.indexOf("@");
- final int slashLoc = jid.indexOf("/");
- // If there is no "@" in the JID (eg. "example.net" or "example.net/resource")
- // or there are one or more "@" signs but they're all in the resourcepart (eg. "example.net/@/rp@"):
- if (atCount == 0 || (atCount > 0 && slashLoc != -1 && atLoc > slashLoc)) {
- localpart = "";
- finaljid = "";
- domainpartStart = 0;
- } else {
- final String lp = jid.substring(0, atLoc);
- try {
- localpart = Config.DISABLE_STRING_PREP || safe ? lp : Stringprep.nodeprep(lp);
- } catch (final StringprepException e) {
- throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
- }
- if (localpart.isEmpty() || localpart.length() > 1023) {
- throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
- }
- domainpartStart = atLoc + 1;
- finaljid = lp + "@";
- }
-
- final String dp;
- if (slashCount > 0) {
- final String rp = jid.substring(slashLoc + 1, jid.length());
- try {
- resourcepart = Config.DISABLE_STRING_PREP || safe ? rp : Stringprep.resourceprep(rp);
- } catch (final StringprepException e) {
- throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
- }
- if (resourcepart.isEmpty() || resourcepart.length() > 1023) {
- throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
- }
- try {
- dp = IDN.toUnicode(Stringprep.nameprep(jid.substring(domainpartStart, slashLoc)), IDN.USE_STD3_ASCII_RULES);
- } catch (final StringprepException e) {
- throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
- }
- finaljid = finaljid + dp + "/" + rp;
- } else {
- resourcepart = "";
- try{
- dp = IDN.toUnicode(Stringprep.nameprep(jid.substring(domainpartStart, jid.length())), IDN.USE_STD3_ASCII_RULES);
- } catch (final StringprepException e) {
- throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
- }
- finaljid = finaljid + dp;
- }
-
- // Remove trailing "." before storing the domain part.
- if (dp.endsWith(".")) {
- try {
- domainpart = IDN.toASCII(dp.substring(0, dp.length() - 1), IDN.USE_STD3_ASCII_RULES);
- } catch (final IllegalArgumentException e) {
- throw new InvalidJidException(e);
- }
- } else {
- try {
- domainpart = IDN.toASCII(dp, IDN.USE_STD3_ASCII_RULES);
- } catch (final IllegalArgumentException e) {
- throw new InvalidJidException(e);
- }
- }
-
- // TODO: Find a proper domain validation library; validate individual parts, separators, etc.
- if (domainpart.isEmpty() || domainpart.length() > 1023) {
- throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
- }
-
- Jid.cache.put(jid, this);
-
- this.displayjid = finaljid;
- }
-
- public Jid toBareJid() {
- try {
- return resourcepart.isEmpty() ? this : fromParts(localpart, domainpart, "");
- } catch (final InvalidJidException e) {
- // This should never happen.
- throw new AssertionError("Jid " + this.toString() + " invalid");
- }
- }
-
- public Jid toDomainJid() {
- try {
- return resourcepart.isEmpty() && localpart.isEmpty() ? this : fromString(getDomainpart());
- } catch (final InvalidJidException e) {
- // This should never happen.
- throw new AssertionError("Jid " + this.toString() + " invalid");
- }
- }
-
- @Override
- public String toString() {
- return displayjid;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final Jid jid = (Jid) o;
-
- return jid.hashCode() == this.hashCode();
- }
-
- @Override
- public int hashCode() {
- int result = localpart.hashCode();
- result = 31 * result + domainpart.hashCode();
- result = 31 * result + resourcepart.hashCode();
- return result;
- }
-
- public boolean hasLocalpart() {
- return !localpart.isEmpty();
- }
-
- public boolean isBareJid() {
- return this.resourcepart.isEmpty();
- }
-
- public boolean isDomainJid() {
- return !this.hasLocalpart();
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java
deleted file mode 100644
index dcadb92f1..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleCandidate.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.jid.Jid;
-
-public class JingleCandidate {
-
- public static int TYPE_UNKNOWN;
- public static int TYPE_DIRECT = 0;
- public static int TYPE_PROXY = 1;
-
- private boolean ours;
- private boolean usedByCounterpart = false;
- private String cid;
- private String host;
- private int port;
- private int type;
- private Jid jid;
- private int priority;
-
- public JingleCandidate(String cid, boolean ours) {
- this.ours = ours;
- this.cid = cid;
- }
-
- public String getCid() {
- return cid;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public String getHost() {
- return this.host;
- }
-
- public void setJid(final Jid jid) {
- this.jid = jid;
- }
-
- public Jid getJid() {
- return this.jid;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
-
- public int getPort() {
- return this.port;
- }
-
- public void setType(int type) {
- this.type = type;
- }
-
- public void setType(String type) {
- switch (type) {
- case "proxy":
- this.type = TYPE_PROXY;
- break;
- case "direct":
- this.type = TYPE_DIRECT;
- break;
- default:
- this.type = TYPE_UNKNOWN;
- break;
- }
- }
-
- public void setPriority(int i) {
- this.priority = i;
- }
-
- public int getPriority() {
- return this.priority;
- }
-
- public boolean equals(JingleCandidate other) {
- return this.getCid().equals(other.getCid());
- }
-
- public boolean equalValues(JingleCandidate other) {
- return other != null && other.getHost().equals(this.getHost()) && (other.getPort() == this.getPort());
- }
-
- public boolean isOurs() {
- return ours;
- }
-
- public int getType() {
- return this.type;
- }
-
- public static List<JingleCandidate> parse(List<Element> canditates) {
- List<JingleCandidate> parsedCandidates = new ArrayList<>();
- for (Element c : canditates) {
- parsedCandidates.add(JingleCandidate.parse(c));
- }
- return parsedCandidates;
- }
-
- public static JingleCandidate parse(Element candidate) {
- JingleCandidate parsedCandidate = new JingleCandidate(
- candidate.getAttribute("cid"), false);
- parsedCandidate.setHost(candidate.getAttribute("host"));
- parsedCandidate.setJid(candidate.getAttributeAsJid("jid"));
- parsedCandidate.setType(candidate.getAttribute("type"));
- parsedCandidate.setPriority(Integer.parseInt(candidate
- .getAttribute("priority")));
- parsedCandidate
- .setPort(Integer.parseInt(candidate.getAttribute("port")));
- return parsedCandidate;
- }
-
- public Element toElement() {
- Element element = new Element("candidate");
- element.setAttribute("cid", this.getCid());
- element.setAttribute("host", this.getHost());
- element.setAttribute("port", Integer.toString(this.getPort()));
- element.setAttribute("jid", this.getJid().toString());
- element.setAttribute("priority", Integer.toString(this.getPriority()));
- if (this.getType() == TYPE_DIRECT) {
- element.setAttribute("type", "direct");
- } else if (this.getType() == TYPE_PROXY) {
- element.setAttribute("type", "proxy");
- }
- return element;
- }
-
- public void flagAsUsedByCounterpart() {
- this.usedByCounterpart = true;
- }
-
- public boolean isUsedByCounterpart() {
- return this.usedByCounterpart;
- }
-
- public String toString() {
- return this.getHost() + ":" + this.getPort() + " (prio="
- + this.getPriority() + ")";
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
deleted file mode 100644
index 86c445279..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ /dev/null
@@ -1,1076 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import android.util.Log;
-import android.util.Pair;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.crypto.axolotl.AxolotlService;
-import eu.siacs.conversations.crypto.axolotl.OnMessageCreatedCallback;
-import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.entities.DownloadableFile;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.entities.Presence;
-import eu.siacs.conversations.entities.ServiceDiscoveryResult;
-import eu.siacs.conversations.entities.Transferable;
-import eu.siacs.conversations.entities.TransferablePlaceholder;
-import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.services.AbstractConnectionManager;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.OnIqPacketReceived;
-import eu.siacs.conversations.xmpp.jid.Jid;
-import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
-import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
-import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
-import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-
-public class JingleConnection implements Transferable {
- private final SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
-
- private JingleConnectionManager mJingleConnectionManager;
- private XmppConnectionService mXmppConnectionService;
-
- protected static final int JINGLE_STATUS_INITIATED = 0;
- protected static final int JINGLE_STATUS_ACCEPTED = 1;
- protected static final int JINGLE_STATUS_FINISHED = 4;
- protected static final int JINGLE_STATUS_TRANSMITTING = 5;
- protected static final int JINGLE_STATUS_FAILED = 99;
-
- private Content.Version ftVersion = Content.Version.FT_3;
-
- private int ibbBlockSize = 8192;
-
- private int mJingleStatus = -1;
- private int mStatus = Transferable.STATUS_UNKNOWN;
- private Message message;
- private String sessionId;
- private Account account;
- private Jid initiator;
- private Jid responder;
- private List<JingleCandidate> candidates = new ArrayList<>();
- private ConcurrentHashMap<String, JingleSocks5Transport> connections = new ConcurrentHashMap<>();
-
- private String transportId;
- private Element fileOffer;
- private DownloadableFile file = null;
-
- private String contentName;
- private String contentCreator;
-
- private int mProgress = 0;
-
- private boolean receivedCandidate = false;
- private boolean sentCandidate = false;
-
- private boolean acceptedAutomatically = false;
-
- private XmppAxolotlMessage mXmppAxolotlMessage;
-
- private JingleTransport transport = null;
-
- private OutputStream mFileOutputStream;
- private InputStream mFileInputStream;
-
- private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- if (packet.getType() != IqPacket.TYPE.RESULT) {
- fail();
- }
- }
- };
-
- final OnFileTransmissionStatusChanged onFileTransmissionSatusChanged = new OnFileTransmissionStatusChanged() {
-
- @Override
- public void onFileTransmitted(DownloadableFile file) {
- if (responder.equals(account.getJid())) {
- sendSuccess();
- mXmppConnectionService.getFileBackend().updateFileParams(message);
- mXmppConnectionService.databaseBackend.createMessage(message);
- mXmppConnectionService.markMessage(message,Message.STATUS_RECEIVED);
- if (acceptedAutomatically) {
- message.markUnread();
- if (message.getEncryption() == Message.ENCRYPTION_PGP) {
- account.getPgpDecryptionService().decrypt(message, true);
- } else {
- JingleConnection.this.mXmppConnectionService.getNotificationService().push(message);
- }
- }
- } else {
- if (message.getEncryption() == Message.ENCRYPTION_PGP) {
- account.getPgpDecryptionService().decrypt(message, false);
- }
- if (message.getEncryption() == Message.ENCRYPTION_PGP || message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
- file.delete();
- }
- }
- Log.d(Config.LOGTAG,"successfully transmitted file:" + file.getAbsolutePath()+" ("+file.getSha1Sum()+")");
- if (message.getEncryption() != Message.ENCRYPTION_PGP) {
- mXmppConnectionService.getFileBackend().updateMediaScanner(file);
- }
- }
-
- @Override
- public void onFileTransferAborted() {
- JingleConnection.this.sendCancel();
- JingleConnection.this.fail();
- }
- };
-
- public InputStream getFileInputStream() {
- return this.mFileInputStream;
- }
-
- public OutputStream getFileOutputStream() {
- return this.mFileOutputStream;
- }
-
- private OnProxyActivated onProxyActivated = new OnProxyActivated() {
-
- @Override
- public void success() {
- if (initiator.equals(account.getJid())) {
- Log.d(Config.LOGTAG, "we were initiating. sending file");
- transport.send(file, onFileTransmissionSatusChanged);
- } else {
- transport.receive(file, onFileTransmissionSatusChanged);
- Log.d(Config.LOGTAG, "we were responding. receiving file");
- }
- }
-
- @Override
- public void failed() {
- Log.d(Config.LOGTAG, "proxy activation failed");
- }
- };
-
- public JingleConnection(JingleConnectionManager mJingleConnectionManager) {
- this.mJingleConnectionManager = mJingleConnectionManager;
- this.mXmppConnectionService = mJingleConnectionManager
- .getXmppConnectionService();
- }
-
- public String getSessionId() {
- return this.sessionId;
- }
-
- public Account getAccount() {
- return this.account;
- }
-
- public Jid getCounterPart() {
- return this.message.getCounterpart();
- }
-
- public void deliverPacket(JinglePacket packet) {
- boolean returnResult = true;
- if (packet.isAction("session-terminate")) {
- Reason reason = packet.getReason();
- if (reason != null) {
- if (reason.hasChild("cancel")) {
- this.fail();
- } else if (reason.hasChild("success")) {
- this.receiveSuccess();
- } else {
- this.fail();
- }
- } else {
- this.fail();
- }
- } else if (packet.isAction("session-accept")) {
- returnResult = receiveAccept(packet);
- } else if (packet.isAction("transport-info")) {
- returnResult = receiveTransportInfo(packet);
- } else if (packet.isAction("transport-replace")) {
- if (packet.getJingleContent().hasIbbTransport()) {
- returnResult = this.receiveFallbackToIbb(packet);
- } else {
- returnResult = false;
- Log.d(Config.LOGTAG, "trying to fallback to something unknown"
- + packet.toString());
- }
- } else if (packet.isAction("transport-accept")) {
- returnResult = this.receiveTransportAccept(packet);
- } else {
- Log.d(Config.LOGTAG, "packet arrived in connection. action was "
- + packet.getAction());
- returnResult = false;
- }
- IqPacket response;
- if (returnResult) {
- response = packet.generateResponse(IqPacket.TYPE.RESULT);
-
- } else {
- response = packet.generateResponse(IqPacket.TYPE.ERROR);
- }
- mXmppConnectionService.sendIqPacket(account,response,null);
- }
-
- public void init(final Message message) {
- if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
- Conversation conversation = message.getConversation();
- conversation.getAccount().getAxolotlService().prepareKeyTransportMessage(conversation, new OnMessageCreatedCallback() {
- @Override
- public void run(XmppAxolotlMessage xmppAxolotlMessage) {
- if (xmppAxolotlMessage != null) {
- init(message, xmppAxolotlMessage);
- } else {
- fail();
- }
- }
- });
- } else {
- init(message, null);
- }
- }
-
- private void init(Message message, XmppAxolotlMessage xmppAxolotlMessage) {
- this.mXmppAxolotlMessage = xmppAxolotlMessage;
- this.contentCreator = "initiator";
- this.contentName = this.mJingleConnectionManager.nextRandomId();
- this.message = message;
- this.account = message.getConversation().getAccount();
- upgradeNamespace();
- this.message.setTransferable(this);
- this.mStatus = Transferable.STATUS_UPLOADING;
- this.initiator = this.account.getJid();
- this.responder = this.message.getCounterpart();
- this.sessionId = this.mJingleConnectionManager.nextRandomId();
- this.transportId = this.mJingleConnectionManager.nextRandomId();
- if (this.candidates.size() > 0) {
- this.sendInitRequest();
- } else {
- this.mJingleConnectionManager.getPrimaryCandidate(account,
- new OnPrimaryCandidateFound() {
-
- @Override
- public void onPrimaryCandidateFound(boolean success,
- final JingleCandidate candidate) {
- if (success) {
- final JingleSocks5Transport socksConnection = new JingleSocks5Transport(
- JingleConnection.this, candidate);
- connections.put(candidate.getCid(),
- socksConnection);
- socksConnection
- .connect(new OnTransportConnected() {
-
- @Override
- public void failed() {
- Log.d(Config.LOGTAG,
- "connection to our own primary candidete failed");
- sendInitRequest();
- }
-
- @Override
- public void established() {
- Log.d(Config.LOGTAG,
- "successfully connected to our own primary candidate");
- mergeCandidate(candidate);
- sendInitRequest();
- }
- });
- mergeCandidate(candidate);
- } else {
- Log.d(Config.LOGTAG, "no primary candidate of our own was found");
- sendInitRequest();
- }
- }
- });
- }
-
- }
-
- private void upgradeNamespace() {
- Jid jid = this.message.getCounterpart();
- String resource = jid != null ?jid.getResourcepart() : null;
- if (resource != null) {
- Presence presence = this.account.getRoster().getContact(jid).getPresences().getPresences().get(resource);
- ServiceDiscoveryResult result = presence != null ? presence.getServiceDiscoveryResult() : null;
- if (result != null) {
- List<String> features = result.getFeatures();
- if (features.contains(Content.Version.FT_4.getNamespace())) {
- this.ftVersion = Content.Version.FT_4;
- }
- }
- }
- }
-
- public void init(Account account, JinglePacket packet) {
- this.mJingleStatus = JINGLE_STATUS_INITIATED;
- Conversation conversation = this.mXmppConnectionService
- .findOrCreateConversation(account,
- packet.getFrom().toBareJid(), false);
- this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
- this.message.setStatus(Message.STATUS_RECEIVED);
- this.mStatus = Transferable.STATUS_OFFER;
- this.message.setTransferable(this);
- final Jid from = packet.getFrom();
- this.message.setCounterpart(from);
- this.account = account;
- this.initiator = packet.getFrom();
- this.responder = this.account.getJid();
- this.sessionId = packet.getSessionId();
- Content content = packet.getJingleContent();
- this.contentCreator = content.getAttribute("creator");
- this.contentName = content.getAttribute("name");
- this.transportId = content.getTransportId();
- this.mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
- this.ftVersion = content.getVersion();
- if (ftVersion == null) {
- this.sendCancel();
- this.fail();
- return;
- }
- this.fileOffer = content.getFileOffer(this.ftVersion);
-
- mXmppConnectionService.sendIqPacket(account,packet.generateResponse(IqPacket.TYPE.RESULT),null);
-
- if (fileOffer != null) {
- Element encrypted = fileOffer.findChild("encrypted", AxolotlService.PEP_PREFIX);
- if (encrypted != null) {
- this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().toBareJid());
- }
- Element fileSize = fileOffer.findChild("size");
- Element fileNameElement = fileOffer.findChild("name");
- if (fileNameElement != null) {
- String[] filename = fileNameElement.getContent()
- .toLowerCase(Locale.US).toLowerCase().split("\\.");
- String filename_new = fileDateFormat.format(new Date(message.getTimeSent()))+"_"+message.getUuid().substring(0,4);
- String extension = filename[filename.length - 1];
- if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
- message.setType(Message.TYPE_IMAGE);
- message.setRelativeFilePath(filename_new+"."+extension);
- } else if (VALID_CRYPTO_EXTENSIONS.contains(
- filename[filename.length - 1])) {
- if (filename.length == 3) {
- extension = filename[filename.length - 2];
- if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
- message.setType(Message.TYPE_IMAGE);
- message.setRelativeFilePath(filename_new+"."+extension);
- } else {
- message.setType(Message.TYPE_FILE);
- }
- if (filename[filename.length - 1].equals("otr")) {
- message.setEncryption(Message.ENCRYPTION_OTR);
- } else {
- message.setEncryption(Message.ENCRYPTION_PGP);
- }
- }
- } else {
- message.setType(Message.TYPE_FILE);
- }
- if (message.getType() == Message.TYPE_FILE) {
- String suffix = "";
- if (!fileNameElement.getContent().isEmpty()) {
- String parts[] = fileNameElement.getContent().split("/");
- suffix = parts[parts.length - 1];
- if (message.getEncryption() == Message.ENCRYPTION_OTR && suffix.endsWith(".otr")) {
- suffix = suffix.substring(0,suffix.length() - 4);
- } else if (message.getEncryption() == Message.ENCRYPTION_PGP && (suffix.endsWith(".pgp") || suffix.endsWith(".gpg"))) {
- suffix = suffix.substring(0,suffix.length() - 4);
- }
- }
- message.setRelativeFilePath(filename_new+"_"+suffix);
- }
- long size = Long.parseLong(fileSize.getContent());
- message.setBody(Long.toString(size));
- conversation.add(message);
- mXmppConnectionService.updateConversationUi();
- if (mJingleConnectionManager.hasStoragePermission()
- && size < this.mJingleConnectionManager.getAutoAcceptFileSize()) {
- Log.d(Config.LOGTAG, "auto accepting file from "+ packet.getFrom());
- this.acceptedAutomatically = true;
- this.sendAccept();
- } else {
- message.markUnread();
- Log.d(Config.LOGTAG,
- "not auto accepting new file offer with size: "
- + size
- + " allowed size:"
- + this.mJingleConnectionManager
- .getAutoAcceptFileSize());
- this.mXmppConnectionService.getNotificationService().push(message);
- }
- this.file = this.mXmppConnectionService.getFileBackend().getFile(message, false);
- if (mXmppAxolotlMessage != null) {
- XmppAxolotlMessage.XmppAxolotlKeyTransportMessage transportMessage = account.getAxolotlService().processReceivingKeyTransportMessage(mXmppAxolotlMessage);
- if (transportMessage != null) {
- message.setEncryption(Message.ENCRYPTION_AXOLOTL);
- this.file.setKey(transportMessage.getKey());
- this.file.setIv(transportMessage.getIv());
- message.setFingerprint(transportMessage.getFingerprint());
- } else {
- Log.d(Config.LOGTAG,"could not process KeyTransportMessage");
- }
- } else if (message.getEncryption() == Message.ENCRYPTION_OTR) {
- byte[] key = conversation.getSymmetricKey();
- if (key == null) {
- this.sendCancel();
- this.fail();
- return;
- } else {
- this.file.setKeyAndIv(key);
- }
- }
- this.mFileOutputStream = AbstractConnectionManager.createOutputStream(this.file,message.getEncryption() == Message.ENCRYPTION_AXOLOTL);
- if (message.getEncryption() == Message.ENCRYPTION_OTR && Config.REPORT_WRONG_FILESIZE_IN_OTR_JINGLE) {
- this.file.setExpectedSize((size / 16 + 1) * 16);
- } else {
- this.file.setExpectedSize(size);
- }
- Log.d(Config.LOGTAG, "receiving file: expecting size of " + this.file.getExpectedSize());
- } else {
- this.sendCancel();
- this.fail();
- }
- } else {
- this.sendCancel();
- this.fail();
- }
- }
-
- private void sendInitRequest() {
- JinglePacket packet = this.bootstrapPacket("session-initiate");
- Content content = new Content(this.contentCreator, this.contentName);
- if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
- content.setTransportId(this.transportId);
- this.file = this.mXmppConnectionService.getFileBackend().getFile(message, false);
- Pair<InputStream,Integer> pair;
- try {
- if (message.getEncryption() == Message.ENCRYPTION_OTR) {
- Conversation conversation = this.message.getConversation();
- if (!this.mXmppConnectionService.renewSymmetricKey(conversation)) {
- Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not set symmetric key");
- cancel();
- }
- this.file.setKeyAndIv(conversation.getSymmetricKey());
- pair = AbstractConnectionManager.createInputStream(this.file, false);
- this.file.setExpectedSize(pair.second);
- content.setFileOffer(this.file, true, this.ftVersion);
- } else if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
- this.file.setKey(mXmppAxolotlMessage.getInnerKey());
- this.file.setIv(mXmppAxolotlMessage.getIV());
- pair = AbstractConnectionManager.createInputStream(this.file, true);
- this.file.setExpectedSize(pair.second);
- content.setFileOffer(this.file, false, this.ftVersion).addChild(mXmppAxolotlMessage.toElement());
- } else {
- pair = AbstractConnectionManager.createInputStream(this.file, false);
- this.file.setExpectedSize(pair.second);
- content.setFileOffer(this.file, false, this.ftVersion);
- }
- } catch (FileNotFoundException e) {
- cancel();
- return;
- }
- this.mFileInputStream = pair.first;
- content.setTransportId(this.transportId);
- content.socks5transport().setChildren(getCandidatesAsElements());
- packet.setContent(content);
- this.sendJinglePacket(packet,new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- if (packet.getType() == IqPacket.TYPE.RESULT) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": other party received offer");
- mJingleStatus = JINGLE_STATUS_INITIATED;
- mXmppConnectionService.markMessage(message, Message.STATUS_OFFERED);
- } else {
- fail();
- }
- }
- });
-
- }
- }
-
- private List<Element> getCandidatesAsElements() {
- List<Element> elements = new ArrayList<>();
- for (JingleCandidate c : this.candidates) {
- if (c.isOurs()) {
- elements.add(c.toElement());
- }
- }
- return elements;
- }
-
- private void sendAccept() {
- mJingleStatus = JINGLE_STATUS_ACCEPTED;
- this.mStatus = Transferable.STATUS_DOWNLOADING;
- mXmppConnectionService.updateConversationUi();
- this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() {
- @Override
- public void onPrimaryCandidateFound(boolean success, final JingleCandidate candidate) {
- final JinglePacket packet = bootstrapPacket("session-accept");
- final Content content = new Content(contentCreator,contentName);
- content.setFileOffer(fileOffer, ftVersion);
- content.setTransportId(transportId);
- if (success && candidate != null && !equalCandidateExists(candidate)) {
- final JingleSocks5Transport socksConnection = new JingleSocks5Transport(
- JingleConnection.this,
- candidate);
- connections.put(candidate.getCid(), socksConnection);
- socksConnection.connect(new OnTransportConnected() {
-
- @Override
- public void failed() {
- Log.d(Config.LOGTAG,"connection to our own primary candidate failed");
- content.socks5transport().setChildren(getCandidatesAsElements());
- packet.setContent(content);
- sendJinglePacket(packet);
- connectNextCandidate();
- }
-
- @Override
- public void established() {
- Log.d(Config.LOGTAG, "connected to primary candidate");
- mergeCandidate(candidate);
- content.socks5transport().setChildren(getCandidatesAsElements());
- packet.setContent(content);
- sendJinglePacket(packet);
- connectNextCandidate();
- }
- });
- } else {
- Log.d(Config.LOGTAG,"did not find a primary candidate for ourself");
- content.socks5transport().setChildren(getCandidatesAsElements());
- packet.setContent(content);
- sendJinglePacket(packet);
- connectNextCandidate();
- }
- }
- });
- }
-
- private JinglePacket bootstrapPacket(String action) {
- JinglePacket packet = new JinglePacket();
- packet.setAction(action);
- packet.setFrom(account.getJid());
- packet.setTo(this.message.getCounterpart());
- packet.setSessionId(this.sessionId);
- packet.setInitiator(this.initiator);
- return packet;
- }
-
- private void sendJinglePacket(JinglePacket packet) {
- mXmppConnectionService.sendIqPacket(account,packet,responseListener);
- }
-
- private void sendJinglePacket(JinglePacket packet, OnIqPacketReceived callback) {
- mXmppConnectionService.sendIqPacket(account,packet,callback);
- }
-
- private boolean receiveAccept(JinglePacket packet) {
- Content content = packet.getJingleContent();
- mergeCandidates(JingleCandidate.parse(content.socks5transport()
- .getChildren()));
- this.mJingleStatus = JINGLE_STATUS_ACCEPTED;
- mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
- this.connectNextCandidate();
- return true;
- }
-
- private boolean receiveTransportInfo(JinglePacket packet) {
- Content content = packet.getJingleContent();
- if (content.hasSocks5Transport()) {
- if (content.socks5transport().hasChild("activated")) {
- if ((this.transport != null) && (this.transport instanceof JingleSocks5Transport)) {
- onProxyActivated.success();
- } else {
- String cid = content.socks5transport().findChild("activated").getAttribute("cid");
- Log.d(Config.LOGTAG, "received proxy activated (" + cid
- + ")prior to choosing our own transport");
- JingleSocks5Transport connection = this.connections.get(cid);
- if (connection != null) {
- connection.setActivated(true);
- } else {
- Log.d(Config.LOGTAG, "activated connection not found");
- this.sendCancel();
- this.fail();
- }
- }
- return true;
- } else if (content.socks5transport().hasChild("proxy-error")) {
- onProxyActivated.failed();
- return true;
- } else if (content.socks5transport().hasChild("candidate-error")) {
- Log.d(Config.LOGTAG, "received candidate error");
- this.receivedCandidate = true;
- if ((mJingleStatus == JINGLE_STATUS_ACCEPTED)
- && (this.sentCandidate)) {
- this.connect();
- }
- return true;
- } else if (content.socks5transport().hasChild("candidate-used")) {
- String cid = content.socks5transport()
- .findChild("candidate-used").getAttribute("cid");
- if (cid != null) {
- Log.d(Config.LOGTAG, "candidate used by counterpart:" + cid);
- JingleCandidate candidate = getCandidate(cid);
- candidate.flagAsUsedByCounterpart();
- this.receivedCandidate = true;
- if ((mJingleStatus == JINGLE_STATUS_ACCEPTED)
- && (this.sentCandidate)) {
- this.connect();
- } else {
- Log.d(Config.LOGTAG,
- "ignoring because file is already in transmission or we haven't sent our candidate yet");
- }
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- } else {
- return true;
- }
- }
-
- private void connect() {
- final JingleSocks5Transport connection = chooseConnection();
- this.transport = connection;
- if (connection == null) {
- Log.d(Config.LOGTAG, "could not find suitable candidate");
- this.disconnectSocks5Connections();
- if (this.initiator.equals(account.getJid())) {
- this.sendFallbackToIbb();
- }
- } else {
- this.mJingleStatus = JINGLE_STATUS_TRANSMITTING;
- if (connection.needsActivation()) {
- if (connection.getCandidate().isOurs()) {
- final String sid;
- if (ftVersion == Content.Version.FT_3) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": use session ID instead of transport ID to activate proxy");
- sid = getSessionId();
- } else {
- sid = getTransportId();
- }
- Log.d(Config.LOGTAG, "candidate "
- + connection.getCandidate().getCid()
- + " was our proxy. going to activate");
- IqPacket activation = new IqPacket(IqPacket.TYPE.SET);
- activation.setTo(connection.getCandidate().getJid());
- activation.query("http://jabber.org/protocol/bytestreams")
- .setAttribute("sid", sid);
- activation.query().addChild("activate")
- .setContent(this.getCounterPart().toString());
- mXmppConnectionService.sendIqPacket(account,activation,
- new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account,
- IqPacket packet) {
- if (packet.getType() != IqPacket.TYPE.RESULT) {
- onProxyActivated.failed();
- } else {
- onProxyActivated.success();
- sendProxyActivated(connection.getCandidate().getCid());
- }
- }
- });
- } else {
- Log.d(Config.LOGTAG,
- "candidate "
- + connection.getCandidate().getCid()
- + " was a proxy. waiting for other party to activate");
- }
- } else {
- if (initiator.equals(account.getJid())) {
- Log.d(Config.LOGTAG, "we were initiating. sending file");
- connection.send(file, onFileTransmissionSatusChanged);
- } else {
- Log.d(Config.LOGTAG, "we were responding. receiving file");
- connection.receive(file, onFileTransmissionSatusChanged);
- }
- }
- }
- }
-
- private JingleSocks5Transport chooseConnection() {
- JingleSocks5Transport connection = null;
- for (Entry<String, JingleSocks5Transport> cursor : connections
- .entrySet()) {
- JingleSocks5Transport currentConnection = cursor.getValue();
- // Log.d(Config.LOGTAG,"comparing candidate: "+currentConnection.getCandidate().toString());
- if (currentConnection.isEstablished()
- && (currentConnection.getCandidate().isUsedByCounterpart() || (!currentConnection
- .getCandidate().isOurs()))) {
- // Log.d(Config.LOGTAG,"is usable");
- if (connection == null) {
- connection = currentConnection;
- } else {
- if (connection.getCandidate().getPriority() < currentConnection
- .getCandidate().getPriority()) {
- connection = currentConnection;
- } else if (connection.getCandidate().getPriority() == currentConnection
- .getCandidate().getPriority()) {
- // Log.d(Config.LOGTAG,"found two candidates with same priority");
- if (initiator.equals(account.getJid())) {
- if (currentConnection.getCandidate().isOurs()) {
- connection = currentConnection;
- }
- } else {
- if (!currentConnection.getCandidate().isOurs()) {
- connection = currentConnection;
- }
- }
- }
- }
- }
- }
- return connection;
- }
-
- private void sendSuccess() {
- JinglePacket packet = bootstrapPacket("session-terminate");
- Reason reason = new Reason();
- reason.addChild("success");
- packet.setReason(reason);
- this.sendJinglePacket(packet);
- this.disconnectSocks5Connections();
- this.mJingleStatus = JINGLE_STATUS_FINISHED;
- this.message.setStatus(Message.STATUS_RECEIVED);
- this.message.setTransferable(null);
- this.mXmppConnectionService.updateMessage(message);
- this.mJingleConnectionManager.finishConnection(this);
- }
-
- private void sendFallbackToIbb() {
- Log.d(Config.LOGTAG, "sending fallback to ibb");
- JinglePacket packet = this.bootstrapPacket("transport-replace");
- Content content = new Content(this.contentCreator, this.contentName);
- this.transportId = this.mJingleConnectionManager.nextRandomId();
- content.setTransportId(this.transportId);
- content.ibbTransport().setAttribute("block-size",
- Integer.toString(this.ibbBlockSize));
- packet.setContent(content);
- this.sendJinglePacket(packet);
- }
-
- private boolean receiveFallbackToIbb(JinglePacket packet) {
- Log.d(Config.LOGTAG, "receiving fallack to ibb");
- String receivedBlockSize = packet.getJingleContent().ibbTransport()
- .getAttribute("block-size");
- if (receivedBlockSize != null) {
- int bs = Integer.parseInt(receivedBlockSize);
- if (bs > this.ibbBlockSize) {
- this.ibbBlockSize = bs;
- }
- }
- this.transportId = packet.getJingleContent().getTransportId();
- this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
- this.transport.receive(file, onFileTransmissionSatusChanged);
- JinglePacket answer = bootstrapPacket("transport-accept");
- Content content = new Content("initiator", "a-file-offer");
- content.setTransportId(this.transportId);
- content.ibbTransport().setAttribute("block-size",this.ibbBlockSize);
- answer.setContent(content);
- this.sendJinglePacket(answer);
- return true;
- }
-
- private boolean receiveTransportAccept(JinglePacket packet) {
- if (packet.getJingleContent().hasIbbTransport()) {
- String receivedBlockSize = packet.getJingleContent().ibbTransport()
- .getAttribute("block-size");
- if (receivedBlockSize != null) {
- int bs = Integer.parseInt(receivedBlockSize);
- if (bs > this.ibbBlockSize) {
- this.ibbBlockSize = bs;
- }
- }
- this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
- this.transport.connect(new OnTransportConnected() {
-
- @Override
- public void failed() {
- Log.d(Config.LOGTAG, "ibb open failed");
- }
-
- @Override
- public void established() {
- JingleConnection.this.transport.send(file,
- onFileTransmissionSatusChanged);
- }
- });
- return true;
- } else {
- return false;
- }
- }
-
- private void receiveSuccess() {
- this.mJingleStatus = JINGLE_STATUS_FINISHED;
- this.mXmppConnectionService.markMessage(this.message,Message.STATUS_SEND_RECEIVED);
- this.disconnectSocks5Connections();
- if (this.transport != null && this.transport instanceof JingleInbandTransport) {
- this.transport.disconnect();
- }
- this.message.setTransferable(null);
- this.mJingleConnectionManager.finishConnection(this);
- }
-
- public void cancel() {
- this.disconnectSocks5Connections();
- if (this.transport != null && this.transport instanceof JingleInbandTransport) {
- this.transport.disconnect();
- }
- this.sendCancel();
- this.mJingleConnectionManager.finishConnection(this);
- if (this.responder.equals(account.getJid())) {
- this.message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_FAILED));
- if (this.file!=null) {
- file.delete();
- }
- this.mXmppConnectionService.updateConversationUi();
- } else {
- this.mXmppConnectionService.markMessage(this.message,
- Message.STATUS_SEND_FAILED);
- this.message.setTransferable(null);
- }
- }
-
- private void fail() {
- this.mJingleStatus = JINGLE_STATUS_FAILED;
- this.disconnectSocks5Connections();
- if (this.transport != null && this.transport instanceof JingleInbandTransport) {
- this.transport.disconnect();
- }
- FileBackend.close(mFileInputStream);
- FileBackend.close(mFileOutputStream);
- if (this.message != null) {
- if (this.responder.equals(account.getJid())) {
- this.message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_FAILED));
- if (this.file!=null) {
- file.delete();
- }
- this.mXmppConnectionService.updateConversationUi();
- } else {
- this.mXmppConnectionService.markMessage(this.message,
- Message.STATUS_SEND_FAILED);
- this.message.setTransferable(null);
- }
- }
- this.mJingleConnectionManager.finishConnection(this);
- }
-
- private void sendCancel() {
- JinglePacket packet = bootstrapPacket("session-terminate");
- Reason reason = new Reason();
- reason.addChild("cancel");
- packet.setReason(reason);
- this.sendJinglePacket(packet);
- }
-
- private void connectNextCandidate() {
- for (JingleCandidate candidate : this.candidates) {
- if ((!connections.containsKey(candidate.getCid()) && (!candidate
- .isOurs()))) {
- this.connectWithCandidate(candidate);
- return;
- }
- }
- this.sendCandidateError();
- }
-
- private void connectWithCandidate(final JingleCandidate candidate) {
- final JingleSocks5Transport socksConnection = new JingleSocks5Transport(
- this, candidate);
- connections.put(candidate.getCid(), socksConnection);
- socksConnection.connect(new OnTransportConnected() {
-
- @Override
- public void failed() {
- Log.d(Config.LOGTAG,
- "connection failed with " + candidate.getHost() + ":"
- + candidate.getPort());
- connectNextCandidate();
- }
-
- @Override
- public void established() {
- Log.d(Config.LOGTAG,
- "established connection with " + candidate.getHost()
- + ":" + candidate.getPort());
- sendCandidateUsed(candidate.getCid());
- }
- });
- }
-
- private void disconnectSocks5Connections() {
- Iterator<Entry<String, JingleSocks5Transport>> it = this.connections
- .entrySet().iterator();
- while (it.hasNext()) {
- Entry<String, JingleSocks5Transport> pairs = it.next();
- pairs.getValue().disconnect();
- it.remove();
- }
- }
-
- private void sendProxyActivated(String cid) {
- JinglePacket packet = bootstrapPacket("transport-info");
- Content content = new Content(this.contentCreator, this.contentName);
- content.setTransportId(this.transportId);
- content.socks5transport().addChild("activated")
- .setAttribute("cid", cid);
- packet.setContent(content);
- this.sendJinglePacket(packet);
- }
-
- private void sendCandidateUsed(final String cid) {
- JinglePacket packet = bootstrapPacket("transport-info");
- Content content = new Content(this.contentCreator, this.contentName);
- content.setTransportId(this.transportId);
- content.socks5transport().addChild("candidate-used")
- .setAttribute("cid", cid);
- packet.setContent(content);
- this.sentCandidate = true;
- if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) {
- connect();
- }
- this.sendJinglePacket(packet);
- }
-
- private void sendCandidateError() {
- JinglePacket packet = bootstrapPacket("transport-info");
- Content content = new Content(this.contentCreator, this.contentName);
- content.setTransportId(this.transportId);
- content.socks5transport().addChild("candidate-error");
- packet.setContent(content);
- this.sentCandidate = true;
- if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) {
- connect();
- }
- this.sendJinglePacket(packet);
- }
-
- public Jid getInitiator() {
- return this.initiator;
- }
-
- public Jid getResponder() {
- return this.responder;
- }
-
- public int getJingleStatus() {
- return this.mJingleStatus;
- }
-
- private boolean equalCandidateExists(JingleCandidate candidate) {
- for (JingleCandidate c : this.candidates) {
- if (c.equalValues(candidate)) {
- return true;
- }
- }
- return false;
- }
-
- private void mergeCandidate(JingleCandidate candidate) {
- for (JingleCandidate c : this.candidates) {
- if (c.equals(candidate)) {
- return;
- }
- }
- this.candidates.add(candidate);
- }
-
- private void mergeCandidates(List<JingleCandidate> candidates) {
- for (JingleCandidate c : candidates) {
- mergeCandidate(c);
- }
- }
-
- private JingleCandidate getCandidate(String cid) {
- for (JingleCandidate c : this.candidates) {
- if (c.getCid().equals(cid)) {
- return c;
- }
- }
- return null;
- }
-
- public void updateProgress(int i) {
- this.mProgress = i;
- mXmppConnectionService.updateConversationUi();
- }
-
- public String getTransportId() {
- return this.transportId;
- }
-
- public Content.Version getFtVersion() {
- return this.ftVersion;
- }
-
- interface OnProxyActivated {
- public void success();
-
- public void failed();
- }
-
- public boolean hasTransportId(String sid) {
- return sid.equals(this.transportId);
- }
-
- public JingleTransport getTransport() {
- return this.transport;
- }
-
- public boolean start() {
- if (account.getStatus() == Account.State.ONLINE) {
- if (mJingleStatus == JINGLE_STATUS_INITIATED) {
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- sendAccept();
- }
- }).start();
- }
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public int getStatus() {
- return this.mStatus;
- }
-
- @Override
- public long getFileSize() {
- if (this.file != null) {
- return this.file.getExpectedSize();
- } else {
- return 0;
- }
- }
-
- @Override
- public int getProgress() {
- return this.mProgress;
- }
-
- public AbstractConnectionManager getConnectionManager() {
- return this.mJingleConnectionManager;
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
deleted file mode 100644
index 0f0361cd3..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import android.annotation.SuppressLint;
-import android.util.Log;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.entities.Transferable;
-import eu.siacs.conversations.services.AbstractConnectionManager;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.utils.Xmlns;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.OnIqPacketReceived;
-import eu.siacs.conversations.xmpp.jid.Jid;
-import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
-import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-
-public class JingleConnectionManager extends AbstractConnectionManager {
- private List<JingleConnection> connections = new CopyOnWriteArrayList<>();
-
- private HashMap<Jid, JingleCandidate> primaryCandidates = new HashMap<>();
-
- @SuppressLint("TrulyRandom")
- private SecureRandom random = new SecureRandom();
-
- public JingleConnectionManager(XmppConnectionService service) {
- super(service);
- }
-
- public void deliverPacket(Account account, JinglePacket packet) {
- if (packet.isAction("session-initiate")) {
- JingleConnection connection = new JingleConnection(this);
- connection.init(account, packet);
- connections.add(connection);
- } else {
- for (JingleConnection connection : connections) {
- if (connection.getAccount() == account
- && connection.getSessionId().equals(
- packet.getSessionId())
- && connection.getCounterPart().equals(packet.getFrom())) {
- connection.deliverPacket(packet);
- return;
- }
- }
- IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR);
- Element error = response.addChild("error");
- error.setAttribute("type", "cancel");
- error.addChild("item-not-found",
- "urn:ietf:params:xml:ns:xmpp-stanzas");
- error.addChild("unknown-session", "urn:xmpp:jingle:errors:1");
- account.getXmppConnection().sendIqPacket(response, null);
- }
- }
-
- public JingleConnection createNewConnection(Message message) {
- Transferable old = message.getTransferable();
- if (old != null) {
- old.cancel();
- }
- JingleConnection connection = new JingleConnection(this);
- mXmppConnectionService.markMessage(message,Message.STATUS_WAITING);
- connection.init(message);
- this.connections.add(connection);
- return connection;
- }
-
- public JingleConnection createNewConnection(final JinglePacket packet) {
- JingleConnection connection = new JingleConnection(this);
- this.connections.add(connection);
- return connection;
- }
-
- public void finishConnection(JingleConnection connection) {
- this.connections.remove(connection);
- }
-
- public void getPrimaryCandidate(Account account,
- final OnPrimaryCandidateFound listener) {
- if (Config.DISABLE_PROXY_LOOKUP) {
- listener.onPrimaryCandidateFound(false, null);
- return;
- }
- if (!this.primaryCandidates.containsKey(account.getJid().toBareJid())) {
- final Jid proxy = account.getXmppConnection().findDiscoItemByFeature(Xmlns.BYTE_STREAMS);
- if (proxy != null) {
- IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
- iq.setTo(proxy);
- iq.query(Xmlns.BYTE_STREAMS);
- account.getXmppConnection().sendIqPacket(iq,new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- Element streamhost = packet.query().findChild("streamhost",Xmlns.BYTE_STREAMS);
- final String host = streamhost == null ? null : streamhost.getAttribute("host");
- final String port = streamhost == null ? null : streamhost.getAttribute("port");
- if (host != null && port != null) {
- try {
- JingleCandidate candidate = new JingleCandidate(nextRandomId(), true);
- candidate.setHost(host);
- candidate.setPort(Integer.parseInt(port));
- candidate.setType(JingleCandidate.TYPE_PROXY);
- candidate.setJid(proxy);
- candidate.setPriority(655360 + 65535);
- primaryCandidates.put(account.getJid().toBareJid(),candidate);
- listener.onPrimaryCandidateFound(true,candidate);
- } catch (final NumberFormatException e) {
- listener.onPrimaryCandidateFound(false,null);
- return;
- }
- } else {
- listener.onPrimaryCandidateFound(false,null);
- }
- }
- });
- } else {
- listener.onPrimaryCandidateFound(false, null);
- }
-
- } else {
- listener.onPrimaryCandidateFound(true,
- this.primaryCandidates.get(account.getJid().toBareJid()));
- }
- }
-
- public String nextRandomId() {
- return new BigInteger(50, random).toString(32);
- }
-
- public void deliverIbbPacket(Account account, IqPacket packet) {
- String sid = null;
- Element payload = null;
- if (packet.hasChild("open", "http://jabber.org/protocol/ibb")) {
- payload = packet.findChild("open", "http://jabber.org/protocol/ibb");
- sid = payload.getAttribute("sid");
- } else if (packet.hasChild("data", "http://jabber.org/protocol/ibb")) {
- payload = packet.findChild("data", "http://jabber.org/protocol/ibb");
- sid = payload.getAttribute("sid");
- }
- if (sid != null) {
- for (JingleConnection connection : connections) {
- if (connection.getAccount() == account
- && connection.hasTransportId(sid)) {
- JingleTransport transport = connection.getTransport();
- if (transport instanceof JingleInbandTransport) {
- JingleInbandTransport inbandTransport = (JingleInbandTransport) transport;
- inbandTransport.deliverPayload(packet, payload);
- return;
- }
- }
- }
- Log.d(Config.LOGTAG,"couldn't deliver payload: " + payload.toString());
- } else {
- Log.d(Config.LOGTAG, "no sid found in incoming ibb packet");
- }
- }
-
- public void cancelInTransmission() {
- for (JingleConnection connection : this.connections) {
- if (connection.getJingleStatus() == JingleConnection.JINGLE_STATUS_TRANSMITTING) {
- connection.cancel();
- }
- }
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java
deleted file mode 100644
index 0b0cb4083..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import android.util.Base64;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.DownloadableFile;
-import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.utils.CryptoHelper;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.OnIqPacketReceived;
-import eu.siacs.conversations.xmpp.jid.Jid;
-import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-
-public class JingleInbandTransport extends JingleTransport {
-
- private Account account;
- private Jid counterpart;
- private int blockSize;
- private int seq = 0;
- private String sessionId;
-
- private boolean established = false;
-
- private boolean connected = true;
-
- private DownloadableFile file;
- private JingleConnection connection;
-
- private InputStream fileInputStream = null;
- private OutputStream fileOutputStream = null;
- private long remainingSize = 0;
- private long fileSize = 0;
- private MessageDigest digest;
-
- private OnFileTransmissionStatusChanged onFileTransmissionStatusChanged;
-
- private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() {
- @Override
- public void onIqPacketReceived(Account account, IqPacket packet) {
- if (connected && packet.getType() == IqPacket.TYPE.RESULT) {
- sendNextBlock();
- }
- }
- };
-
- public JingleInbandTransport(final JingleConnection connection, final String sid, final int blocksize) {
- this.connection = connection;
- this.account = connection.getAccount();
- this.counterpart = connection.getCounterPart();
- this.blockSize = blocksize;
- this.sessionId = sid;
- }
-
- public void connect(final OnTransportConnected callback) {
- IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
- iq.setTo(this.counterpart);
- Element open = iq.addChild("open", "http://jabber.org/protocol/ibb");
- open.setAttribute("sid", this.sessionId);
- open.setAttribute("stanza", "iq");
- open.setAttribute("block-size", Integer.toString(this.blockSize));
- this.connected = true;
- this.account.getXmppConnection().sendIqPacket(iq,
- new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account,
- IqPacket packet) {
- if (packet.getType() != IqPacket.TYPE.RESULT) {
- callback.failed();
- } else {
- callback.established();
- }
- }
- });
- }
-
- @Override
- public void receive(DownloadableFile file,
- OnFileTransmissionStatusChanged callback) {
- this.onFileTransmissionStatusChanged = callback;
- this.file = file;
- try {
- this.digest = MessageDigest.getInstance("SHA-1");
- digest.reset();
- file.getParentFile().mkdirs();
- file.createNewFile();
- this.fileOutputStream = connection.getFileOutputStream();
- if (this.fileOutputStream == null) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not create output stream");
- callback.onFileTransferAborted();
- return;
- }
- this.remainingSize = this.fileSize = file.getExpectedSize();
- } catch (final NoSuchAlgorithmException | IOException e) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+" "+e.getMessage());
- callback.onFileTransferAborted();
- }
- }
-
- @Override
- public void send(DownloadableFile file,
- OnFileTransmissionStatusChanged callback) {
- this.onFileTransmissionStatusChanged = callback;
- this.file = file;
- try {
- this.remainingSize = this.file.getExpectedSize();
- this.fileSize = this.remainingSize;
- this.digest = MessageDigest.getInstance("SHA-1");
- this.digest.reset();
- fileInputStream = connection.getFileInputStream();
- if (fileInputStream == null) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could no create input stream");
- callback.onFileTransferAborted();
- return;
- }
- if (this.connected) {
- this.sendNextBlock();
- }
- } catch (NoSuchAlgorithmException e) {
- callback.onFileTransferAborted();
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": "+e.getMessage());
- }
- }
-
- @Override
- public void disconnect() {
- this.connected = false;
- if (this.fileOutputStream != null) {
- try {
- this.fileOutputStream.close();
- } catch (IOException e) {
-
- }
- }
- if (this.fileInputStream != null) {
- try {
- this.fileInputStream.close();
- } catch (IOException e) {
-
- }
- }
- }
-
- private void sendNextBlock() {
- byte[] buffer = new byte[this.blockSize];
- try {
- int count = fileInputStream.read(buffer);
- if (count == -1) {
- file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
- this.onFileTransmissionStatusChanged.onFileTransmitted(file);
- fileInputStream.close();
- return;
- } else if (count != buffer.length) {
- int rem = fileInputStream.read(buffer,count,buffer.length-count);
- if (rem > 0) {
- count += rem;
- }
- }
- this.remainingSize -= count;
- this.digest.update(buffer,0,count);
- String base64 = Base64.encodeToString(buffer,0,count, Base64.NO_WRAP);
- IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
- iq.setTo(this.counterpart);
- Element data = iq.addChild("data", "http://jabber.org/protocol/ibb");
- data.setAttribute("seq", Integer.toString(this.seq));
- data.setAttribute("block-size", Integer.toString(this.blockSize));
- data.setAttribute("sid", this.sessionId);
- data.setContent(base64);
- this.account.getXmppConnection().sendIqPacket(iq, this.onAckReceived);
- this.account.getXmppConnection().r(); //don't fill up stanza queue too much
- this.seq++;
- if (this.remainingSize > 0) {
- connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
- } else {
- file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
- this.onFileTransmissionStatusChanged.onFileTransmitted(file);
- fileInputStream.close();
- }
- } catch (IOException e) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": "+e.getMessage());
- FileBackend.close(fileInputStream);
- this.onFileTransmissionStatusChanged.onFileTransferAborted();
- }
- }
-
- private void receiveNextBlock(String data) {
- try {
- byte[] buffer = Base64.decode(data, Base64.NO_WRAP);
- if (this.remainingSize < buffer.length) {
- buffer = Arrays.copyOfRange(buffer, 0, (int) this.remainingSize);
- }
- this.remainingSize -= buffer.length;
- this.fileOutputStream.write(buffer);
- this.digest.update(buffer);
- if (this.remainingSize <= 0) {
- file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
- fileOutputStream.flush();
- fileOutputStream.close();
- this.onFileTransmissionStatusChanged.onFileTransmitted(file);
- } else {
- connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
- }
- } catch (IOException e) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": "+e.getMessage());
- FileBackend.close(fileOutputStream);
- this.onFileTransmissionStatusChanged.onFileTransferAborted();
- }
- }
-
- public void deliverPayload(IqPacket packet, Element payload) {
- if (payload.getName().equals("open")) {
- if (!established) {
- established = true;
- connected = true;
- this.receiveNextBlock("");
- this.account.getXmppConnection().sendIqPacket(
- packet.generateResponse(IqPacket.TYPE.RESULT), null);
- } else {
- this.account.getXmppConnection().sendIqPacket(
- packet.generateResponse(IqPacket.TYPE.ERROR), null);
- }
- } else if (connected && payload.getName().equals("data")) {
- this.receiveNextBlock(payload.getContent());
- this.account.getXmppConnection().sendIqPacket(
- packet.generateResponse(IqPacket.TYPE.RESULT), null);
- } else {
- // TODO some sort of exception
- }
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
deleted file mode 100644
index 140f20b91..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
+++ /dev/null
@@ -1,210 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import android.os.PowerManager;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.entities.DownloadableFile;
-import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.utils.CryptoHelper;
-import eu.siacs.conversations.utils.SocksSocketFactory;
-import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
-
-public class JingleSocks5Transport extends JingleTransport {
- private JingleCandidate candidate;
- private JingleConnection connection;
- private String destination;
- private OutputStream outputStream;
- private InputStream inputStream;
- private boolean isEstablished = false;
- private boolean activated = false;
- protected Socket socket;
-
- public JingleSocks5Transport(JingleConnection jingleConnection,
- JingleCandidate candidate) {
- this.candidate = candidate;
- this.connection = jingleConnection;
- try {
- MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
- StringBuilder destBuilder = new StringBuilder();
- if (jingleConnection.getFtVersion() == Content.Version.FT_3) {
- Log.d(Config.LOGTAG,this.connection.getAccount().getJid().toBareJid()+": using session Id instead of transport Id for proxy destination");
- destBuilder.append(jingleConnection.getSessionId());
- } else {
- destBuilder.append(jingleConnection.getTransportId());
- }
- if (candidate.isOurs()) {
- destBuilder.append(jingleConnection.getAccount().getJid());
- destBuilder.append(jingleConnection.getCounterPart());
- } else {
- destBuilder.append(jingleConnection.getCounterPart());
- destBuilder.append(jingleConnection.getAccount().getJid());
- }
- mDigest.reset();
- this.destination = CryptoHelper.bytesToHex(mDigest
- .digest(destBuilder.toString().getBytes()));
- } catch (NoSuchAlgorithmException e) {
-
- }
- }
-
- public void connect(final OnTransportConnected callback) {
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- try {
- final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect();
- if (useTor) {
- socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(),candidate.getPort());
- } else {
- socket = new Socket();
- SocketAddress address = new InetSocketAddress(candidate.getHost(),candidate.getPort());
- socket.connect(address,Config.SOCKET_TIMEOUT * 1000);
- }
- inputStream = socket.getInputStream();
- outputStream = socket.getOutputStream();
- SocksSocketFactory.createSocksConnection(socket,destination,0);
- isEstablished = true;
- callback.established();
- } catch (IOException e) {
- callback.failed();
- }
- }
- }).start();
-
- }
-
- public void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- InputStream fileInputStream = null;
- final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_"+connection.getSessionId());
- try {
- wakeLock.acquire();
- MessageDigest digest = MessageDigest.getInstance("SHA-1");
- digest.reset();
- fileInputStream = connection.getFileInputStream();
- if (fileInputStream == null) {
- Log.d(Config.LOGTAG, connection.getAccount().getJid().toBareJid() + ": could not create input stream");
- callback.onFileTransferAborted();
- return;
- }
- long size = file.getExpectedSize();
- long transmitted = 0;
- int count;
- byte[] buffer = new byte[8192];
- while ((count = fileInputStream.read(buffer)) > 0) {
- outputStream.write(buffer, 0, count);
- digest.update(buffer, 0, count);
- transmitted += count;
- connection.updateProgress((int) ((((double) transmitted) / size) * 100));
- }
- outputStream.flush();
- file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
- if (callback != null) {
- callback.onFileTransmitted(file);
- }
- } catch (Exception e) {
- Log.d(Config.LOGTAG, connection.getAccount().getJid().toBareJid() + ": "+e.getMessage());
- callback.onFileTransferAborted();
- } finally {
- FileBackend.close(fileInputStream);
- wakeLock.release();
- }
- }
- }).start();
-
- }
-
- public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- OutputStream fileOutputStream = null;
- final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_receive_"+connection.getSessionId());
- try {
- wakeLock.acquire();
- MessageDigest digest = MessageDigest.getInstance("SHA-1");
- digest.reset();
- //inputStream.skip(45);
- socket.setSoTimeout(30000);
- file.getParentFile().mkdirs();
- file.createNewFile();
- fileOutputStream = connection.getFileOutputStream();
- if (fileOutputStream == null) {
- callback.onFileTransferAborted();
- Log.d(Config.LOGTAG, connection.getAccount().getJid().toBareJid() + ": could not create output stream");
- return;
- }
- double size = file.getExpectedSize();
- long remainingSize = file.getExpectedSize();
- byte[] buffer = new byte[8192];
- int count;
- while (remainingSize > 0) {
- count = inputStream.read(buffer);
- if (count == -1) {
- callback.onFileTransferAborted();
- Log.d(Config.LOGTAG, connection.getAccount().getJid().toBareJid() + ": file ended prematurely with "+remainingSize+" bytes remaining");
- return;
- } else {
- fileOutputStream.write(buffer, 0, count);
- digest.update(buffer, 0, count);
- remainingSize -= count;
- }
- connection.updateProgress((int) (((size - remainingSize) / size) * 100));
- }
- fileOutputStream.flush();
- fileOutputStream.close();
- file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
- callback.onFileTransmitted(file);
- } catch (Exception e) {
- Log.d(Config.LOGTAG, connection.getAccount().getJid().toBareJid() + ": "+e.getMessage());
- callback.onFileTransferAborted();
- } finally {
- wakeLock.release();
- FileBackend.close(fileOutputStream);
- FileBackend.close(inputStream);
- }
- }
- }).start();
- }
-
- public boolean isProxy() {
- return this.candidate.getType() == JingleCandidate.TYPE_PROXY;
- }
-
- public boolean needsActivation() {
- return (this.isProxy() && !this.activated);
- }
-
- public void disconnect() {
- FileBackend.close(inputStream);
- FileBackend.close(outputStream);
- FileBackend.close(socket);
- }
-
- public boolean isEstablished() {
- return this.isEstablished;
- }
-
- public JingleCandidate getCandidate() {
- return this.candidate;
- }
-
- public void setActivated(boolean activated) {
- this.activated = activated;
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleTransport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleTransport.java
deleted file mode 100644
index e832d3f58..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleTransport.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import eu.siacs.conversations.entities.DownloadableFile;
-
-public abstract class JingleTransport {
- public abstract void connect(final OnTransportConnected callback);
-
- public abstract void receive(final DownloadableFile file,
- final OnFileTransmissionStatusChanged callback);
-
- public abstract void send(final DownloadableFile file,
- final OnFileTransmissionStatusChanged callback);
-
- public abstract void disconnect();
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java
deleted file mode 100644
index 91cba39f5..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnFileTransmissionStatusChanged.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import eu.siacs.conversations.entities.DownloadableFile;
-
-public interface OnFileTransmissionStatusChanged {
- void onFileTransmitted(DownloadableFile file);
-
- void onFileTransferAborted();
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java
deleted file mode 100644
index 9a60b3924..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.PacketReceived;
-import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
-
-public interface OnJinglePacketReceived extends PacketReceived {
- void onJinglePacketReceived(Account account, JinglePacket packet);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnPrimaryCandidateFound.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/OnPrimaryCandidateFound.java
deleted file mode 100644
index 76e337177..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnPrimaryCandidateFound.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-public interface OnPrimaryCandidateFound {
- void onPrimaryCandidateFound(boolean success, JingleCandidate canditate);
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnTransportConnected.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/OnTransportConnected.java
deleted file mode 100644
index 38f03c5d0..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/OnTransportConnected.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle;
-
-public interface OnTransportConnected {
- public void failed();
-
- public void established();
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
deleted file mode 100644
index 49f52bf33..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle.stanzas;
-
-import eu.siacs.conversations.entities.DownloadableFile;
-import eu.siacs.conversations.xml.Element;
-
-public class Content extends Element {
-
- public enum Version {
- FT_3("urn:xmpp:jingle:apps:file-transfer:3"),
- FT_4("urn:xmpp:jingle:apps:file-transfer:4");
-
- private final String namespace;
-
- Version(String namespace) {
- this.namespace = namespace;
- }
-
- public String getNamespace() {
- return namespace;
- }
- }
-
- private String transportId;
-
- public Content() {
- super("content");
- }
-
- public Content(String creator, String name) {
- super("content");
- this.setAttribute("creator", creator);
- this.setAttribute("name", name);
- }
-
- public Version getVersion() {
- if (hasChild("description", Version.FT_3.namespace)) {
- return Version.FT_3;
- } else if (hasChild("description" , Version.FT_4.namespace)) {
- return Version.FT_4;
- }
- return null;
- }
-
- public void setTransportId(String sid) {
- this.transportId = sid;
- }
-
- public Element setFileOffer(DownloadableFile actualFile, boolean otr, Version version) {
- Element description = this.addChild("description", version.namespace);
- Element file;
- if (version == Version.FT_3) {
- Element offer = description.addChild("offer");
- file = offer.addChild("file");
- } else {
- file = description.addChild("file");
- }
- file.addChild("size").setContent(Long.toString(actualFile.getExpectedSize()));
- if (otr) {
- file.addChild("name").setContent(actualFile.getName() + ".otr");
- } else {
- file.addChild("name").setContent(actualFile.getName());
- }
- return file;
- }
-
- public Element getFileOffer(Version version) {
- Element description = this.findChild("description", version.namespace);
- if (description == null) {
- return null;
- }
- if (version == Version.FT_3) {
- Element offer = description.findChild("offer");
- if (offer == null) {
- return null;
- }
- return offer.findChild("file");
- } else {
- return description.findChild("file");
- }
- }
-
- public void setFileOffer(Element fileOffer, Version version) {
- Element description = this.addChild("description", version.namespace);
- if (version == Version.FT_3) {
- description.addChild("offer").addChild(fileOffer);
- } else {
- description.addChild(fileOffer);
- }
- }
-
- public String getTransportId() {
- if (hasSocks5Transport()) {
- this.transportId = socks5transport().getAttribute("sid");
- } else if (hasIbbTransport()) {
- this.transportId = ibbTransport().getAttribute("sid");
- }
- return this.transportId;
- }
-
- public Element socks5transport() {
- Element transport = this.findChild("transport",
- "urn:xmpp:jingle:transports:s5b:1");
- if (transport == null) {
- transport = this.addChild("transport",
- "urn:xmpp:jingle:transports:s5b:1");
- transport.setAttribute("sid", this.transportId);
- }
- return transport;
- }
-
- public Element ibbTransport() {
- Element transport = this.findChild("transport",
- "urn:xmpp:jingle:transports:ibb:1");
- if (transport == null) {
- transport = this.addChild("transport",
- "urn:xmpp:jingle:transports:ibb:1");
- transport.setAttribute("sid", this.transportId);
- }
- return transport;
- }
-
- public boolean hasSocks5Transport() {
- return this.hasChild("transport", "urn:xmpp:jingle:transports:s5b:1");
- }
-
- public boolean hasIbbTransport() {
- return this.hasChild("transport", "urn:xmpp:jingle:transports:ibb:1");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
deleted file mode 100644
index 4f73a83a7..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle.stanzas;
-
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.jid.Jid;
-import eu.siacs.conversations.xmpp.stanzas.IqPacket;
-
-public class JinglePacket extends IqPacket {
- Content content = null;
- Reason reason = null;
- Element jingle = new Element("jingle");
-
- @Override
- public Element addChild(Element child) {
- if ("jingle".equals(child.getName())) {
- Element contentElement = child.findChild("content");
- if (contentElement != null) {
- this.content = new Content();
- this.content.setChildren(contentElement.getChildren());
- this.content.setAttributes(contentElement.getAttributes());
- }
- Element reasonElement = child.findChild("reason");
- if (reasonElement != null) {
- this.reason = new Reason();
- this.reason.setChildren(reasonElement.getChildren());
- this.reason.setAttributes(reasonElement.getAttributes());
- }
- this.jingle.setAttributes(child.getAttributes());
- }
- return child;
- }
-
- public JinglePacket setContent(Content content) {
- this.content = content;
- return this;
- }
-
- public Content getJingleContent() {
- if (this.content == null) {
- this.content = new Content();
- }
- return this.content;
- }
-
- public JinglePacket setReason(Reason reason) {
- this.reason = reason;
- return this;
- }
-
- public Reason getReason() {
- return this.reason;
- }
-
- private void build() {
- this.children.clear();
- this.jingle.clearChildren();
- this.jingle.setAttribute("xmlns", "urn:xmpp:jingle:1");
- if (this.content != null) {
- jingle.addChild(this.content);
- }
- if (this.reason != null) {
- jingle.addChild(this.reason);
- }
- this.children.add(jingle);
- this.setAttribute("type", "set");
- }
-
- public String getSessionId() {
- return this.jingle.getAttribute("sid");
- }
-
- public void setSessionId(String sid) {
- this.jingle.setAttribute("sid", sid);
- }
-
- @Override
- public String toString() {
- this.build();
- return super.toString();
- }
-
- public void setAction(String action) {
- this.jingle.setAttribute("action", action);
- }
-
- public String getAction() {
- return this.jingle.getAttribute("action");
- }
-
- public void setInitiator(final Jid initiator) {
- this.jingle.setAttribute("initiator", initiator.toString());
- }
-
- public boolean isAction(String action) {
- return action.equalsIgnoreCase(this.getAction());
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java
deleted file mode 100644
index 610d5e760..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.siacs.conversations.xmpp.jingle.stanzas;
-
-import eu.siacs.conversations.xml.Element;
-
-public class Reason extends Element {
- private Reason(String name) {
- super(name);
- }
-
- public Reason() {
- super("reason");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java b/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java
deleted file mode 100644
index 38bb5c8f9..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/pep/Avatar.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package eu.siacs.conversations.xmpp.pep;
-
-import android.util.Base64;
-
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.jid.Jid;
-
-public class Avatar {
-
- public enum Origin { PEP, VCARD };
-
- public String type;
- public String sha1sum;
- public String image;
- public int height;
- public int width;
- public long size;
- public Jid owner;
- public Origin origin = Origin.PEP; //default to maintain compat
-
- public byte[] getImageAsBytes() {
- return Base64.decode(image, Base64.DEFAULT);
- }
-
- public String getFilename() {
- return sha1sum;
- }
-
- public static Avatar parseMetadata(Element items) {
- Element item = items.findChild("item");
- if (item == null) {
- return null;
- }
- Element metadata = item.findChild("metadata");
- if (metadata == null) {
- return null;
- }
- String primaryId = item.getAttribute("id");
- if (primaryId == null) {
- return null;
- }
- for (Element child : metadata.getChildren()) {
- if (child.getName().equals("info")
- && primaryId.equals(child.getAttribute("id"))) {
- Avatar avatar = new Avatar();
- String height = child.getAttribute("height");
- String width = child.getAttribute("width");
- String size = child.getAttribute("bytes");
- try {
- if (height != null) {
- avatar.height = Integer.parseInt(height);
- }
- if (width != null) {
- avatar.width = Integer.parseInt(width);
- }
- if (size != null) {
- avatar.size = Long.parseLong(size);
- }
- } catch (NumberFormatException e) {
- return null;
- }
- avatar.type = child.getAttribute("type");
- String hash = child.getAttribute("id");
- if (!isValidSHA1(hash)) {
- return null;
- }
- avatar.sha1sum = hash;
- avatar.origin = Origin.PEP;
- return avatar;
- }
- }
- return null;
- }
-
- @Override
- public boolean equals(Object object) {
- if (object != null && object instanceof Avatar) {
- Avatar other = (Avatar) object;
- return other.getFilename().equals(this.getFilename());
- } else {
- return false;
- }
- }
-
- public static Avatar parsePresence(Element x) {
- String hash = x == null ? null : x.findChildContent("photo");
- if (hash == null) {
- return null;
- }
- if (!isValidSHA1(hash)) {
- return null;
- }
- Avatar avatar = new Avatar();
- avatar.sha1sum = hash;
- avatar.origin = Origin.VCARD;
- return avatar;
- }
-
- private static boolean isValidSHA1(String s) {
- return s != null && s.matches("[a-fA-F0-9]{40}");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractAcknowledgeableStanza.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractAcknowledgeableStanza.java
deleted file mode 100644
index fa5e6fbdd..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractAcknowledgeableStanza.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas;
-
-import eu.siacs.conversations.xml.Element;
-
-abstract public class AbstractAcknowledgeableStanza extends AbstractStanza {
-
- protected AbstractAcknowledgeableStanza(String name) {
- super(name);
- }
-
-
- public String getId() {
- return this.getAttribute("id");
- }
-
- public void setId(final String id) {
- setAttribute("id", id);
- }
-
- public Element getError() {
- Element error = findChild("error");
- if (error != null) {
- for(Element element : error.getChildren()) {
- if (!element.getName().equals("text")) {
- return element;
- }
- }
- }
- return null;
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java
deleted file mode 100644
index a6144df28..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.jid.Jid;
-
-public class AbstractStanza extends Element {
-
- protected AbstractStanza(final String name) {
- super(name);
- }
-
- public Jid getTo() {
- return getAttributeAsJid("to");
- }
-
- public Jid getFrom() {
- return getAttributeAsJid("from");
- }
-
- public void setTo(final Jid to) {
- if (to != null) {
- setAttribute("to", to.toString());
- }
- }
-
- public void setFrom(final Jid from) {
- if (from != null) {
- setAttribute("from", from.toString());
- }
- }
-
- public boolean fromServer(final Account account) {
- return getFrom() == null
- || getFrom().equals(account.getServer())
- || getFrom().equals(account.getJid().toBareJid())
- || getFrom().equals(account.getJid());
- }
-
- public boolean toServer(final Account account) {
- return getTo() == null
- || getTo().equals(account.getServer())
- || getTo().equals(account.getJid().toBareJid())
- || getTo().equals(account.getJid());
- }
-
- public boolean fromAccount(final Account account) {
- return getFrom() != null && getFrom().toBareJid().equals(account.getJid().toBareJid());
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java
deleted file mode 100644
index 302dc78e8..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/IqPacket.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas;
-
-import eu.siacs.conversations.xml.Element;
-
-public class IqPacket extends AbstractAcknowledgeableStanza {
-
- public enum TYPE {
- ERROR,
- SET,
- RESULT,
- GET,
- INVALID,
- TIMEOUT
- }
-
- public IqPacket(final TYPE type) {
- super("iq");
- if (type != TYPE.INVALID) {
- this.setAttribute("type", type.toString().toLowerCase());
- }
- }
-
- public IqPacket() {
- super("iq");
- }
-
- public Element query() {
- Element query = findChild("query");
- if (query == null) {
- query = addChild("query");
- }
- return query;
- }
-
- public Element query(final String xmlns) {
- final Element query = query();
- query.setAttribute("xmlns", xmlns);
- return query();
- }
-
- public TYPE getType() {
- final String type = getAttribute("type");
- if (type == null) {
- return TYPE.INVALID;
- }
- switch (type) {
- case "error":
- return TYPE.ERROR;
- case "result":
- return TYPE.RESULT;
- case "set":
- return TYPE.SET;
- case "get":
- return TYPE.GET;
- case "timeout":
- return TYPE.TIMEOUT;
- default:
- return TYPE.INVALID;
- }
- }
-
- public IqPacket generateResponse(final TYPE type) {
- final IqPacket packet = new IqPacket(type);
- packet.setTo(this.getFrom());
- packet.setId(this.getId());
- return packet;
- }
-
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
deleted file mode 100644
index ac75a5e59..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas;
-
-import android.util.Pair;
-
-import eu.siacs.conversations.parser.AbstractParser;
-import eu.siacs.conversations.xml.Element;
-
-public class MessagePacket extends AbstractAcknowledgeableStanza {
- public static final int TYPE_CHAT = 0;
- public static final int TYPE_NORMAL = 2;
- public static final int TYPE_GROUPCHAT = 3;
- public static final int TYPE_ERROR = 4;
- public static final int TYPE_HEADLINE = 5;
-
- public MessagePacket() {
- super("message");
- }
-
- public String getBody() {
- return findChildContent("body");
- }
-
- public void setBody(String text) {
- this.children.remove(findChild("body"));
- Element body = new Element("body");
- body.setContent(text);
- this.children.add(0, body);
- }
-
- public void setAxolotlMessage(Element axolotlMessage) {
- this.children.remove(findChild("body"));
- this.children.add(0, axolotlMessage);
- }
-
- public void setType(int type) {
- switch (type) {
- case TYPE_CHAT:
- this.setAttribute("type", "chat");
- break;
- case TYPE_GROUPCHAT:
- this.setAttribute("type", "groupchat");
- break;
- case TYPE_NORMAL:
- break;
- case TYPE_ERROR:
- this.setAttribute("type","error");
- break;
- default:
- this.setAttribute("type", "chat");
- break;
- }
- }
-
- public int getType() {
- String type = getAttribute("type");
- if (type == null) {
- return TYPE_NORMAL;
- } else if (type.equals("normal")) {
- return TYPE_NORMAL;
- } else if (type.equals("chat")) {
- return TYPE_CHAT;
- } else if (type.equals("groupchat")) {
- return TYPE_GROUPCHAT;
- } else if (type.equals("error")) {
- return TYPE_ERROR;
- } else if (type.equals("headline")) {
- return TYPE_HEADLINE;
- } else {
- return TYPE_NORMAL;
- }
- }
-
- public Pair<MessagePacket,Long> getForwardedMessagePacket(String name, String namespace) {
- Element wrapper = findChild(name, namespace);
- if (wrapper == null) {
- return null;
- }
- Element forwarded = wrapper.findChild("forwarded", "urn:xmpp:forward:0");
- if (forwarded == null) {
- return null;
- }
- MessagePacket packet = create(forwarded.findChild("message"));
- if (packet == null) {
- return null;
- }
- Long timestamp = AbstractParser.parseTimestamp(forwarded, null);
- return new Pair(packet,timestamp);
- }
-
- public static MessagePacket create(Element element) {
- if (element == null) {
- return null;
- }
- MessagePacket packet = new MessagePacket();
- packet.setAttributes(element.getAttributes());
- packet.setChildren(element.getChildren());
- return packet;
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java
deleted file mode 100644
index c321498d8..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas;
-
-public class PresencePacket extends AbstractAcknowledgeableStanza {
-
- public PresencePacket() {
- super("presence");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java
deleted file mode 100644
index 78ab66d8f..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas.csi;
-
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-
-public class ActivePacket extends AbstractStanza {
- public ActivePacket() {
- super("active");
- setAttribute("xmlns", "urn:xmpp:csi:0");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java
deleted file mode 100644
index f109280f1..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas.csi;
-
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-
-public class InactivePacket extends AbstractStanza {
- public InactivePacket() {
- super("inactive");
- setAttribute("xmlns", "urn:xmpp:csi:0");
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java
deleted file mode 100644
index f93b5d870..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas.streammgmt;
-
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-
-public class AckPacket extends AbstractStanza {
-
- public AckPacket(int sequence, int smVersion) {
- super("a");
- this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
- this.setAttribute("h", Integer.toString(sequence));
- }
-
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java
deleted file mode 100644
index 78cd81edc..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas.streammgmt;
-
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-
-public class EnablePacket extends AbstractStanza {
-
- public EnablePacket(int smVersion) {
- super("enable");
- this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
- this.setAttribute("resume", "true");
- }
-
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java
deleted file mode 100644
index 98cfc748b..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas.streammgmt;
-
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-
-public class RequestPacket extends AbstractStanza {
-
- public RequestPacket(int smVersion) {
- super("r");
- this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
- }
-
-}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java
deleted file mode 100644
index 9cdcfa5ec..000000000
--- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package eu.siacs.conversations.xmpp.stanzas.streammgmt;
-
-import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
-
-public class ResumePacket extends AbstractStanza {
-
- public ResumePacket(String id, int sequence, int smVersion) {
- super("resume");
- this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
- this.setAttribute("previd", id);
- this.setAttribute("h", Integer.toString(sequence));
- }
-
-}