diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/HashManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/HashManager.java index d9ae513c7..de97ffb77 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/HashManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/HashManager.java @@ -20,6 +20,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.hash.element.HashElement; import java.math.BigInteger; import java.security.MessageDigest; @@ -95,6 +96,14 @@ public final class HashManager extends Manager { addAlgorithmsToFeatures(RECOMMENDED); } + public static HashElement calculateHashElement(ALGORITHM algorithm, byte[] data) { + return new HashElement(algorithm, hash(algorithm, data)); + } + + public static HashElement assembleHashElement(ALGORITHM algorithm, byte[] hash) { + return new HashElement(algorithm, hash); + } + /** * Announce support for the given list of algorithms. * @param algorithms diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/element/HashElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/element/HashElement.java index 42ead8210..5d97e3695 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/element/HashElement.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hash/element/HashElement.java @@ -60,17 +60,6 @@ public class HashElement implements ExtensionElement { this.hashB64 = hashB64; } - /** - * Create a new HashElement that contains the hash sum calculated using 'algorithm' based on the data in 'data'. - * - * @param algorithm algorithm which will be used to calculate data's checksum. - * @param data data of which we will calculate the checksum. - * @return HashElement with the checksum of data. - */ - public static HashElement fromData(HashManager.ALGORITHM algorithm, byte[] data) { - return new HashElement(algorithm, HashManager.hash(algorithm, data)); - } - /** * Return the hash algorithm used in this HashElement. * @return algorithm diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/DirtyHelper.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/DirtyHelper.java index 34bd10722..1b0d992f3 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/DirtyHelper.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/DirtyHelper.java @@ -1,22 +1,45 @@ +/** + * + * 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 org.jivesoftware.smackx.hash.HashManager; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.security.DigestInputStream; /** * Dirty. */ public final class DirtyHelper { - public static byte[] readFile(File file) throws IOException { + public static BytesAndDigest readFile(File file, HashManager.ALGORITHM algorithm) throws IOException { byte[] bytes = null; + byte[] digest = null; int read; FileInputStream fin = null; try { fin = new FileInputStream(file); + DigestInputStream din = new DigestInputStream(fin, HashManager.getMessageDigest(algorithm)); bytes = new byte[(int) file.length()]; - read = fin.read(bytes); + read = din.read(bytes); + din.close(); + digest = din.getMessageDigest().digest(); } finally { if (fin != null) { fin.close(); @@ -26,6 +49,24 @@ public final class DirtyHelper { return null; } - return bytes; + return new BytesAndDigest(bytes, digest); + } + + public static class BytesAndDigest { + + private final byte[] bytes, digest; + + public BytesAndDigest(byte[] bytes, byte[] digest) { + this.bytes = bytes; + this.digest = digest; + } + + public byte[] getBytes() { + return bytes; + } + + public byte[] getDigest() { + return digest; + } } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java index 8f3e3cb24..db55476b5 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java @@ -25,7 +25,6 @@ import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager; import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamSession; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.hash.HashManager; -import org.jivesoftware.smackx.hash.element.HashElement; import org.jivesoftware.smackx.jingle.JingleManager; import org.jivesoftware.smackx.jingle.JingleSessionHandler; import org.jivesoftware.smackx.jingle.element.Jingle; @@ -94,14 +93,10 @@ public final class JingleFileTransferManager extends Manager { * @param file */ public void sendFile(File file, final FullJid recipient) throws IOException, SmackException.NotConnectedException, InterruptedException { - final byte[] bytes = DirtyHelper.readFile(file); - if (bytes == null) { - LOGGER.log(Level.SEVERE, "bytes are null."); - return; - } + final DirtyHelper.BytesAndDigest bd = DirtyHelper.readFile(file, HashManager.ALGORITHM.SHA_256); Date lastModified = new Date(file.lastModified()); JingleFileTransferPayload payload = new JingleFileTransferPayload( - lastModified, "A file", HashElement.fromData(HashManager.ALGORITHM.SHA_256, bytes), + lastModified, "A file", HashManager.assembleHashElement(HashManager.ALGORITHM.SHA_256, bd.getDigest()), "application/octet-stream", file.getName(), (int) file.length(), null); ArrayList payloadTypes = new ArrayList<>(); payloadTypes.add(payload); @@ -142,7 +137,7 @@ public final class JingleFileTransferManager extends Manager { } try { - session.getOutputStream().write(bytes); + session.getOutputStream().write(bd.getBytes()); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Fail while writing: " + e, e); } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferPayload.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferPayload.java index fceaabbd2..63dba8c54 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferPayload.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferPayload.java @@ -20,6 +20,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.hash.element.HashElement; import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionPayloadType; +import java.io.File; import java.util.Date; /** @@ -121,4 +122,66 @@ public class JingleFileTransferPayload extends JingleContentDescriptionPayloadTy 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 int 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; + } + + public Builder setMediaType(String mediaType) { + this.mediaType = mediaType; + return this; + } + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setSize(int size) { + this.size = size; + return this; + } + + public Builder setRange(Range range) { + this.range = range; + return this; + } + + public JingleFileTransferPayload build() { + return new JingleFileTransferPayload(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()); + } + } + } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/hash/HashElementTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/hash/HashElementTest.java index 5872263ca..143a3f29c 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/hash/HashElementTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/hash/HashElementTest.java @@ -37,7 +37,7 @@ public class HashElementTest extends SmackTestSuite { @Test public void stanzaTest() throws Exception { String message = "Hello World!"; - HashElement element = HashElement.fromData(SHA_256, message.getBytes(StringUtils.UTF8)); + HashElement element = HashManager.calculateHashElement(SHA_256, message.getBytes(StringUtils.UTF8)); String expected = "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk="; assertEquals(expected, element.toXML().toString()); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java index c58a4f5ee..96db3e26f 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java @@ -1,3 +1,19 @@ +/** + * + * 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_ibb; import org.jivesoftware.smack.test.util.SmackTestSuite;