mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 14:22:05 +01:00
Merge branch '4.0'
Also slightly improve OfflineMessageManager.getMessages() Conflicts: build.gradle smack-extensions/src/main/java/org/jivesoftware/smackx/offline/OfflineMessageManager.java
This commit is contained in:
commit
92a6d01507
12 changed files with 123 additions and 46 deletions
|
@ -26,6 +26,7 @@ allprojects {
|
||||||
}
|
}
|
||||||
group = 'org.igniterealtime.smack'
|
group = 'org.igniterealtime.smack'
|
||||||
sourceCompatibility = 1.7
|
sourceCompatibility = 1.7
|
||||||
|
targetCompatibility = sourceCompatibility
|
||||||
version = shortVersion
|
version = shortVersion
|
||||||
if (isSnapshot) {
|
if (isSnapshot) {
|
||||||
version += '-SNAPSHOT'
|
version += '-SNAPSHOT'
|
||||||
|
@ -97,7 +98,7 @@ import org.apache.tools.ant.filters.ReplaceTokens
|
||||||
task prepareReleasedocs(type: Copy) {
|
task prepareReleasedocs(type: Copy) {
|
||||||
from 'resources/releasedocs'
|
from 'resources/releasedocs'
|
||||||
into releasedocsDir
|
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]) {
|
task distributionZip(type: Zip, dependsOn: [javadocAll, prepareReleasedocs]) {
|
||||||
|
|
|
@ -23,10 +23,8 @@ important classes and concepts.
|
||||||
JAR Files and Requirements
|
JAR Files and Requirements
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Smack is meant to be easily embedded into any existing JDK 1.5 or later Java application.
|
Smack is meant to be easily embedded into any existing Java application.
|
||||||
It has no external dependencies (except for the Jingle voice chat functionality) and is optimized
|
The library ships as several JAR files to provide more flexibility over which features applications require:
|
||||||
to be as small as possible. The library ships as several JAR files to provide more flexibility
|
|
||||||
over which features applications require:
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>smack-core.jar</tt> -- provides core XMPP functionality. All XMPP features that are
|
<li><tt>smack-core.jar</tt> -- provides core XMPP functionality. All XMPP features that are
|
||||||
|
|
|
@ -154,18 +154,27 @@ hr {
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Thank you for downloading Smack!
|
Thank you for downloading Smack! This version of Smack is compatible
|
||||||
<p>
|
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 <a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/">Xml
|
||||||
|
Pull Parser 3rd Edition (XPP3) library</a> or any other library that
|
||||||
|
implements the XmlPullParser interface
|
||||||
|
(like <a href="http://kxml.org/">kXML</a>).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
Start off by viewing the <a href="documentation/index.html">documentation</a>
|
Start off by viewing the <a href="documentation/index.html">documentation</a>
|
||||||
that can be found in the "documentation" directory included with this distribution.
|
that can be found in the "documentation" directory included with this distribution.
|
||||||
<p>
|
</p>
|
||||||
Further information can be found on the <a href="http://www.igniterealtime.org/projects/smack">
|
Further information can be found on the <a href="http://www.igniterealtime.org/projects/smack">
|
||||||
Smack website</a>. If you need help using or would like to make contributions or
|
Smack website</a>. If you need help using or would like to make contributions or
|
||||||
fixes to the code, please visit the
|
fixes to the code, please visit the
|
||||||
<a href="https://community.igniterealtime.org">online forum</a>.
|
<a href="https://community.igniterealtime.org">online forum</a>.
|
||||||
|
</p>
|
||||||
<p><b>About the Distribution</b><p>
|
|
||||||
|
<p><b>About the Distribution</b></p>
|
||||||
|
|
||||||
The <tt>smack-core.jar</tt> file in the main distribution folder. The optional
|
The <tt>smack-core.jar</tt> file in the main distribution folder. The optional
|
||||||
<tt>smack-extensions.jar</tt> contains the <a href="documentation/extensions/index.html">Smack extensions</a>
|
<tt>smack-extensions.jar</tt> contains the <a href="documentation/extensions/index.html">Smack extensions</a>
|
||||||
|
|
|
@ -58,7 +58,9 @@ public class JzlibInputOutputStream extends XMPPInputOutputStream {
|
||||||
@Override
|
@Override
|
||||||
public OutputStream getOutputStream(OutputStream outputStream) throws IOException {
|
public OutputStream getOutputStream(OutputStream outputStream) throws IOException {
|
||||||
final DeflaterOutputStream os = new DeflaterOutputStream(outputStream);
|
final DeflaterOutputStream os = new DeflaterOutputStream(outputStream);
|
||||||
os.setSyncFlush(true);
|
if (flushMethod == FlushMethod.SYNC_FLUSH) {
|
||||||
|
os.setSyncFlush(true);
|
||||||
|
}
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.jivesoftware.smack;
|
||||||
import org.jivesoftware.smack.packet.Session;
|
import org.jivesoftware.smack.packet.Session;
|
||||||
import org.jivesoftware.smack.proxy.ProxyInfo;
|
import org.jivesoftware.smack.proxy.ProxyInfo;
|
||||||
import org.jivesoftware.smack.util.DNSUtil;
|
import org.jivesoftware.smack.util.DNSUtil;
|
||||||
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.dns.HostAddress;
|
import org.jivesoftware.smack.util.dns.HostAddress;
|
||||||
import org.jxmpp.util.XmppStringUtils;
|
import org.jxmpp.util.XmppStringUtils;
|
||||||
|
|
||||||
|
@ -191,6 +192,9 @@ public class ConnectionConfiguration implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void init(String serviceName, ProxyInfo proxy) {
|
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.serviceName = serviceName;
|
||||||
this.proxy = proxy;
|
this.proxy = proxy;
|
||||||
|
|
||||||
|
@ -645,6 +649,9 @@ public class ConnectionConfiguration implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initHostAddresses(String host, int port) {
|
private void initHostAddresses(String host, int port) {
|
||||||
|
if (StringUtils.isEmpty(host)) {
|
||||||
|
throw new IllegalArgumentException("host must not be the empty String");
|
||||||
|
}
|
||||||
hostAddresses = new ArrayList<HostAddress>(1);
|
hostAddresses = new ArrayList<HostAddress>(1);
|
||||||
HostAddress hostAddress;
|
HostAddress hostAddress;
|
||||||
hostAddress = new HostAddress(host, port);
|
hostAddress = new HostAddress(host, port);
|
||||||
|
|
|
@ -48,6 +48,9 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream {
|
||||||
private final static boolean supported;
|
private final static boolean supported;
|
||||||
private final static int compressionLevel = Deflater.DEFAULT_COMPRESSION;
|
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 {
|
static {
|
||||||
Method m = null;
|
Method m = null;
|
||||||
try {
|
try {
|
||||||
|
@ -100,25 +103,23 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream getOutputStream(OutputStream outputStream) {
|
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)) {
|
return new DeflaterOutputStream(outputStream, new Deflater(compressionLevel)) {
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
if (!supported) {
|
if (!supported) {
|
||||||
super.flush();
|
super.flush();
|
||||||
return;
|
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 {
|
try {
|
||||||
do {
|
int count;
|
||||||
count = (Integer) method.invoke(def, buf, 0, buf.length, 2);
|
while ((count = (Integer) method.invoke(def, buf, 0, buf.length, flushMethodInt)) != 0) {
|
||||||
out.write(buf, 0, count);
|
out.write(buf, 0, count);
|
||||||
} while (count > 0);
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new IOException("Can't flush");
|
throw new IOException("Can't flush");
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
|
|
|
@ -20,6 +20,21 @@ import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public abstract class XMPPInputOutputStream {
|
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 <a href="https://blog.thijsalkema.de/blog/2014/08/07/https-attacks-and-xmpp-2-crime-and-breach/">Attacks against XMPP when using compression</a>
|
||||||
|
* @param flushMethod
|
||||||
|
*/
|
||||||
|
public static void setFlushMethod(FlushMethod flushMethod) {
|
||||||
|
XMPPInputOutputStream.flushMethod = flushMethod;
|
||||||
|
}
|
||||||
|
|
||||||
protected String compressionMethod;
|
protected String compressionMethod;
|
||||||
|
|
||||||
public String getCompressionMethod() {
|
public String getCompressionMethod() {
|
||||||
|
@ -31,4 +46,9 @@ public abstract class XMPPInputOutputStream {
|
||||||
public abstract InputStream getInputStream(InputStream inputStream) throws Exception;
|
public abstract InputStream getInputStream(InputStream inputStream) throws Exception;
|
||||||
|
|
||||||
public abstract OutputStream getOutputStream(OutputStream outputStream) throws Exception;
|
public abstract OutputStream getOutputStream(OutputStream outputStream) throws Exception;
|
||||||
|
|
||||||
|
public enum FlushMethod {
|
||||||
|
FULL_FLUSH,
|
||||||
|
SYNC_FLUSH,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,13 +279,23 @@ 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
|
* @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) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String collectionToString(Collection<String> collection) {
|
public static String collectionToString(Collection<String> collection) {
|
||||||
|
|
|
@ -73,7 +73,12 @@ public class Socks5Proxy {
|
||||||
private static Socks5Proxy socks5Server;
|
private static Socks5Proxy socks5Server;
|
||||||
|
|
||||||
private static boolean localSocks5ProxyEnabled = true;
|
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 */
|
/* reusable implementation of a SOCKS5 proxy server process */
|
||||||
private Socks5ServerProcess serverProcess;
|
private Socks5ServerProcess serverProcess;
|
||||||
|
@ -142,6 +147,9 @@ public class Socks5Proxy {
|
||||||
* @param localSocks5ProxyPort the port of the local Socks5 proxy to set
|
* @param localSocks5ProxyPort the port of the local Socks5 proxy to set
|
||||||
*/
|
*/
|
||||||
public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) {
|
public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) {
|
||||||
|
if (Math.abs(localSocks5ProxyPort) > 65535) {
|
||||||
|
throw new IllegalArgumentException("localSocks5ProxyPort must be within (-65535,65535)");
|
||||||
|
}
|
||||||
Socks5Proxy.localSocks5ProxyPort = localSocks5ProxyPort;
|
Socks5Proxy.localSocks5ProxyPort = localSocks5ProxyPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,20 +154,24 @@ public class OfflineMessageManager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
PacketCollector messageCollector = connection.createPacketCollector(messageFilter);
|
PacketCollector messageCollector = connection.createPacketCollector(messageFilter);
|
||||||
connection.createPacketCollectorAndSend(request).nextResultOrThrow();
|
try {
|
||||||
// Collect the received offline messages
|
connection.createPacketCollectorAndSend(request).nextResultOrThrow();
|
||||||
Message message = (Message) messageCollector.nextResult();
|
// Collect the received offline messages
|
||||||
while (message != null) {
|
Message message = (Message) messageCollector.nextResult();
|
||||||
messages.add(message);
|
while (message != null) {
|
||||||
message = (Message) messageCollector.nextResult();
|
messages.add(message);
|
||||||
|
message = (Message) messageCollector.nextResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
// Stop queuing offline messages
|
||||||
|
messageCollector.cancel();
|
||||||
}
|
}
|
||||||
// Stop queuing offline messages
|
|
||||||
messageCollector.cancel();
|
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an Iterator with all the offline <tt>Messages</tt> of the user. The returned offline
|
* Returns a List of Messages with all the offline <tt>Messages</tt> of the user. The returned offline
|
||||||
* messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)}
|
* messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)}
|
||||||
* to delete the messages.
|
* to delete the messages.
|
||||||
*
|
*
|
||||||
|
@ -181,17 +185,23 @@ public class OfflineMessageManager {
|
||||||
List<Message> messages = new ArrayList<Message>();
|
List<Message> messages = new ArrayList<Message>();
|
||||||
OfflineMessageRequest request = new OfflineMessageRequest();
|
OfflineMessageRequest request = new OfflineMessageRequest();
|
||||||
request.setFetch(true);
|
request.setFetch(true);
|
||||||
connection.createPacketCollectorAndSend(request).nextResultOrThrow();
|
|
||||||
|
|
||||||
PacketCollector messageCollector = connection.createPacketCollector(PACKET_FILTER);
|
PacketCollector messageCollector = connection.createPacketCollector(PACKET_FILTER);
|
||||||
// Collect the received offline messages
|
PacketCollector resultCollector = connection.createPacketCollectorAndSend(request);
|
||||||
Message message = (Message) messageCollector.nextResult();
|
|
||||||
while (message != null) {
|
try {
|
||||||
messages.add(message);
|
// Collect the received offline messages
|
||||||
message = (Message) messageCollector.nextResult();
|
Message message = (Message) messageCollector.nextResult();
|
||||||
|
while (message != null) {
|
||||||
|
messages.add(message);
|
||||||
|
message = (Message) messageCollector.nextResult();
|
||||||
|
}
|
||||||
|
resultCollector.nextResultOrThrow();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
messageCollector.cancel();
|
||||||
|
resultCollector.cancel();
|
||||||
}
|
}
|
||||||
// Stop queuing offline messages
|
|
||||||
messageCollector.cancel();
|
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -577,12 +577,23 @@ public class ConfigureForm extends Form
|
||||||
* Determines if subscriptions are allowed.
|
* Determines if subscriptions are allowed.
|
||||||
*
|
*
|
||||||
* @return true if subscriptions are allowed, false otherwise
|
* @return true if subscriptions are allowed, false otherwise
|
||||||
|
* @deprecated use {@link #isSubscribe()} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean isSubscibe()
|
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.
|
* Sets whether subscriptions are allowed.
|
||||||
*
|
*
|
||||||
|
|
|
@ -313,7 +313,7 @@ public class FormField {
|
||||||
*/
|
*/
|
||||||
public static class Option {
|
public static class Option {
|
||||||
|
|
||||||
public static final String ELEMNT = "option";
|
public static final String ELEMENT = "option";
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
private String label;
|
private String label;
|
||||||
|
@ -352,7 +352,7 @@ public class FormField {
|
||||||
|
|
||||||
public XmlStringBuilder toXML() {
|
public XmlStringBuilder toXML() {
|
||||||
XmlStringBuilder xml = new XmlStringBuilder();
|
XmlStringBuilder xml = new XmlStringBuilder();
|
||||||
xml.halfOpenElement(ELEMNT);
|
xml.halfOpenElement(ELEMENT);
|
||||||
// Add attribute
|
// Add attribute
|
||||||
xml.optAttribute("label", getLabel());
|
xml.optAttribute("label", getLabel());
|
||||||
xml.rightAngelBracket();
|
xml.rightAngelBracket();
|
||||||
|
|
Loading…
Reference in a new issue