1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-30 07:52:06 +01:00

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

This commit is contained in:
vanitasvitae 2017-08-16 21:53:29 +02:00
parent 524660c870
commit 63c2ef595f
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
53 changed files with 0 additions and 3786 deletions

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;
}
}

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;
}
}

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;
}
}

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;

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);
}
}
}

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;
}
}

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;
}
}

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();
}
}

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;

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;
}
}

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;

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;
}
}

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;

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());
}
}

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;
}
}

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;

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);
}
}

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();
}

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;
}
}

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;
}
}
}

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;
}
}

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;
}
}

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;
}
}

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) {
}
}

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;

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;
import java.io.OutputStream;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
/**
* User interface for an incoming Jingle file offer.
*/
public interface IncomingFileOfferController extends JingleFileTransferController {
void accept(XMPPConnection connection, File target) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, IOException;
void accept(XMPPConnection connection, OutputStream outputStream) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, IOException;
}

View file

@ -1,24 +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;
/**
* Created by vanitas on 27.07.17.
*/
public interface IncomingFileRequestController extends JingleFileTransferController {
//TODO: Declare methods.
}

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 org.jivesoftware.smackx.jingle.JingleDescriptionController;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransferFile;
import org.jivesoftware.smackx.jingle_filetransfer.listener.ProgressListener;
/**
* User interface for Jingle file transfers.
*/
public interface JingleFileTransferController extends JingleDescriptionController {
void addProgressListener(ProgressListener listener);
void removeProgressListener(ProgressListener listener);
JingleFileTransferFile getFile();
void cancel();
}

View file

@ -1,24 +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;
/**
* Created by vanitas on 27.07.17.
*/
public interface OutgoingFileOfferController extends JingleFileTransferController {
//TODO: Declare methods.
}

View file

@ -1,24 +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;
/**
* Created by vanitas on 27.07.17.
*/
public interface OutgoingFileRequestController extends JingleFileTransferController {
//TODO: Declare methods.
}

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>.
* Controller.
*/
package org.jivesoftware.smackx.jingle_filetransfer.controller;

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.element;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransfer;
/**
* Checksum element.
*/
public class ChecksumElement implements ExtensionElement {
public static final String ELEMENT = "checksum";
public static final String ATTR_CREATOR = "creator";
public static final String ATTR_NAME = "name";
private final JingleContentElement.Creator creator;
private final String name;
private final JingleFileTransferChildElement file;
public ChecksumElement(JingleContentElement.Creator creator, String name, JingleFileTransferChildElement file) {
this.creator = creator;
this.name = name;
this.file = Objects.requireNonNull(file, "file MUST NOT be null.");
Objects.requireNonNull(file.getHash(), "file MUST contain at least one hash element.");
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder sb = new XmlStringBuilder(this);
sb.optAttribute(ATTR_CREATOR, creator);
sb.optAttribute(ATTR_NAME, name);
sb.rightAngleBracket();
sb.element(file);
sb.closeElement(this);
return sb;
}
@Override
public String getNamespace() {
return JingleFileTransfer.NAMESPACE;
}
}

View file

@ -1,176 +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.element;
import java.io.File;
import java.util.Date;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.hashes.element.HashElement;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionChildElement;
/**
* Content of type File.
*/
public class JingleFileTransferChildElement extends JingleContentDescriptionChildElement {
public static final String ELEMENT = "file";
public static final String ELEM_DATE = "date";
public static final String ELEM_DESC = "desc";
public static final String ELEM_MEDIA_TYPE = "media-type";
public static final String ELEM_NAME = "name";
public static final String ELEM_SIZE = "size";
private final Date date;
private final String desc;
private final HashElement hash;
private final String mediaType;
private final String name;
private final long size;
private final Range range;
public JingleFileTransferChildElement(Date date, String desc, HashElement hash, String mediaType, String name, long size, Range range) {
this.date = date;
this.desc = desc;
this.hash = hash;
this.mediaType = mediaType;
this.name = name;
this.size = size;
this.range = range;
}
public Date getDate() {
return date;
}
public String getDescription() {
return desc;
}
public HashElement getHash() {
return hash;
}
public String getMediaType() {
return mediaType;
}
public String getName() {
return name;
}
public long getSize() {
return size;
}
public Range getRange() {
return range;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder sb = new XmlStringBuilder(this);
sb.rightAngleBracket();
sb.optElement(ELEM_DATE, date);
sb.optElement(ELEM_DESC, desc);
sb.optElement(ELEM_MEDIA_TYPE, mediaType);
sb.optElement(ELEM_NAME, name);
sb.optElement(range);
if (size > 0) {
sb.element(ELEM_SIZE, Long.toString(size));
}
sb.optElement(hash);
sb.closeElement(this);
return sb;
}
public static Builder getBuilder() {
return new Builder();
}
public static final class Builder {
private Date date;
private String desc;
private HashElement hash;
private String mediaType;
private String name;
private long size;
private Range range;
private Builder() {
}
public Builder setDate(Date date) {
this.date = date;
return this;
}
public Builder setDescription(String desc) {
this.desc = desc;
return this;
}
public Builder setHash(HashElement hash) {
this.hash = hash;
return this;
}
/**
* Set the media type of the file.
* This is a MIME type from this list:
* https://www.iana.org/assignments/media-types/media-types.xhtml
* Default should be application/octet-stream.
* @param mediaType new media type.
* @return builder.
*/
public Builder setMediaType(String mediaType) {
this.mediaType = mediaType;
return this;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setSize(long size) {
this.size = size;
return this;
}
public Builder setRange(Range range) {
this.range = range;
return this;
}
public JingleFileTransferChildElement build() {
return new JingleFileTransferChildElement(date, desc, hash, mediaType, name, size, range);
}
public Builder setFile(File file) {
return setDate(new Date(file.lastModified()))
.setName(file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf("/") + 1))
.setSize((int) file.length());
}
}
}

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.jingle_filetransfer.element;
import java.util.Collections;
import java.util.List;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionChildElement;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransfer;
/**
* File element.
*/
public class JingleFileTransferElement extends JingleContentDescriptionElement {
public JingleFileTransferElement(JingleContentDescriptionChildElement payload) {
this(Collections.singletonList(payload));
}
public JingleFileTransferElement(List<JingleContentDescriptionChildElement> payloads) {
super(payloads);
}
@Override
public String getNamespace() {
return JingleFileTransfer.NAMESPACE;
}
}

View file

@ -1,131 +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.element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.hashes.element.HashElement;
/**
* RangeElement which specifies, which range of a file shall be transferred.
*/
public class Range implements NamedElement {
public static final String ELEMENT = "range";
public static final String ATTR_OFFSET = "offset";
public static final String ATTR_LENGTH = "length";
private final Long offset, length;
private final HashElement hash;
/**
* Create a Range element with default values.
*/
public Range() {
this(null, null, null);
}
/**
* Create a Range element with specified length.
* @param length length of the transmitted data in bytes.
*/
public Range(Long length) {
this(null, length, null);
}
/**
* Create a Range element with specified offset and length.
* @param offset offset in bytes from the beginning of the transmitted data.
* @param length number of bytes that shall be transferred.
*/
public Range(Long offset, Long length) {
this(offset, length, null);
}
/**
* Create a Range element with specified offset, length and hash.
* @param offset offset in bytes from the beginning of the transmitted data.
* @param length number of bytes that shall be transferred.
* @param hash hash of the bytes in the specified range.
*/
public Range(Long offset, Long length, HashElement hash) {
this.offset = offset;
this.length = length;
this.hash = hash;
}
/**
* Return the index of the offset.
* This marks the begin of the specified range.
* @return offset
*/
public Long getOffset() {
return offset;
}
/**
* Return the length of the range.
* @return length
*/
public Long getLength() {
return length;
}
/**
* Return the hash element that contains a checksum of the bytes specified in the range.
* @return hash element
*/
public HashElement getHash() {
return hash;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder sb = new XmlStringBuilder(this);
sb.optAttribute(ATTR_OFFSET, offset);
sb.optAttribute(ATTR_LENGTH, length);
if (hash != null) {
sb.rightAngleBracket();
sb.element(hash);
sb.closeElement(this);
} else {
sb.closeEmptyElement();
}
return sb;
}
@Override
public boolean equals(Object other) {
if (other == null || !(other instanceof Range)) {
return false;
}
return this.hashCode() == other.hashCode();
}
@Override
public int hashCode() {
return toXML().toString().hashCode();
}
}

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>.
* Elements.
*/
package org.jivesoftware.smackx.jingle_filetransfer.element;

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.listener;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileOfferController;
/**
* Created by vanitas on 26.07.17.
*/
public interface IncomingFileOfferListener {
void onIncomingFileOffer(IncomingFileOfferController offer);
}

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.listener;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileRequestController;
/**
* Created by vanitas on 27.07.17.
*/
public interface IncomingFileRequestListener {
void onIncomingFileRequest(IncomingFileRequestController request);
}

View file

@ -1,29 +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.listener;
/**
* Created by vanitas on 27.07.17.
*/
public interface ProgressListener {
void started();
void progress(float percent);
void finished();
}

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>.
* Listeners.
*/
package org.jivesoftware.smackx.jingle_filetransfer.listener;

View file

@ -1,21 +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>.
*/
package org.jivesoftware.smackx.jingle_filetransfer;

View file

@ -1,91 +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.provider;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smackx.hashes.element.HashElement;
import org.jivesoftware.smackx.hashes.provider.HashElementProvider;
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.ChecksumElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.Range;
import org.xmlpull.v1.XmlPullParser;
/**
* Provider for the Checksum element.
*/
public class ChecksumProvider extends ExtensionElementProvider<ChecksumElement> {
@Override
public ChecksumElement parse(XmlPullParser parser, int initialDepth) throws Exception {
JingleContentElement.Creator creator = null;
String creatorString = parser.getAttributeValue(null, ChecksumElement.ATTR_CREATOR);
if (creatorString != null) {
creator = JingleContentElement.Creator.valueOf(creatorString);
}
String name = parser.getAttributeValue(null, ChecksumElement.ATTR_NAME);
JingleFileTransferChildElement.Builder cb = JingleFileTransferChildElement.getBuilder();
HashElement hashElement = null;
Range range = null;
boolean go = true;
while (go) {
int tag = parser.nextTag();
String n = parser.getName();
if (tag == START_TAG) {
switch (n) {
case HashElement.ELEMENT:
hashElement = new HashElementProvider().parse(parser);
break;
case Range.ELEMENT:
Long offset = ParserUtils.getLongAttribute(parser, Range.ATTR_OFFSET);
Long length = ParserUtils.getLongAttribute(parser, Range.ATTR_LENGTH);
range = new Range(offset, length);
}
} else if (tag == END_TAG) {
switch (n) {
case Range.ELEMENT:
if (hashElement != null && range != null) {
range = new Range(range.getOffset(), range.getLength(), hashElement);
hashElement = null;
}
break;
case JingleFileTransferChildElement.ELEMENT:
if (hashElement != null) {
cb.setHash(hashElement);
}
if (range != null) {
cb.setRange(range);
}
go = false;
}
}
}
return new ChecksumElement(creator, name, cb.build());
}
}

View file

@ -1,122 +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.provider;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import java.util.ArrayList;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smackx.hashes.element.HashElement;
import org.jivesoftware.smackx.hashes.provider.HashElementProvider;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionChildElement;
import org.jivesoftware.smackx.jingle.provider.JingleContentDescriptionProvider;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransfer;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.Range;
import org.xmlpull.v1.XmlPullParser;
/**
* Provider for JingleContentDescriptionFileTransfer elements.
*/
public class JingleFileTransferProvider
extends JingleContentDescriptionProvider<JingleFileTransferElement> {
@Override
public JingleFileTransferElement parse(XmlPullParser parser, int initialDepth) throws Exception {
ArrayList<JingleContentDescriptionChildElement> payloads = new ArrayList<>();
boolean inRange = false;
JingleFileTransferChildElement.Builder builder = JingleFileTransferChildElement.getBuilder();
HashElement inRangeHash = null;
Long length = null, offset = null;
while (true) {
int tag = parser.nextTag();
String elem = parser.getName();
if (tag == START_TAG) {
switch (elem) {
case JingleFileTransferChildElement.ELEM_DATE:
//builder.setDate(XmppDateTime.parseXEP0082Date(parser.nextText()));
parser.nextText();
break;
case JingleFileTransferChildElement.ELEM_DESC:
builder.setDescription(parser.nextText());
break;
case JingleFileTransferChildElement.ELEM_MEDIA_TYPE:
builder.setMediaType(parser.nextText());
break;
case JingleFileTransferChildElement.ELEM_NAME:
builder.setName(parser.nextText());
break;
case JingleFileTransferChildElement.ELEM_SIZE:
builder.setSize(Integer.parseInt(parser.nextText()));
break;
case Range.ELEMENT:
inRange = true;
offset = ParserUtils.getLongAttribute(parser, Range.ATTR_OFFSET);
length = ParserUtils.getLongAttribute(parser, Range.ATTR_LENGTH);
if (parser.isEmptyElementTag()) {
inRange = false;
builder.setRange(new Range(offset, length));
}
break;
case HashElement.ELEMENT:
if (inRange) {
inRangeHash = new HashElementProvider().parse(parser);
} else {
builder.setHash(new HashElementProvider().parse(parser));
}
break;
}
} else if (tag == END_TAG) {
switch (elem) {
case Range.ELEMENT:
inRange = false;
builder.setRange(new Range(offset, length, inRangeHash));
inRangeHash = null;
break;
case JingleFileTransferChildElement.ELEMENT:
payloads.add(builder.build());
builder = JingleFileTransferChildElement.getBuilder();
break;
case JingleFileTransferElement.ELEMENT:
return new JingleFileTransferElement(payloads);
}
}
}
}
@Override
public String getNamespace() {
return JingleFileTransfer.NAMESPACE;
}
}

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>.
* Providers.
*/
package org.jivesoftware.smackx.jingle_filetransfer.provider;

View file

@ -1,101 +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 static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Arrays;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.junit.Test;
public class AesGcmNoPaddingTest extends SmackTestSuite {
@Test
public void Aes128Test() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, InvalidAlgorithmParameterException {
AesGcmNoPadding aes128 = AesGcmNoPadding.createEncryptionKey(Aes128GcmNoPadding.NAMESPACE);
assertNotNull(aes128);
assertEquals(16, aes128.getKey().length);
assertEquals(12, aes128.getIv().length);
assertEquals(28, aes128.getKeyAndIv().length);
assertNotNull(aes128.getCipher());
assertEquals(128, aes128.getLength());
}
@Test
public void Aes256Test() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, InvalidAlgorithmParameterException {
AesGcmNoPadding aes256 = AesGcmNoPadding.createEncryptionKey(Aes256GcmNoPadding.NAMESPACE);
assertNotNull(aes256);
assertEquals(32, aes256.getKey().length);
assertEquals(12, aes256.getIv().length);
assertEquals(44, aes256.getKeyAndIv().length);
assertNotNull(aes256.getCipher());
assertEquals(256, aes256.getLength());
}
@Test(expected = NoSuchAlgorithmException.class)
public void invalidEncryptionCipher() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, InvalidAlgorithmParameterException {
AesGcmNoPadding.createEncryptionKey("invalid");
}
@Test(expected = NoSuchAlgorithmException.class)
public void invalidDecryptionCipher() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, InvalidAlgorithmParameterException {
AesGcmNoPadding.createDecryptionKey("invalid", null);
}
@Test
public void encryption128Test() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException {
AesGcmNoPadding aes1 = AesGcmNoPadding.createEncryptionKey(Aes128GcmNoPadding.NAMESPACE);
AesGcmNoPadding aes2 = AesGcmNoPadding.createDecryptionKey(Aes128GcmNoPadding.NAMESPACE, aes1.getKeyAndIv());
byte[] data = new byte[4096];
new Random().nextBytes(data);
byte[] enc = aes1.getCipher().doFinal(data);
assertFalse(Arrays.equals(data, enc));
byte[] dec = aes2.getCipher().doFinal(enc);
assertTrue(Arrays.equals(dec, data));
}
@Test
public void encryption256Test() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException {
AesGcmNoPadding aes1 = AesGcmNoPadding.createEncryptionKey(Aes256GcmNoPadding.NAMESPACE);
AesGcmNoPadding aes2 = AesGcmNoPadding.createDecryptionKey(Aes256GcmNoPadding.NAMESPACE, aes1.getKeyAndIv());
byte[] data = new byte[4096];
new Random().nextBytes(data);
byte[] enc = aes1.getCipher().doFinal(data);
assertFalse(Arrays.equals(data, enc));
byte[] dec = aes2.getCipher().doFinal(enc);
assertTrue(Arrays.equals(dec, data));
}
}

View file

@ -1,97 +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 static junit.framework.TestCase.assertEquals;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.ciphers.Aes128GcmNoPadding;
import org.jivesoftware.smackx.jet.component.JetSecurity;
import org.jivesoftware.smackx.jet.element.JetSecurityElement;
import org.junit.Test;
import org.jxmpp.jid.FullJid;
import org.xml.sax.SAXException;
public class JetElementTest extends SmackTestSuite {
@Test
public void jetTest() throws InterruptedException, JingleEnvelopeManager.JingleEncryptionException, NoSuchAlgorithmException, SmackException.NotConnectedException, SmackException.NoResponseException, IOException, SAXException {
ExtensionElement child = new SecurityStub().encryptJingleTransfer(null, null);
JetSecurityElement element = new JetSecurityElement("content1", Aes128GcmNoPadding.NAMESPACE, child);
JetSecurity security = new JetSecurity(element);
assertEquals(SecurityStub.NAMESPACE, security.getEnvelopeNamespace());
assertEquals(Aes128GcmNoPadding.NAMESPACE, element.getCipherName());
assertEquals(SecurityStub.NAMESPACE, element.getEnvelopeNamespace());
assertEquals("content1", element.getContentName());
String xml = "<security xmlns='" + JetSecurity.NAMESPACE + "' " +
"name='content1' " +
"cipher='" + Aes128GcmNoPadding.NAMESPACE + "' " +
"type='" + SecurityStub.NAMESPACE + "'>" +
"<security-stub/>" +
"</security>";
assertXMLEqual(xml, security.getElement().toXML().toString());
}
private static class SecurityStub implements JingleEnvelopeManager {
public static final String NAMESPACE = "urn:xmpp:security-stub";
@Override
public ExtensionElement encryptJingleTransfer(FullJid recipient, byte[] keyData) throws JingleEncryptionException, InterruptedException, NoSuchAlgorithmException, SmackException.NotConnectedException, SmackException.NoResponseException {
return new ExtensionElement() {
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public String getElementName() {
return "security-stub";
}
@Override
public CharSequence toXML() {
return "<security-stub/>";
}
};
}
@Override
public byte[] decryptJingleTransfer(FullJid sender, ExtensionElement envelope) throws JingleEncryptionException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException {
return new byte[0];
}
@Override
public XMPPConnection getConnection() {
return null;
}
@Override
public String getJingleEnvelopeNamespace() {
return NAMESPACE;
}
}
}

View file

@ -1,67 +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 static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.hashes.HashManager;
import org.jivesoftware.smackx.hashes.element.HashElement;
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.ChecksumElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;
import org.jivesoftware.smackx.jingle_filetransfer.element.Range;
import org.jivesoftware.smackx.jingle_filetransfer.provider.ChecksumProvider;
import org.junit.Test;
/**
* Created by vanitas on 12.07.17.
*/
public class ChecksumTest extends SmackTestSuite {
@Test
public void parserTest() throws Exception {
HashElement hash = new HashElement(HashManager.ALGORITHM.SHA_256, "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=");
JingleFileTransferChildElement file = new JingleFileTransferChildElement(null, null, hash, null, null, -1, null);
ChecksumElement checksum = new ChecksumElement(JingleContentElement.Creator.initiator, "name", file);
String xml = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator' name='name'>" +
"<file>" +
"<hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=</hash>" +
"</file>" +
"</checksum>";
assertXMLEqual(xml, checksum.toXML().toString());
assertXMLEqual(xml, new ChecksumProvider().parse(TestUtils.getParser(xml)).toXML().toString());
Range range = new Range(12L,34L);
file = new JingleFileTransferChildElement(null, null, hash, null, null, -1, range);
checksum = new ChecksumElement(JingleContentElement.Creator.initiator, "name", file);
xml = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator' name='name'>" +
"<file>" +
"<range offset='12' length='34'/>" +
"<hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=</hash>" +
"</file>" +
"</checksum>";
assertXMLEqual(xml, checksum.toXML().toString());
assertXMLEqual(xml, new ChecksumProvider().parse(TestUtils.getParser(xml)).toXML().toString());
}
}

View file

@ -1,40 +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 static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
import java.util.Date;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleIncomingFileOffer;
import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement;
import org.junit.Test;
public class IncomingFileTransferTest extends SmackTestSuite {
@Test
public void incomingFileOfferTest() {
Date date = new Date();
JingleFileTransferChildElement offerElement = new JingleFileTransferChildElement(date, "description", null, "application/octet-stream", "name", 1234, null);
JingleIncomingFileOffer offer = new JingleIncomingFileOffer(offerElement);
assertTrue(offer.isOffer());
assertFalse(offer.isRequest());
}
}

View file

@ -1,145 +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 static org.jivesoftware.smackx.omemo.OmemoIntegrationTestHelper.cleanServerSideTraces;
import static org.jivesoftware.smackx.omemo.OmemoIntegrationTestHelper.setUpOmemoManager;
import static org.jivesoftware.smackx.omemo.OmemoIntegrationTestHelper.subscribe;
import static org.jivesoftware.smackx.omemo.OmemoIntegrationTestHelper.unidirectionalTrust;
import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.transport.jingle_ibb.JingleIBBTransportManager;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.JingleS5BTransportManager;
import org.jivesoftware.smackx.jingle_filetransfer.JingleFileTransferManager;
import org.jivesoftware.smackx.jingle_filetransfer.component.JingleFileTransferFile;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingFileOfferListener;
import org.jivesoftware.smackx.jingle_filetransfer.listener.ProgressListener;
import org.jivesoftware.smackx.omemo.AbstractOmemoIntegrationTest;
import org.jivesoftware.smackx.omemo.OmemoManager;
import org.jivesoftware.smackx.omemo.OmemoService;
import org.jivesoftware.smackx.omemo.OmemoStore;
import org.jivesoftware.smackx.omemo.provider.OmemoVAxolotlProvider;
import org.jivesoftware.smackx.omemo.util.OmemoConstants;
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
import org.igniterealtime.smack.inttest.TestNotPossibleException;
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
public class JetIntegrationTest extends AbstractOmemoIntegrationTest {
private OmemoManager oa, ob;
private JetManager ja, jb;
private JingleIBBTransportManager ia, ib;
private JingleS5BTransportManager sa, sb;
private OmemoStore<?,?,?,?,?,?,?,?,?> store;
public JetIntegrationTest(SmackIntegrationTestEnvironment environment)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, TestNotPossibleException {
super(environment);
}
@Override
public void before() {
store = OmemoService.getInstance().getOmemoStoreBackend();
oa = OmemoManager.getInstanceFor(conOne, 666);
ob = OmemoManager.getInstanceFor(conTwo, 777);
ja = JetManager.getInstanceFor(conOne);
jb = JetManager.getInstanceFor(conTwo);
ia = JingleIBBTransportManager.getInstanceFor(conOne);
ib = JingleIBBTransportManager.getInstanceFor(conTwo);
sa = JingleS5BTransportManager.getInstanceFor(conOne);
sb = JingleS5BTransportManager.getInstanceFor(conTwo);
JetManager.registerEnvelopeProvider(OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL, new OmemoVAxolotlProvider());
}
@SmackIntegrationTest
public void JingleEncryptedFileTransferTest()
throws Exception {
final SimpleResultSyncPoint received = new SimpleResultSyncPoint();
Random weakRandom = new Random();
//Setup OMEMO
subscribe(oa, ob, "Bob");
subscribe(ob, oa, "Alice");
setUpOmemoManager(oa);
setUpOmemoManager(ob);
unidirectionalTrust(oa, ob);
unidirectionalTrust(ob, oa);
ja.registerEnvelopeManager(oa);
jb.registerEnvelopeManager(ob);
byte[] sourceBytes = new byte[16000];
weakRandom.nextBytes(sourceBytes);
InputStream sourceStream = new ByteArrayInputStream(sourceBytes);
final ByteArrayOutputStream targetStream = new ByteArrayOutputStream(16000);
JingleFileTransferManager.getInstanceFor(conTwo).addIncomingFileOfferListener(new IncomingFileOfferListener() {
@Override
public void onIncomingFileOffer(IncomingFileOfferController offer) {
try {
offer.addProgressListener(new ProgressListener() {
@Override
public void started() {
}
@Override
public void progress(float percent) {
}
@Override
public void finished() {
received.signal();
}
});
offer.accept(conTwo, targetStream);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
received.signal(e);
}
}
});
ja.sendEncryptedStream(sourceStream, new JingleFileTransferFile.StreamFile("test", sourceBytes.length, "desc", null, null, null), conTwo.getUser().asFullJidOrThrow(), oa);
received.waitForResult(60 * 1000);
assertArrayEquals(sourceBytes, targetStream.toByteArray());
}
@Override
public void after() {
oa.shutdown();
ob.shutdown();
cleanServerSideTraces(oa);
cleanServerSideTraces(ob);
}
}

View file

@ -1,21 +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.
*/
/**
* Tests for XEP-XXXX - Jingle Encrypted Transfers.
*/
package org.jivesoftware.smackx.jet;

View file

@ -1,178 +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 static junit.framework.TestCase.fail;
import static org.junit.Assert.assertArrayEquals;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.Future;
import java.util.logging.Level;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy;
import org.jivesoftware.smackx.jingle.transport.jingle_ibb.JingleIBBTransportManager;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingFileOfferListener;
import org.jivesoftware.smackx.jingle_filetransfer.listener.ProgressListener;
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
import org.junit.AfterClass;
import org.jxmpp.jid.FullJid;
/**
* Created by vanitas on 29.06.17.
*/
public class JingleFileTransferIntegrationTest extends AbstractSmackIntegrationTest {
private static final File tempDir;
static {
String userHome = System.getProperty("user.home");
if (userHome != null) {
File f = new File(userHome);
tempDir = new File(f, ".config/smack-integration-test/");
} else {
tempDir = new File("int_test_jingle");
}
}
public JingleFileTransferIntegrationTest(SmackIntegrationTestEnvironment environment) {
super(environment);
}
@SmackIntegrationTest
public void basicFileTransferTest() throws Exception {
JingleIBBTransportManager.getInstanceFor(conOne);
JingleIBBTransportManager.getInstanceFor(conTwo);
final SimpleResultSyncPoint resultSyncPoint1 = new SimpleResultSyncPoint();
final SimpleResultSyncPoint resultSyncPoint2 = new SimpleResultSyncPoint();
FullJid alice = conOne.getUser().asFullJidOrThrow();
FullJid bob = conTwo.getUser().asFullJidOrThrow();
File source = prepareNewTestFile("source");
final File target = new File(tempDir, "target");
JingleFileTransferManager aftm = JingleFileTransferManager.getInstanceFor(conOne);
JingleFileTransferManager bftm = JingleFileTransferManager.getInstanceFor(conTwo);
final ArrayList<Future<Void>> receiveFuture = new ArrayList<>(); //Uglaay
bftm.addIncomingFileOfferListener(new IncomingFileOfferListener() {
@Override
public void onIncomingFileOffer(IncomingFileOfferController offer) {
LOGGER.log(Level.INFO, "INCOMING FILE TRANSFER!");
offer.addProgressListener(new ProgressListener() {
@Override
public void started() {
}
@Override
public void progress(float percent) {
}
@Override
public void finished() {
resultSyncPoint2.signal();
}
});
try {
offer.accept(conTwo, target);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
fail(e.toString());
}
}
});
OutgoingFileOfferController sending = aftm.sendFile(source, bob);
sending.addProgressListener(new ProgressListener() {
@Override
public void started() {
}
@Override
public void progress(float percent) {
}
@Override
public void finished() {
resultSyncPoint1.signal();
}
});
resultSyncPoint1.waitForResult(60 * 1000);
resultSyncPoint2.waitForResult(60 * 1000);
byte[] sBytes = new byte[(int) source.length()];
byte[] tBytes = new byte[(int) target.length()];
try {
FileInputStream fi = new FileInputStream(source);
fi.read(sBytes);
fi.close();
fi = new FileInputStream(target);
fi.read(tBytes);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not read files.");
fail();
}
assertArrayEquals(sBytes, tBytes);
LOGGER.log(Level.INFO, "SUCCESSFULLY SENT AND RECEIVED");
}
public static File prepareNewTestFile(String name) {
File testFile = new File(tempDir, name);
try {
if (!testFile.exists()) {
testFile.createNewFile();
}
FileOutputStream fo = new FileOutputStream(testFile);
byte[] rand = new byte[16000];
INSECURE_RANDOM.nextBytes(rand);
fo.write(rand);
fo.close();
return testFile;
} catch (IOException e) {
return null;
}
}
@AfterClass
public static void cleanup() {
Socks5Proxy.getSocks5Proxy().stop();
}
}

View file

@ -1,192 +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 static junit.framework.TestCase.fail;
import static org.junit.Assert.assertArrayEquals;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy;
import org.jivesoftware.smackx.jingle.transport.jingle_ibb.JingleIBBTransportManager;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.JingleS5BTransportManager;
import org.jivesoftware.smackx.jingle_filetransfer.controller.IncomingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.controller.OutgoingFileOfferController;
import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingFileOfferListener;
import org.jivesoftware.smackx.jingle_filetransfer.listener.ProgressListener;
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.jxmpp.jid.FullJid;
public class JingleFileTransferTransportFallbackIntegrationTest extends AbstractSmackIntegrationTest {
private static final File tempDir;
static {
String userHome = System.getProperty("user.home");
if (userHome != null) {
File f = new File(userHome);
tempDir = new File(f, ".config/smack-integration-test/");
} else {
tempDir = new File("int_test_jingle");
}
}
public JingleFileTransferTransportFallbackIntegrationTest(SmackIntegrationTestEnvironment environment) {
super(environment);
}
@Before
public void crippleS5B() {
// Manipulate the Manager so that it'll fail.
JingleS5BTransportManager.useExternalCandidates = false;
JingleS5BTransportManager.useLocalCandidates = false;
// *evil super villain laughter*
}
@SmackIntegrationTest
public void S5BtoIBBfallbackTest() throws Exception {
JingleS5BTransportManager.getInstanceFor(conOne);
JingleS5BTransportManager.getInstanceFor(conTwo);
// Use Jingle IBB Transport as fallback.
JingleIBBTransportManager.getInstanceFor(conOne);
JingleIBBTransportManager.getInstanceFor(conTwo);
final SimpleResultSyncPoint resultSyncPoint1 = new SimpleResultSyncPoint();
final SimpleResultSyncPoint resultSyncPoint2 = new SimpleResultSyncPoint();
FullJid alice = conOne.getUser().asFullJidOrThrow();
FullJid bob = conTwo.getUser().asFullJidOrThrow();
File source = prepareNewTestFile("source");
final File target = new File(tempDir, "target");
JingleFileTransferManager aftm = JingleFileTransferManager.getInstanceFor(conOne);
JingleFileTransferManager bftm = JingleFileTransferManager.getInstanceFor(conTwo);
bftm.addIncomingFileOfferListener(new IncomingFileOfferListener() {
@Override
public void onIncomingFileOffer(IncomingFileOfferController offer) {
LOGGER.log(Level.INFO, "INCOMING FILE TRANSFER!");
offer.addProgressListener(new ProgressListener() {
@Override
public void started() {
}
@Override
public void progress(float percent) {
}
@Override
public void finished() {
resultSyncPoint2.signal();
}
});
try {
offer.accept(conTwo, target);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
fail(e.toString());
}
}
});
OutgoingFileOfferController sending = aftm.sendFile(source, bob);
sending.addProgressListener(new ProgressListener() {
@Override
public void started() {
}
@Override
public void progress(float percent) {
}
@Override
public void finished() {
resultSyncPoint1.signal();
}
});
resultSyncPoint1.waitForResult(60 * 1000);
resultSyncPoint2.waitForResult(60 * 1000);
byte[] sBytes = new byte[(int) source.length()];
byte[] tBytes = new byte[(int) target.length()];
try {
FileInputStream fi = new FileInputStream(source);
fi.read(sBytes);
fi.close();
fi = new FileInputStream(target);
fi.read(tBytes);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not read files.");
fail();
}
assertArrayEquals(sBytes, tBytes);
LOGGER.log(Level.INFO, "SUCCESSFULLY SENT AND RECEIVED");
}
@After
public void cureS5B() {
JingleS5BTransportManager.useExternalCandidates = true;
JingleS5BTransportManager.useLocalCandidates = true;
}
public static File prepareNewTestFile(String name) {
File testFile = new File(tempDir, name);
try {
if (!testFile.exists()) {
testFile.createNewFile();
}
FileOutputStream fo = new FileOutputStream(testFile);
byte[] rand = new byte[16000];
INSECURE_RANDOM.nextBytes(rand);
fo.write(rand);
fo.close();
return testFile;
} catch (IOException e) {
return null;
}
}
@AfterClass
public void cleanup() {
Socks5Proxy.getSocks5Proxy().stop();
}
}

View file

@ -1,21 +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.
*/
/**
* Tests for XEP-0234 - Jingle File Transfer.
*/
package org.jivesoftware.smackx.jingle_filetransfer;