Browse Source

Add support for XEP-0166, XEP-0260, XEP-0261

jinglePR1
vanitasvitae 2 years ago
parent
commit
63c2ef595f
No known key found for this signature in database GPG Key ID: 62BEE9264BF17311
53 changed files with 0 additions and 3786 deletions
  1. +0
    -43
      smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/Aes128GcmNoPadding.java
  2. +0
    -43
      smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/Aes256GcmNoPadding.java
  3. +0
    -144
      smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/AesGcmNoPadding.java
  4. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/package-info.java
  5. +0
    -190
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetManager.java
  6. +0
    -35
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetSecurityAdapter.java
  7. +0
    -142
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/component/JetSecurity.java
  8. +0
    -51
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/component/JetSecurityBytestreamSession.java
  9. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/component/package-info.java
  10. +0
    -81
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/element/JetSecurityElement.java
  11. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/element/package-info.java
  12. +0
    -65
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/provider/JetSecurityProvider.java
  13. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jet/provider/package-info.java
  14. +0
    -218
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java
  15. +0
    -64
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/adapter/JingleFileTransferAdapter.java
  16. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/adapter/package-info.java
  17. +0
    -27
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/AbstractJingleFileOffer.java
  18. +0
    -30
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/AbstractJingleFileRequest.java
  19. +0
    -96
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleFileTransfer.java
  20. +0
    -225
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleFileTransferFile.java
  21. +0
    -146
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleIncomingFileOffer.java
  22. +0
    -65
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleIncomingFileRequest.java
  23. +0
    -108
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleOutgoingFileOffer.java
  24. +0
    -57
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleOutgoingFileRequest.java
  25. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/package-info.java
  26. +0
    -35
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/IncomingFileOfferController.java
  27. +0
    -24
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/IncomingFileRequestController.java
  28. +0
    -35
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/JingleFileTransferController.java
  29. +0
    -24
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/OutgoingFileOfferController.java
  30. +0
    -24
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/OutgoingFileRequestController.java
  31. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/package-info.java
  32. +0
    -65
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/ChecksumElement.java
  33. +0
    -176
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferChildElement.java
  34. +0
    -43
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferElement.java
  35. +0
    -131
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/Range.java
  36. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/package-info.java
  37. +0
    -27
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/IncomingFileOfferListener.java
  38. +0
    -27
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/IncomingFileRequestListener.java
  39. +0
    -29
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/ProgressListener.java
  40. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/package-info.java
  41. +0
    -21
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/package-info.java
  42. +0
    -91
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/provider/ChecksumProvider.java
  43. +0
    -122
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/provider/JingleFileTransferProvider.java
  44. +0
    -22
      smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/provider/package-info.java
  45. +0
    -101
      smack-experimental/src/test/java/org/jivesoftware/smackx/ciphers/AesGcmNoPaddingTest.java
  46. +0
    -97
      smack-experimental/src/test/java/org/jivesoftware/smackx/jet/JetElementTest.java
  47. +0
    -67
      smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_filetransfer/ChecksumTest.java
  48. +0
    -40
      smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_filetransfer/IncomingFileTransferTest.java
  49. +0
    -145
      smack-integration-test/src/main/java/org/jivesoftware/smackx/jet/JetIntegrationTest.java
  50. +0
    -21
      smack-integration-test/src/main/java/org/jivesoftware/smackx/jet/package-info.java
  51. +0
    -178
      smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferIntegrationTest.java
  52. +0
    -192
      smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferTransportFallbackIntegrationTest.java
  53. +0
    -21
      smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/package-info.java

+ 0
- 43
smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/Aes128GcmNoPadding.java View File

@@ -1,43 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.ciphers;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.NoSuchPaddingException;

public class Aes128GcmNoPadding extends AesGcmNoPadding {
public static final String NAMESPACE = "urn:xmpp:ciphers:aes-128-gcm-nopadding:0";

public Aes128GcmNoPadding(int MODE) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, InvalidAlgorithmParameterException {
super(128, MODE);
}

public Aes128GcmNoPadding(byte[] keyAndIv, int MODE) throws NoSuchProviderException, InvalidAlgorithmParameterException,
NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException {
super(AesGcmNoPadding.copyOfRange(keyAndIv, 0, 16), // 16 byte key
AesGcmNoPadding.copyOfRange(keyAndIv, 16, keyAndIv.length), MODE); // rest (12 byte) IV
}

@Override
public String getNamespace() {
return NAMESPACE;
}
}

+ 0
- 43
smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/Aes256GcmNoPadding.java View File

@@ -1,43 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.ciphers;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.NoSuchPaddingException;

public class Aes256GcmNoPadding extends AesGcmNoPadding {
public static final String NAMESPACE = "urn:xmpp:ciphers:aes-256-gcm-nopadding:0";

public Aes256GcmNoPadding(int MODE) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, InvalidAlgorithmParameterException {
super(256, MODE);
}

public Aes256GcmNoPadding(byte[] keyAndIv, int MODE) throws NoSuchProviderException, InvalidAlgorithmParameterException,
NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException {
super(AesGcmNoPadding.copyOfRange(keyAndIv, 0, 32), // 32 byte key
AesGcmNoPadding.copyOfRange(keyAndIv, 32, keyAndIv.length), MODE); // rest (12 byte) IV
}

@Override
public String getNamespace() {
return NAMESPACE;
}
}

+ 0
- 144
smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/AesGcmNoPadding.java View File

@@ -1,144 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.ciphers;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public abstract class AesGcmNoPadding {

public static final String keyType = "AES";
public static final String cipherMode = "AES/GCM/NoPadding";

private final int length;
protected final Cipher cipher;
private final byte[] key, iv, keyAndIv;

AesGcmNoPadding(int bits, int MODE) throws NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
this.length = bits;
int bytes = bits / 8;

KeyGenerator keyGenerator = KeyGenerator.getInstance(keyType);
keyGenerator.init(bits);
key = keyGenerator.generateKey().getEncoded();

SecureRandom secureRandom = new SecureRandom();
iv = new byte[12];
secureRandom.nextBytes(iv);

keyAndIv = new byte[bytes + 12];
System.arraycopy(key, 0, keyAndIv, 0, bytes);
System.arraycopy(iv, 0, keyAndIv, bytes, 12);

cipher = Cipher.getInstance(cipherMode, "BC");
SecretKey keySpec = new SecretKeySpec(key, keyType);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(MODE, keySpec, ivSpec);
}

public static AesGcmNoPadding createEncryptionKey(String cipherName)
throws NoSuchProviderException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
InvalidAlgorithmParameterException {

switch (cipherName) {
case Aes128GcmNoPadding.NAMESPACE:
return new Aes128GcmNoPadding(Cipher.ENCRYPT_MODE);
case Aes256GcmNoPadding.NAMESPACE:
return new Aes256GcmNoPadding(Cipher.ENCRYPT_MODE);
default: throw new NoSuchAlgorithmException("Invalid cipher.");
}
}

/**
* Create a new AES key.
* @param key key
* @param iv iv
* @param MODE cipher mode (Cipher.ENCRYPT_MODE / Cipher.DECRYPT_MODE)
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
*/
public AesGcmNoPadding(byte[] key, byte[] iv, int MODE) throws NoSuchPaddingException, NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException {
assert iv.length == 12;
this.length = key.length * 8;
this.key = key;
this.iv = iv;

keyAndIv = new byte[key.length + iv.length];
System.arraycopy(key, 0, keyAndIv, 0, key.length);
System.arraycopy(iv, 0, keyAndIv, key.length, iv.length);

cipher = Cipher.getInstance(cipherMode, "BC");
SecretKeySpec keySpec = new SecretKeySpec(key, keyType);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(MODE, keySpec, ivSpec);
}

public static AesGcmNoPadding createDecryptionKey(String namespace, byte[] serialized)
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException,
InvalidKeyException, NoSuchPaddingException {

switch (namespace) {
case Aes128GcmNoPadding.NAMESPACE:
return new Aes128GcmNoPadding(serialized, Cipher.DECRYPT_MODE);
case Aes256GcmNoPadding.NAMESPACE:
return new Aes256GcmNoPadding(serialized, Cipher.DECRYPT_MODE);
default: throw new NoSuchAlgorithmException("Invalid cipher.");
}
}

public byte[] getKeyAndIv() {
return keyAndIv.clone();
}

public byte[] getKey() {
return key.clone();
}

public byte[] getIv() {
return iv.clone();
}

public int getLength() {
return length;
}

public Cipher getCipher() {
return cipher;
}

public abstract String getNamespace();

static byte[] copyOfRange(byte[] source, int start, int end) {
byte[] copy = new byte[end - start];
System.arraycopy(source, start, copy, 0, end - start);
return copy;
}
}

+ 0
- 22
smack-experimental/src/main/java/org/jivesoftware/smackx/ciphers/package-info.java View File

@@ -1,22 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Smack's API for XEP-XXXX: Ciphers</a>.
* This contains some AES cipher utility functions.
*/
package org.jivesoftware.smackx.ciphers;

+ 0
- 190
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetManager.java View File

@@ -1,190 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jet;

import java.io.File;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.HashMap;
import java.util.WeakHashMap;
import java.util.logging.Logger;

import javax.crypto.NoSuchPaddingException;

import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smackx.ciphers.Aes256GcmNoPadding;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.jet.component.JetSecurity;
import org.jivesoftware.smackx.jet.provider.JetSecurityProvider;
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.JingleTransportManager;
import org.jivesoftware.smackx.jingle.component.JingleContent;
import org.jivesoftware.smackx.jingle.component.JingleSession;
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
import org.jivesoftware.smackx.jingle.util.Role;
import org.jivesoftware.smackx.jingle_filetransfer.JingleFileTransferManager;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransferFile;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleOutgoingFileOffer;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileOfferController;

import org.jxmpp.jid.FullJid;

/**
* Manager for Jingle Encrypted Transfers (XEP-XXXX).
*/
public final class JetManager extends Manager implements JingleDescriptionManager {

private static final Logger LOGGER = Logger.getLogger(JetManager.class.getName());

private static final WeakHashMap<XMPPConnection, JetManager> INSTANCES = new WeakHashMap<>();
private static final HashMap<String, JingleEnvelopeManager> envelopeManagers = new HashMap<>();
private static final HashMap<String, ExtensionElementProvider<?>> envelopeProviders = new HashMap<>();

private final JingleManager jingleManager;

static {
JingleManager.addJingleSecurityAdapter(new JetSecurityAdapter());
JingleManager.addJingleSecurityProvider(new JetSecurityProvider());
}

private JetManager(XMPPConnection connection) {
super(connection);
this.jingleManager = JingleManager.getInstanceFor(connection);
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(getNamespace());
jingleManager.addJingleDescriptionManager(this);
}

public static JetManager getInstanceFor(XMPPConnection connection) {
JetManager manager = INSTANCES.get(connection);

if (manager == null) {
manager = new JetManager(connection);
INSTANCES.put(connection, manager);
}

return manager;
}

public OutgoingFileOfferController sendEncryptedFile(File file, FullJid recipient, JingleEnvelopeManager envelopeManager) throws Exception {
return sendEncryptedFile(file, null, recipient, envelopeManager);
}

public OutgoingFileOfferController sendEncryptedFile(File file, String filename, FullJid recipient, JingleEnvelopeManager envelopeManager) throws Exception {
if (file == null || !file.exists()) {
throw new IllegalArgumentException("File MUST NOT be null and MUST exist.");
}

throwIfRecipientLacksSupport(recipient);

JingleSession session = jingleManager.createSession(Role.initiator, recipient);

JingleContent content = new JingleContent(JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
session.addContent(content);

JingleOutgoingFileOffer offer = new JingleOutgoingFileOffer(file);
if (filename != null) {
offer.getFile().setName(filename);
}
content.setDescription(offer);

JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);
content.setTransport(transportManager.createTransportForInitiator(content));

JetSecurity security = new JetSecurity(envelopeManager, recipient, content.getName(), Aes256GcmNoPadding.NAMESPACE);
content.setSecurity(security);
session.sendInitiate(connection());

return offer;
}

public OutgoingFileOfferController sendEncryptedStream(InputStream inputStream, JingleFileTransferFile.StreamFile file, FullJid recipient, JingleEnvelopeManager envelopeManager)
throws XMPPException.XMPPErrorException, SmackException.FeatureNotSupportedException, SmackException.NotConnectedException,
InterruptedException, SmackException.NoResponseException, NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException,
JingleEnvelopeManager.JingleEncryptionException, NoSuchProviderException, InvalidAlgorithmParameterException {

throwIfRecipientLacksSupport(recipient);
JingleSession session = jingleManager.createSession(Role.initiator, recipient);

JingleContent content = new JingleContent(JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
session.addContent(content);

JingleOutgoingFileOffer offer = new JingleOutgoingFileOffer(file, inputStream);
content.setDescription(offer);

JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);
content.setTransport(transportManager.createTransportForInitiator(content));

JetSecurity security = new JetSecurity(envelopeManager, recipient, content.getName(), Aes256GcmNoPadding.NAMESPACE);
content.setSecurity(security);
session.sendInitiate(connection());

return offer;
}

public void registerEnvelopeManager(JingleEnvelopeManager method) {
envelopeManagers.put(method.getJingleEnvelopeNamespace(), method);
}

public void unregisterEnvelopeManager(String namespace) {
envelopeManagers.remove(namespace);
}

public JingleEnvelopeManager getEnvelopeManager(String namespace) {
return envelopeManagers.get(namespace);
}

public static void registerEnvelopeProvider(String namespace, ExtensionElementProvider<?> provider) {
envelopeProviders.put(namespace, provider);
}

public static void unregisterEnvelopeProvider(String namespace) {
envelopeProviders.remove(namespace);
}

public static ExtensionElementProvider<?> getEnvelopeProvider(String namespace) {
return envelopeProviders.get(namespace);
}

@Override
public String getNamespace() {
return JetSecurity.NAMESPACE;
}

@Override
public void notifySessionInitiate(JingleSession session) {
JingleFileTransferManager.getInstanceFor(connection()).notifySessionInitiate(session);
}

@Override
public void notifyContentAdd(JingleSession session, JingleContent content) {
JingleFileTransferManager.getInstanceFor(connection()).notifyContentAdd(session, content);
}

private void throwIfRecipientLacksSupport(FullJid recipient) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, SmackException.FeatureNotSupportedException {
if (!ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(recipient, getNamespace())) {
throw new SmackException.FeatureNotSupportedException(getNamespace(), recipient);
}
}
}

+ 0
- 35
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetSecurityAdapter.java View File

@@ -1,35 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jet;

import org.jivesoftware.smackx.jet.component.JetSecurity;
import org.jivesoftware.smackx.jet.element.JetSecurityElement;
import org.jivesoftware.smackx.jingle.adapter.JingleSecurityAdapter;
import org.jivesoftware.smackx.jingle.element.JingleContentSecurityElement;

public class JetSecurityAdapter implements JingleSecurityAdapter<JetSecurity> {

@Override
public JetSecurity securityFromElement(JingleContentSecurityElement element) {
return new JetSecurity((JetSecurityElement) element);
}

@Override
public String getNamespace() {
return JetSecurity.NAMESPACE;
}
}

+ 0
- 142
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/component/JetSecurity.java View File

@@ -1,142 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jet.component;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.NoSuchPaddingException;

import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.ciphers.AesGcmNoPadding;
import org.jivesoftware.smackx.jet.JetManager;
import org.jivesoftware.smackx.jet.JingleEnvelopeManager;
import org.jivesoftware.smackx.jet.element.JetSecurityElement;
import org.jivesoftware.smackx.jingle.callbacks.JingleSecurityCallback;
import org.jivesoftware.smackx.jingle.component.JingleSecurity;
import org.jivesoftware.smackx.jingle.element.JingleContentSecurityInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;

import org.jxmpp.jid.FullJid;

/**
* Created by vanitas on 22.07.17.
*/
public class JetSecurity extends JingleSecurity<JetSecurityElement> {
private static final Logger LOGGER = Logger.getLogger(JetSecurity.class.getName());

public static final String NAMESPACE_V0 = "urn:xmpp:jingle:jet:0";
public static final String NAMESPACE = NAMESPACE_V0;

private final String envelopeNamespace;

private AesGcmNoPadding aesKey;
private final ExtensionElement child;
private final String cipherName;
private final String contentName;

public JetSecurity(JetSecurityElement element) {
super();
this.child = element.getChild();
this.envelopeNamespace = element.getEnvelopeNamespace();
this.contentName = element.getContentName();
this.cipherName = element.getCipherName();
}

public JetSecurity(JingleEnvelopeManager envelopeManager, FullJid recipient, String contentName, String cipherName)
throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
InvalidAlgorithmParameterException, InvalidKeyException, InterruptedException,
JingleEnvelopeManager.JingleEncryptionException, SmackException.NotConnectedException,
SmackException.NoResponseException {

this.envelopeNamespace = envelopeManager.getJingleEnvelopeNamespace();
this.aesKey = AesGcmNoPadding.createEncryptionKey(cipherName);
this.child = envelopeManager.encryptJingleTransfer(recipient, aesKey.getKeyAndIv());
this.contentName = contentName;
this.cipherName = cipherName;
}

private void decryptEncryptionKey(JingleEnvelopeManager method, FullJid sender)
throws InterruptedException, JingleEnvelopeManager.JingleEncryptionException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, NoSuchProviderException, InvalidKeyException, NoSuchPaddingException {
byte[] keyAndIv = method.decryptJingleTransfer(sender, child);
aesKey = AesGcmNoPadding.createDecryptionKey(cipherName, keyAndIv);
}

@Override
public JetSecurityElement getElement() {
return new JetSecurityElement(contentName, cipherName, child);
}

@Override
public JingleElement handleSecurityInfo(JingleContentSecurityInfoElement element, JingleElement wrapping) {
return null;
}

@Override
public void decryptIncomingBytestream(BytestreamSession bytestreamSession, JingleSecurityCallback callback) {
if (aesKey == null) {
throw new IllegalStateException("Encryption key has not yet been decrypted.");
}
JetSecurityBytestreamSession securityBytestreamSession = new JetSecurityBytestreamSession(bytestreamSession, aesKey.getCipher());
callback.onSecurityReady(securityBytestreamSession);
}

@Override
public void encryptOutgoingBytestream(BytestreamSession bytestreamSession, JingleSecurityCallback callback) {
JetSecurityBytestreamSession securityBytestreamSession = new JetSecurityBytestreamSession(bytestreamSession, aesKey.getCipher());
callback.onSecurityReady(securityBytestreamSession);
}

@Override
public String getNamespace() {
return NAMESPACE;
}

@Override
public void prepare(XMPPConnection connection, FullJid sender) {
if (getParent().getParent().isInitiator()) {
return;
}

if (aesKey != null) {
return;
}

JingleEnvelopeManager method = JetManager.getInstanceFor(connection).getEnvelopeManager(getEnvelopeNamespace());
if (method == null) {
throw new AssertionError("No JingleEncryptionMethodManager found for " + getEnvelopeNamespace());
}
try {
decryptEncryptionKey(method, sender);
} catch (InterruptedException | NoSuchPaddingException | InvalidKeyException | NoSuchProviderException | InvalidAlgorithmParameterException | NoSuchAlgorithmException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | JingleEnvelopeManager.JingleEncryptionException e) {
LOGGER.log(Level.SEVERE, "Could not decrypt security key: " + e, e);
}
}

public String getEnvelopeNamespace() {
return envelopeNamespace;
}
}

+ 0
- 51
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/component/JetSecurityBytestreamSession.java View File

@@ -1,51 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jet.component;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;

import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.component.JingleSecurityBytestreamSession;

public class JetSecurityBytestreamSession extends JingleSecurityBytestreamSession {
private final Cipher cipher;

public JetSecurityBytestreamSession(BytestreamSession session, Cipher cipher) {
super(session);
this.cipher = cipher;
}

@Override
public InputStream getInputStream() throws IOException {
return new CipherInputStream(wrapped.getInputStream(), cipher);
}

@Override
public OutputStream getOutputStream() throws IOException {
return new CipherOutputStream(wrapped.getOutputStream(), cipher);
}

@Override
public void close() throws IOException {
wrapped.close();
}
}

+ 0
- 22
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/component/package-info.java View File

@@ -1,22 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Smack's API for XEP-XXXX: Jingle Encrypted Transfers</a>.
* Internal classes.
*/
package org.jivesoftware.smackx.jet.component;

+ 0
- 81
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/element/JetSecurityElement.java View File

@@ -1,81 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jet.element;

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.jet.component.JetSecurity;
import org.jivesoftware.smackx.jingle.element.JingleContentSecurityElement;

/**
* Implementation of the Jingle security element as specified in XEP-XXXX (Jingle Encrypted Transfers).
* <jingle>
* <content>
* <description/>
* <transport/>
* <security/> <- You are here.
* </content>
* </jingle>
*/
public class JetSecurityElement extends JingleContentSecurityElement {
public static final String ATTR_CONTENT_NAME = "name";
public static final String ATTR_ENVELOPE_TYPE = "type";
public static final String ATTR_CIPHER_TYPE = "cipher";

private final ExtensionElement child;
private final String contentName;
private final String cipherName;

public JetSecurityElement(String contentName, String cipherName, ExtensionElement child) {
this.contentName = contentName;
this.child = child;
this.cipherName = cipherName;
}

@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder(this);
xml.attribute(ATTR_CONTENT_NAME, contentName)
.attribute(ATTR_CIPHER_TYPE, cipherName)
.attribute(ATTR_ENVELOPE_TYPE, child.getNamespace());
xml.rightAngleBracket();
xml.element(child);
xml.closeElement(this);
return xml;
}

@Override
public String getNamespace() {
return JetSecurity.NAMESPACE;
}

public String getEnvelopeNamespace() {
return child.getNamespace();
}

public ExtensionElement getChild() {
return child;
}

public String getContentName() {
return contentName;
}

public String getCipherName() {
return cipherName;
}
}

+ 0
- 22
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/element/package-info.java View File

@@ -1,22 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Smack's API for XEP-XXXX: Jingle Encrypted Transfers</a>.
* Elements.
*/
package org.jivesoftware.smackx.jet.element;

+ 0
- 65
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/provider/JetSecurityProvider.java View File

@@ -1,65 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jet.provider;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smackx.jet.JetManager;
import org.jivesoftware.smackx.jet.component.JetSecurity;
import org.jivesoftware.smackx.jet.element.JetSecurityElement;
import org.jivesoftware.smackx.jingle.provider.JingleContentSecurityProvider;

import org.xmlpull.v1.XmlPullParser;

/**
* Provider for the Jingle security element for XEP-XXXX (Jingle Encrypted Transfers).
*/
public class JetSecurityProvider extends JingleContentSecurityProvider<JetSecurityElement> {
private static final Logger LOGGER = Logger.getLogger(JetSecurityProvider.class.getName());

@Override
public JetSecurityElement parse(XmlPullParser parser, int initialDepth) throws Exception {
String name = parser.getAttributeValue("", JetSecurityElement.ATTR_CONTENT_NAME);
String cipher = parser.getAttributeValue("", JetSecurityElement.ATTR_CIPHER_TYPE);
String type = parser.getAttributeValue("", JetSecurityElement.ATTR_ENVELOPE_TYPE);
ExtensionElement child;

Objects.requireNonNull(type);
Objects.requireNonNull(cipher);

ExtensionElementProvider<?> encryptionElementProvider =
JetManager.getEnvelopeProvider(type);

if (encryptionElementProvider != null) {
child = encryptionElementProvider.parse(parser);
} else {
LOGGER.log(Level.WARNING, "Unknown child element in JetSecurityElement: " + type);
return null;
}

return new JetSecurityElement(name, cipher, child);
}

@Override
public String getNamespace() {
return JetSecurity.NAMESPACE;
}
}

+ 0
- 22
smack-experimental/src/main/java/org/jivesoftware/smackx/jet/provider/package-info.java View File

@@ -1,22 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Smack's API for XEP-XXXX: Jingle Encrypted Transfers</a>.
* Providers.
*/
package org.jivesoftware.smackx.jet.provider;

+ 0
- 218
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java View File

@@ -1,218 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.JingleTransportManager;
import org.jivesoftware.smackx.jingle.component.JingleContent;
import org.jivesoftware.smackx.jingle.component.JingleSession;
import org.jivesoftware.smackx.jingle.component.JingleTransport;
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
import org.jivesoftware.smackx.jingle.util.Role;
import org.jivesoftware.smackx.jingle_filetransfer.adapter.JingleFileTransferAdapter;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransfer;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransferFile;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleIncomingFileOffer;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleIncomingFileRequest;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleOutgoingFileOffer;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleOutgoingFileRequest;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileRequestController;
import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingFileOfferListener;
import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingFileRequestListener;
import org.jivesoftware.smackx.jingle_filetransfer.provider.JingleFileTransferProvider;

import org.jxmpp.jid.FullJid;

/**
* Created by vanitas on 22.07.17.
*/
public final class JingleFileTransferManager extends Manager implements JingleDescriptionManager {

private static final Logger LOGGER = Logger.getLogger(JingleFileTransferManager.class.getName());

private static final WeakHashMap<XMPPConnection, JingleFileTransferManager> INSTANCES = new WeakHashMap<>();
private final JingleManager jingleManager;

private final List<IncomingFileOfferListener> offerListeners =
Collections.synchronizedList(new ArrayList<IncomingFileOfferListener>());

private final List<IncomingFileRequestListener> requestListeners =
Collections.synchronizedList(new ArrayList<IncomingFileRequestListener>());

static {
JingleManager.addJingleDescriptionAdapter(new JingleFileTransferAdapter());
JingleManager.addJingleDescriptionProvider(new JingleFileTransferProvider());
}

private JingleFileTransferManager(XMPPConnection connection) {
super(connection);
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(getNamespace());
jingleManager = JingleManager.getInstanceFor(connection);
jingleManager.addJingleDescriptionManager(this);
}

public static JingleFileTransferManager getInstanceFor(XMPPConnection connection) {
JingleFileTransferManager manager = INSTANCES.get(connection);

if (manager == null) {
manager = new JingleFileTransferManager(connection);
INSTANCES.put(connection, manager);
}

return manager;
}

public OutgoingFileOfferController sendFile(File file, FullJid to)
throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException,
SmackException.NoResponseException, SmackException.FeatureNotSupportedException, FileNotFoundException {
return sendFile(file, null, to);
}

public OutgoingFileOfferController sendFile(File file, String alternativeFilename, FullJid to)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, SmackException.FeatureNotSupportedException, FileNotFoundException {
if (file == null || !file.exists()) {
throw new IllegalArgumentException("File MUST NOT be null and MUST exist.");
}

if (!ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(to, getNamespace())) {
throw new SmackException.FeatureNotSupportedException(getNamespace(), to);
}

JingleSession session = jingleManager.createSession(Role.initiator, to);

JingleContent content = new JingleContent(JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
session.addContent(content);

JingleOutgoingFileOffer offer = new JingleOutgoingFileOffer(file);
if (alternativeFilename != null) {
offer.getFile().setName(alternativeFilename);
}
content.setDescription(offer);

JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(to);
JingleTransport<?> transport = transportManager.createTransportForInitiator(content);
content.setTransport(transport);

session.sendInitiate(connection());

return offer;
}

public OutgoingFileOfferController sendStream(final InputStream stream, JingleFileTransferFile.StreamFile file, FullJid recipient) throws SmackException.FeatureNotSupportedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
if (!ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(recipient, getNamespace())) {
throw new SmackException.FeatureNotSupportedException(getNamespace(), recipient);
}

JingleSession session = jingleManager.createSession(Role.initiator, recipient);

JingleContent content = new JingleContent(JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
session.addContent(content);

JingleOutgoingFileOffer outgoingFileOffer = new JingleOutgoingFileOffer(file, stream);

content.setDescription(outgoingFileOffer);

JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);
JingleTransport<?> transport = transportManager.createTransportForInitiator(content);
content.setTransport(transport);

session.sendInitiate(connection());

return outgoingFileOffer;
}

public OutgoingFileRequestController requestFile(JingleFileTransferFile.RemoteFile file, FullJid from) {
JingleOutgoingFileRequest request = new JingleOutgoingFileRequest(file);

//TODO at some point.

return request;
}

public void addIncomingFileOfferListener(IncomingFileOfferListener listener) {
offerListeners.add(listener);
}

public void removeIncomingFileOfferListener(IncomingFileOfferListener listener) {
offerListeners.remove(listener);
}

public void notifyIncomingFileOfferListeners(JingleIncomingFileOffer offer) {
LOGGER.log(Level.INFO, "Incoming File transfer: [" + offer.getNamespace() + ", "
+ offer.getParent().getTransport().getNamespace() + ", "
+ (offer.getParent().getSecurity() != null ? offer.getParent().getSecurity().getNamespace() : "") + "]");
for (IncomingFileOfferListener l : offerListeners) {
l.onIncomingFileOffer(offer);
}
}

public void addIncomingFileRequestListener(IncomingFileRequestListener listener) {
requestListeners.add(listener);
}

public void removeIncomingFileRequestListener(IncomingFileRequestListener listener) {
requestListeners.remove(listener);
}

public void notifyIncomingFileRequestListeners(JingleIncomingFileRequest request) {
for (IncomingFileRequestListener l : requestListeners) {
l.onIncomingFileRequest(request);
}
}

@Override
public String getNamespace() {
return JingleFileTransfer.NAMESPACE;
}

private void notifyTransfer(JingleFileTransfer transfer) {
if (transfer.isOffer()) {
notifyIncomingFileOfferListeners((JingleIncomingFileOffer) transfer);
} else {
notifyIncomingFileRequestListeners((JingleIncomingFileRequest) transfer);
}
}

@Override
public void notifySessionInitiate(JingleSession session) {
JingleContent content = session.getSoleContentOrThrow();
notifyTransfer((JingleFileTransfer) content.getDescription());
}

@Override
public void notifyContentAdd(JingleSession session, JingleContent content) {
notifyTransfer((JingleFileTransfer) content.getDescription());
}
}

+ 0
- 64
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/adapter/JingleFileTransferAdapter.java View File

@@ -1,64 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.adapter;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smackx.jingle.adapter.JingleDescriptionAdapter;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement;
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransfer;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleIncomingFileOffer;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleIncomingFileRequest;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferElement;

/**
* Created by vanitas on 28.07.17.
*/
public class JingleFileTransferAdapter implements JingleDescriptionAdapter<JingleFileTransfer> {
private static final Logger LOGGER = Logger.getLogger(JingleFileTransferAdapter.class.getName());

@Override
public JingleFileTransfer descriptionFromElement(JingleContentElement.Creator creator, JingleContentElement.Senders senders,
String contentName, String contentDisposition, JingleContentDescriptionElement element) {
JingleFileTransferElement description = (JingleFileTransferElement) element;
List<NamedElement> children = description.getJingleContentDescriptionChildren();
assert children.size() == 1;
JingleFileTransferChildElement file = (JingleFileTransferChildElement) children.get(0);

if (senders == JingleContentElement.Senders.initiator) {
return new JingleIncomingFileOffer(file);
} else if (senders == JingleContentElement.Senders.responder) {
return new JingleIncomingFileRequest(file);
} else {
if (senders == null) {
LOGGER.log(Level.INFO, "Senders is null. Gajim workaround: assume 'initiator'.");
return new JingleIncomingFileOffer(file);
}
throw new AssertionError("Senders attribute MUST be either initiator or responder. Is: " + senders);
}
}

@Override
public String getNamespace() {
return JingleFileTransfer.NAMESPACE;
}
}

+ 0
- 22
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/adapter/package-info.java View File

@@ -1,22 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Smack's API for <a href="https://xmpp.org/extensions/xep-0234.html">XEP-0234: Jingle File Transfer</a>.
* Adapters.
*/
package org.jivesoftware.smackx.jingle_filetransfer.adapter;

+ 0
- 27
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/AbstractJingleFileOffer.java View File

@@ -1,27 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

/**
* Created by vanitas on 22.07.17.
*/
public abstract class AbstractJingleFileOffer extends JingleFileTransfer {

AbstractJingleFileOffer(JingleFileTransferFile fileTransferFile) {
super(fileTransferFile);
}
}

+ 0
- 30
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/AbstractJingleFileRequest.java View File

@@ -1,30 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

/**
* Created by vanitas on 22.07.17.
*/
public abstract class AbstractJingleFileRequest<D extends JingleFileTransferFile> extends JingleFileTransfer {

AbstractJingleFileRequest(D fileTransferFile) {
super(fileTransferFile);
}

@Override
public abstract D getFile();
}

+ 0
- 96
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleFileTransfer.java View File

@@ -1,96 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.jivesoftware.smackx.jingle.component.JingleDescription;
import org.jivesoftware.smackx.jingle_filetransfer.controller.JingleFileTransferController;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferElement;
import org.jivesoftware.smackx.jingle_filetransfer.listener.ProgressListener;

/**
* Created by vanitas on 22.07.17.
*/
public abstract class JingleFileTransfer extends JingleDescription<JingleFileTransferElement> implements JingleFileTransferController {

public static final String NAMESPACE_V5 = "urn:xmpp:jingle:apps:file-transfer:5";
public static final String NAMESPACE = NAMESPACE_V5;

public abstract boolean isOffer();
public abstract boolean isRequest();

protected State state;
protected JingleFileTransferFile file;

private final List<ProgressListener> progressListeners = Collections.synchronizedList(new ArrayList<ProgressListener>());

JingleFileTransfer(JingleFileTransferFile file) {
this.file = file;
}

@Override
public void addProgressListener(ProgressListener listener) {
progressListeners.add(listener);
//TODO: Notify new listener?
}

@Override
public void removeProgressListener(ProgressListener listener) {
progressListeners.remove(listener);
}

@Override
public void cancel() {
//TODO
}

public void notifyProgressListeners(float progress) {
for (ProgressListener p : progressListeners) {
p.progress(progress);
}
}

public void notifyProgressListenersFinished() {
for (ProgressListener p : progressListeners) {
p.finished();
}
}

public void notifyProgressListenersStarted() {
for (ProgressListener p : progressListeners) {
p.started();
}
}

@Override
public String getNamespace() {
return JingleFileTransfer.NAMESPACE;
}

@Override
public JingleFileTransferElement getElement() {
return new JingleFileTransferElement(file.getElement());
}

@Override
public State getState() {
return state;
}
}

+ 0
- 225
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleFileTransferFile.java View File

@@ -1,225 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

import java.io.File;
import java.util.Date;

import org.jivesoftware.smackx.hashes.element.HashElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;

/**
* Represent a file sent in a file transfer.
* This can be both LocalFile (available to the client), or RemoteFile (file not yet available).
*/
public abstract class JingleFileTransferFile {

public JingleFileTransferFile() {

}

public JingleFileTransferChildElement getElement() {
JingleFileTransferChildElement.Builder builder = JingleFileTransferChildElement.getBuilder();
builder.setDate(getDate());
builder.setSize(getSize());
builder.setName(getName());
builder.setDescription(getDescription());
builder.setMediaType(getMediaType());
builder.setHash(getHashElement());

return builder.build();
}

public abstract Date getDate();

public abstract long getSize();

public abstract String getName();

public abstract String getDescription();

public abstract String getMediaType();

public abstract HashElement getHashElement();

public static class LocalFile extends JingleFileTransferFile {

private final File file;
private String name;
private String description;
private String mediaType;
private HashElement hashElement;

public LocalFile(File file) {
this(file, null, null);
}

public LocalFile(File file, String description) {
this(file, description, null);
}

public LocalFile(File file, String description, String mediaType) {
super();
this.file = file;
String path = file.getAbsolutePath();
name = path.substring(path.lastIndexOf(File.separator) + 1);
this.description = description;
this.mediaType = mediaType;
}

@Override
public Date getDate() {
return new Date(file.lastModified());
}

public void setDate(Date date) {
}

@Override
public long getSize() {
return file.length();
}

@Override
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String getDescription() {
return description;
}

@Override
public String getMediaType() {
return mediaType;
}

@Override
public HashElement getHashElement() {
return hashElement;
}

public void setDescription(String description) {
this.description = description;
}

public void setMediaType(String mediaType) {
this.mediaType = mediaType;
}

public void setHashElement(HashElement hashElement) {
this.hashElement = hashElement;
}

public File getFile() {
return file;
}
}

public static class RemoteFile extends JingleFileTransferFile {

private final JingleFileTransferChildElement file;

public RemoteFile(JingleFileTransferChildElement file) {
super();
this.file = file;
}

@Override
public String getDescription() {
return file.getDescription();
}

@Override
public String getMediaType() {
return file.getMediaType();
}

@Override
public HashElement getHashElement() {
return file.getHash();
}

@Override
public Date getDate() {
return file.getDate();
}

@Override
public long getSize() {
return file.getSize();
}

@Override
public String getName() {
return file.getName();
}
}

public static class StreamFile extends JingleFileTransferFile {

private String name, description, mediaType;
private long size;
private Date date;
private HashElement hashElement;

public StreamFile(String name, long size, String description, String mediaType, Date date, HashElement hashElement) {
this.name = name;
this.size = size;
this.description = description;
this.mediaType = mediaType;
this.date = date;
this.hashElement = hashElement;
}

@Override
public Date getDate() {
return date;
}

@Override
public long getSize() {
return size;
}

@Override
public String getName() {
return name;
}

@Override
public String getDescription() {
return description;
}

@Override
public String getMediaType() {
return mediaType;
}

@Override
public HashElement getHashElement() {
return hashElement;
}
}

}

+ 0
- 146
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleIncomingFileOffer.java View File

@@ -1,146 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.component.JingleSession;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;

/**
* Behind the scenes logic of an incoming Jingle file offer.
* Created by vanitas on 26.07.17.
*/
public class JingleIncomingFileOffer extends AbstractJingleFileOffer implements IncomingFileOfferController {

private static final Logger LOGGER = Logger.getLogger(JingleIncomingFileOffer.class.getName());
private OutputStream target;

public JingleIncomingFileOffer(JingleFileTransferChildElement offer) {
super(new JingleFileTransferFile.RemoteFile(offer));
}

@Override
public JingleElement handleDescriptionInfo(JingleContentDescriptionInfoElement info) {
return null;
}

@Override
public void onBytestreamReady(BytestreamSession bytestreamSession) {
if (target == null) {
throw new IllegalStateException("Target OutputStream is null");
}

LOGGER.log(Level.INFO, "Receive file");

InputStream inputStream = null;
try {
inputStream = bytestreamSession.getInputStream();

int length = 0;
int read = 0;
byte[] bufbuf = new byte[4096];
while ((length = inputStream.read(bufbuf)) >= 0) {
target.write(bufbuf, 0, length);
read += length;
LOGGER.log(Level.INFO, "Read " + read + " (" + length + ") of " + file.getSize() + " bytes.");
if (read == (int) file.getSize()) {
break;
}
}
LOGGER.log(Level.INFO, "Reading/Writing finished.");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Cannot get InputStream from BytestreamSession: " + e, e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
LOGGER.log(Level.INFO, "CipherInputStream closed.");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not close InputStream: " + e, e);
}
}

if (target != null) {
try {
target.close();
LOGGER.log(Level.INFO, "FileOutputStream closed.");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not close OutputStream: " + e, e);
}
}
}
notifyProgressListenersFinished();
}

@Override
public boolean isOffer() {
return true;
}

@Override
public boolean isRequest() {
return false;
}

@Override
public void accept(XMPPConnection connection, File target)
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
SmackException.NoResponseException, IOException {

if (!target.exists()) {
target.createNewFile();
}

this.target = new FileOutputStream(target);

JingleSession session = getParent().getParent();
if (session.getSessionState() == JingleSession.SessionState.pending) {
session.sendAccept(connection);
}
}

@Override
public void accept(XMPPConnection connection, OutputStream stream)
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
SmackException.NoResponseException {
target = stream;

JingleSession session = getParent().getParent();
if (session.getSessionState() == JingleSession.SessionState.pending) {
session.sendAccept(connection);
}
}

@Override
public JingleFileTransferFile.RemoteFile getFile() {
return (JingleFileTransferFile.RemoteFile) this.file;
}
}

+ 0
- 65
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleIncomingFileRequest.java View File

@@ -1,65 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileRequestController;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferElement;

/**
* Created by vanitas on 27.07.17.
* TODO: RemoteFile????
*/
public class JingleIncomingFileRequest extends AbstractJingleFileRequest<JingleFileTransferFile.RemoteFile> implements IncomingFileRequestController {

public JingleIncomingFileRequest(JingleFileTransferChildElement request) {
super(new JingleFileTransferFile.RemoteFile(request));
}

@Override
public JingleFileTransferElement getElement() {
return null;
}

@Override
public JingleElement handleDescriptionInfo(JingleContentDescriptionInfoElement info) {
return null;
}

@Override
public boolean isOffer() {
return false;
}

@Override
public boolean isRequest() {
return true;
}

@Override
public void onBytestreamReady(BytestreamSession bytestreamSession) {

}

@Override
public JingleFileTransferFile.RemoteFile getFile() {
return (JingleFileTransferFile.RemoteFile) file;
}
}

+ 0
- 108
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleOutgoingFileOffer.java View File

@@ -1,108 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileOfferController;

/**
* Created by vanitas on 26.07.17.
*/
public class JingleOutgoingFileOffer extends AbstractJingleFileOffer implements OutgoingFileOfferController {
private static final Logger LOGGER = Logger.getLogger(JingleOutgoingFileOffer.class.getName());

private final InputStream source;

public JingleOutgoingFileOffer(File file) throws FileNotFoundException {
super(new JingleFileTransferFile.LocalFile(file));
this.source = new FileInputStream(file);
}

public JingleOutgoingFileOffer(JingleFileTransferFile.StreamFile streamFile, InputStream inputStream) {
super(streamFile);
this.source = inputStream;
}

@Override
public JingleElement handleDescriptionInfo(JingleContentDescriptionInfoElement info) {
return null;
}

@Override
public void onBytestreamReady(BytestreamSession bytestreamSession) {
if (source == null) {
throw new IllegalStateException("Source InputStream is null!");
}

OutputStream outputStream = null;

try {
outputStream = bytestreamSession.getOutputStream();

byte[] buf = new byte[8192];

while (true) {
int r = source.read(buf);
if (r < 0) {
break;
}
outputStream.write(buf, 0, r);
}

outputStream.flush();
outputStream.close();

} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Exception while sending file: " + e, e);
} finally {

try {
source.close();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not close FileInputStream: " + e, e);
}
}

notifyProgressListenersFinished();
}

@Override
public boolean isOffer() {
return true;
}

@Override
public boolean isRequest() {
return false;
}

@Override
public JingleFileTransferFile.LocalFile getFile() {
return (JingleFileTransferFile.LocalFile) file;
}
}

+ 0
- 57
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/JingleOutgoingFileRequest.java View File

@@ -1,57 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileRequestController;

/**
* Created by vanitas on 27.07.17.
*/
public class JingleOutgoingFileRequest extends AbstractJingleFileRequest<JingleFileTransferFile.RemoteFile> implements OutgoingFileRequestController {

public JingleOutgoingFileRequest(JingleFileTransferFile.RemoteFile file) {
super(file);
}

@Override
public JingleFileTransferFile.RemoteFile getFile() {
return (JingleFileTransferFile.RemoteFile) file;
}

@Override
public JingleElement handleDescriptionInfo(JingleContentDescriptionInfoElement info) {
return null;
}

@Override
public boolean isOffer() {
return false;
}

@Override
public boolean isRequest() {
return true;
}

@Override
public void onBytestreamReady(BytestreamSession bytestreamSession) {

}
}

+ 0
- 22
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/component/package-info.java View File

@@ -1,22 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Smack's API for <a href="https://xmpp.org/extensions/xep-0234.html">XEP-0234: Jingle File Transfer</a>.
* Internal classes.
*/
package org.jivesoftware.smackx.jingle_filetransfer.component;

+ 0
- 35
smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/controller/IncomingFileOfferController.java View File

@@ -1,35 +0,0 @@
/**
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle_filetransfer.controller;

import java.io.File;
import java.io.IOException;