From 5ead24e416634a47b31b9d88bebbc38301bd4b31 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sun, 27 Jul 2014 23:45:19 +0200 Subject: [PATCH 1/9] Smack 4.0.3-SNAPSHOT --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8cf025fe6..04e1875c7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,8 @@ allprojects { apply plugin: 'eclipse' ext { - shortVersion = '4.0.2' - isSnapshot = false + shortVersion = '4.0.3' + isSnapshot = true gitCommit = getGitCommit() javadocAllDir = new File(buildDir, 'javadoc') documentationDir = new File(projectDir, 'documentation') From 0b6069d75f3e513f13ccf837b16da8cb38644e69 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 30 Jul 2014 21:58:10 +0200 Subject: [PATCH 2/9] Fix FormField.Option.toXML() to use correct element Fixes SMACK-589 --- .../main/java/org/jivesoftware/smackx/xdata/FormField.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java index 1e7ba1bd8..5b8172f5c 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java @@ -313,7 +313,7 @@ public class FormField { */ public static class Option { - public static final String ELEMNT = "option"; + public static final String ELEMENT = "option"; private final String value; private String label; @@ -352,7 +352,7 @@ public class FormField { public XmlStringBuilder toXML() { XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(ELEMNT); + xml.halfOpenElement(ELEMENT); // Add attribute xml.optAttribute("label", getLabel()); xml.rightAngelBracket(); From 1935039432113a7437c19066d8129164bb73c7f2 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 31 Jul 2014 19:45:00 +0200 Subject: [PATCH 3/9] Improve documentation (targetCompatibility, XPP3) --- build.gradle | 3 ++- documentation/gettingstarted.html | 6 ++---- resources/releasedocs/README.html | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 04e1875c7..79b7392da 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,7 @@ allprojects { } group = 'org.igniterealtime.smack' sourceCompatibility = 1.7 + targetCompatibility = sourceCompatibility version = shortVersion if (isSnapshot) { version += '-SNAPSHOT' @@ -81,7 +82,7 @@ import org.apache.tools.ant.filters.ReplaceTokens task prepareReleasedocs(type: Copy) { from 'resources/releasedocs' into releasedocsDir - filter(ReplaceTokens, tokens: [version: version, releasedate: buildDate]) + filter(ReplaceTokens, tokens: [version: version, releasedate: buildDate, targetCompatibility: targetCompatibility.toString()]) } task distributionZip(type: Zip, dependsOn: [javadocAll, prepareReleasedocs]) { diff --git a/documentation/gettingstarted.html b/documentation/gettingstarted.html index ee5c35273..de817b244 100644 --- a/documentation/gettingstarted.html +++ b/documentation/gettingstarted.html @@ -23,10 +23,8 @@ important classes and concepts. JAR Files and Requirements

-Smack is meant to be easily embedded into any existing JDK 1.5 or later Java application. -It has no external dependencies (except for the Jingle voice chat functionality) and is optimized -to be as small as possible. The library ships as several JAR files to provide more flexibility -over which features applications require: +Smack is meant to be easily embedded into any existing Java application. +The library ships as several JAR files to provide more flexibility over which features applications require:
  • smack-core.jar -- provides core XMPP functionality. All XMPP features that are diff --git a/resources/releasedocs/README.html b/resources/releasedocs/README.html index d1a220e4c..962c43fbc 100644 --- a/resources/releasedocs/README.html +++ b/resources/releasedocs/README.html @@ -154,18 +154,27 @@ hr {

    -Thank you for downloading Smack! -

    +Thank you for downloading Smack! This version of Smack is compatible +with JVMs @targetCompatibility@ or higher. If you dont' use a +dependency resolution system, like gradle or maven, then you will need +to download at least +the Xml +Pull Parser 3rd Edition (XPP3) library or any other library that +implements the XmlPullParser interface +(like kXML). +

    +

    Start off by viewing the documentation that can be found in the "documentation" directory included with this distribution. -

    +

    Further information can be found on the Smack website. If you need help using or would like to make contributions or fixes to the code, please visit the online forum. - -

    About the Distribution

    +

    + +

    About the Distribution

    The smack-core.jar file in the main distribution folder. The optional smack-extensions.jar contains the Smack extensions From 66da4dfa91cc4cadfa0170a3c9e04f25c6bcf282 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Fri, 1 Aug 2014 23:15:46 +0200 Subject: [PATCH 4/9] Fix Typo: s/isSubscibe/isSubscribe/ in ConfigureForm Fixes SMACK-588 --- .../jivesoftware/smackx/pubsub/ConfigureForm.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java index f6f6cb76a..297557daf 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java @@ -577,12 +577,23 @@ public class ConfigureForm extends Form * Determines if subscriptions are allowed. * * @return true if subscriptions are allowed, false otherwise + * @deprecated use {@link #isSubscribe()} instead */ + @Deprecated public boolean isSubscibe() { - return parseBoolean(getFieldValue(ConfigureNodeFields.subscribe)); + return isSubscribe(); } + /** + * Determines if subscriptions are allowed. + * + * @return true if subscriptions are allowed, false otherwise + */ + public boolean isSubscribe() { + return parseBoolean(getFieldValue(ConfigureNodeFields.subscribe)); + } + /** * Sets whether subscriptions are allowed. * From a574e1d56d5530c6b836f14b5f70e12cce119fbb Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Fri, 1 Aug 2014 23:20:35 +0200 Subject: [PATCH 5/9] Verify ConnectionConfiguration parameters also fix javadoc error for StringUtils.isNullOrEmpty() Fixes SMACK-539 --- .../smack/ConnectionConfiguration.java | 7 +++++++ .../org/jivesoftware/smack/util/StringUtils.java | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index f8e69533c..544f3ac48 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -20,6 +20,7 @@ package org.jivesoftware.smack; import org.jivesoftware.smack.packet.Session; import org.jivesoftware.smack.proxy.ProxyInfo; import org.jivesoftware.smack.util.DNSUtil; +import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.dns.HostAddress; import javax.net.SocketFactory; @@ -180,6 +181,9 @@ public class ConnectionConfiguration implements Cloneable { } protected void init(String serviceName, ProxyInfo proxy) { + if (StringUtils.isEmpty(serviceName)) { + throw new IllegalArgumentException("serviceName must not be the empty String"); + } this.serviceName = serviceName; this.proxy = proxy; @@ -597,6 +601,9 @@ public class ConnectionConfiguration implements Cloneable { } private void initHostAddresses(String host, int port) { + if (StringUtils.isEmpty(host)) { + throw new IllegalArgumentException("host must not be the empty String"); + } hostAddresses = new ArrayList(1); HostAddress hostAddress; hostAddress = new HostAddress(host, port); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java index 132e1d340..796b7ff1f 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java @@ -528,12 +528,22 @@ public class StringUtils { } /** - * Returns true if the given CharSequence is not null or empty. + * Returns true if the given CharSequence is null or empty. * * @param cs - * @return true if the given CharSequence is not null or empty + * @return true if the given CharSequence is null or empty */ public static boolean isNullOrEmpty(CharSequence cs) { - return cs == null || cs.length() == 0; + return cs == null || isEmpty(cs); + } + + /** + * Returns true if the given CharSequence is empty + * + * @param cs + * @return true if the given CharSequence is empty + */ + public static boolean isEmpty(CharSequence cs) { + return cs.length() == 0; } } From d65d239550812b0dd5bc2897b3fe9576b59bb578 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Mon, 4 Aug 2014 12:19:58 +0200 Subject: [PATCH 6/9] Make getMessages() set up collector *before* sending the request Similar flaw was also fixed in 2c7f1efe80b988. Also ensure that OfflineMessagesManager doesn't leak collector by using a try/finally block. Fixes SMACK-592 --- .../smackx/offline/OfflineMessageManager.java | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/OfflineMessageManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/OfflineMessageManager.java index 8c7bfb75d..3d7d13b88 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/OfflineMessageManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/OfflineMessageManager.java @@ -156,20 +156,24 @@ public class OfflineMessageManager { } }); PacketCollector messageCollector = connection.createPacketCollector(messageFilter); - connection.createPacketCollectorAndSend(request).nextResultOrThrow(); - // Collect the received offline messages - Message message = (Message) messageCollector.nextResult(); - while (message != null) { - messages.add(message); - message = (Message) messageCollector.nextResult(); + try { + connection.createPacketCollectorAndSend(request).nextResultOrThrow(); + // Collect the received offline messages + Message message = (Message) messageCollector.nextResult(); + while (message != null) { + messages.add(message); + message = (Message) messageCollector.nextResult(); + } + } + finally { + // Stop queuing offline messages + messageCollector.cancel(); } - // Stop queuing offline messages - messageCollector.cancel(); return messages; } /** - * Returns an Iterator with all the offline Messages of the user. The returned offline + * Returns a List of Messages with all the offline Messages of the user. The returned offline * messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)} * to delete the messages. * @@ -183,17 +187,22 @@ public class OfflineMessageManager { List messages = new ArrayList(); OfflineMessageRequest request = new OfflineMessageRequest(); request.setFetch(true); - connection.createPacketCollectorAndSend(request).nextResultOrThrow(); PacketCollector messageCollector = connection.createPacketCollector(packetFilter); - // Collect the received offline messages - Message message = (Message) messageCollector.nextResult(); - while (message != null) { - messages.add(message); - message = (Message) messageCollector.nextResult(); + try { + connection.createPacketCollectorAndSend(request).nextResultOrThrow(); + + // Collect the received offline messages + Message message = (Message) messageCollector.nextResult(); + while (message != null) { + messages.add(message); + message = (Message) messageCollector.nextResult(); + } + } + finally { + // Stop queuing offline messages + messageCollector.cancel(); } - // Stop queuing offline messages - messageCollector.cancel(); return messages; } From 5c2f051c1ce6d4a4e1ac3529ea984f20018347c1 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Tue, 5 Aug 2014 09:32:13 +0200 Subject: [PATCH 7/9] Make Socks5Proxy try other ports if 7777 is already in use by setting the default value to '-7777' (negative values mean that the next port number will be tried if the current one is in use). --- .../smackx/bytestreams/socks5/Socks5Proxy.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java index 08a0abfff..1728347aa 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java @@ -73,7 +73,12 @@ public class Socks5Proxy { private static Socks5Proxy socks5Server; private static boolean localSocks5ProxyEnabled = true; - private static int localSocks5ProxyPort = 7777; + + /** + * The port of the local Socks5 Proxy. If this value is negative, the next ports will be tried + * until a unused is found. + */ + private static int localSocks5ProxyPort = -7777; /* reusable implementation of a SOCKS5 proxy server process */ private Socks5ServerProcess serverProcess; From 4e588f7908d2fc5a8952828a53e58fed97c395e2 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Tue, 5 Aug 2014 09:33:20 +0200 Subject: [PATCH 8/9] Throw IAE if invalid port number is given for Socks5Proxy --- .../jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java index 1728347aa..855cba222 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java @@ -147,6 +147,9 @@ public class Socks5Proxy { * @param localSocks5ProxyPort the port of the local Socks5 proxy to set */ public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) { + if (Math.abs(localSocks5ProxyPort) > 65535) { + throw new IllegalArgumentException("localSocks5ProxyPort must be within (-65535,65535)"); + } Socks5Proxy.localSocks5ProxyPort = localSocks5ProxyPort; } From c3f6c51d0ea3735877e2854e0b5b352a27230c91 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 7 Aug 2014 14:42:30 +0200 Subject: [PATCH 9/9] Add a setting for the used flush mode when compressing data Fixes SMACK-593 --- .../jzlib/JzlibInputOutputStream.java | 4 +++- .../Java7ZlibInputOutputStream.java | 23 ++++++++++--------- .../compression/XMPPInputOutputStream.java | 20 ++++++++++++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/smack-compression-jzlib/src/main/java/org/jivesoftware/smack/compression/jzlib/JzlibInputOutputStream.java b/smack-compression-jzlib/src/main/java/org/jivesoftware/smack/compression/jzlib/JzlibInputOutputStream.java index 356eef8a0..68e4d16d5 100644 --- a/smack-compression-jzlib/src/main/java/org/jivesoftware/smack/compression/jzlib/JzlibInputOutputStream.java +++ b/smack-compression-jzlib/src/main/java/org/jivesoftware/smack/compression/jzlib/JzlibInputOutputStream.java @@ -58,7 +58,9 @@ public class JzlibInputOutputStream extends XMPPInputOutputStream { @Override public OutputStream getOutputStream(OutputStream outputStream) throws IOException { final DeflaterOutputStream os = new DeflaterOutputStream(outputStream); - os.setSyncFlush(true); + if (flushMethod == FlushMethod.SYNC_FLUSH) { + os.setSyncFlush(true); + } return os; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java index 906a8e1f0..0f7933faa 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java @@ -48,6 +48,9 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream { private final static boolean supported; private final static int compressionLevel = Deflater.DEFAULT_COMPRESSION; + private static final int SYNC_FLUSH_INT = 2; + private static final int FULL_FLUSH_INT = 3; + static { Method m = null; try { @@ -100,25 +103,23 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream { @Override public OutputStream getOutputStream(OutputStream outputStream) { + final int flushMethodInt; + if (flushMethod == FlushMethod.SYNC_FLUSH) { + flushMethodInt = SYNC_FLUSH_INT; + } else { + flushMethodInt = FULL_FLUSH_INT; + } return new DeflaterOutputStream(outputStream, new Deflater(compressionLevel)) { public void flush() throws IOException { if (!supported) { super.flush(); return; } - int count = 0; - if (!def.needsInput()) { - do { - count = def.deflate(buf, 0, buf.length); - out.write(buf, 0, count); - } while (count > 0); - out.flush(); - } try { - do { - count = (Integer) method.invoke(def, buf, 0, buf.length, 2); + int count; + while ((count = (Integer) method.invoke(def, buf, 0, buf.length, flushMethodInt)) != 0) { out.write(buf, 0, count); - } while (count > 0); + } } catch (IllegalArgumentException e) { throw new IOException("Can't flush"); } catch (IllegalAccessException e) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java index 41308243f..6fd289325 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java @@ -20,6 +20,21 @@ import java.io.InputStream; import java.io.OutputStream; public abstract class XMPPInputOutputStream { + + protected static FlushMethod flushMethod; + + /** + * Set the used flushed method when compressing data. The default is full flush which may not + * achieve the best compression ratio, but provides better security against certain attacks. + * Only use sync flush if you fully understand the implications. + * + * @see Attacks against XMPP when using compression + * @param flushMethod + */ + public static void setFlushMethod(FlushMethod flushMethod) { + XMPPInputOutputStream.flushMethod = flushMethod; + } + protected String compressionMethod; public String getCompressionMethod() { @@ -31,4 +46,9 @@ public abstract class XMPPInputOutputStream { public abstract InputStream getInputStream(InputStream inputStream) throws Exception; public abstract OutputStream getOutputStream(OutputStream outputStream) throws Exception; + + public enum FlushMethod { + FULL_FLUSH, + SYNC_FLUSH, + } }