mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-02-16 22:06:25 +01:00
Compare commits
37 commits
5782fff2a4
...
d8642847ea
Author | SHA1 | Date | |
---|---|---|---|
|
d8642847ea | ||
|
d8864b62ca | ||
|
a4bb5bfda8 | ||
|
1a963cc794 | ||
|
02c9058c3d | ||
|
ca497a2199 | ||
|
821bdf6d86 | ||
|
c1f3f8ce13 | ||
|
a2636b2f60 | ||
|
f10cbb4a97 | ||
|
c4228e072b | ||
|
3f3a7cb540 | ||
|
59cf449799 | ||
|
0ff8040895 | ||
|
5522d6681e | ||
|
68f400616d | ||
|
71f5cfe3da | ||
|
e117f431bc | ||
|
e6236b0c21 | ||
|
afd18f95c9 | ||
|
1f5ada4822 | ||
|
df96c57093 | ||
|
72acd8e095 | ||
|
7e311ab9df | ||
|
f12fe2264a | ||
|
5dfed2935f | ||
|
e1624e1ab9 | ||
|
74adcda23d | ||
|
cfccc78ba0 | ||
|
5f66685949 | ||
|
a809f181f5 | ||
|
b7a235f43c | ||
|
55d7b9d4eb | ||
1a9ac238e8 | |||
|
28dd56a13a | ||
|
c1b412c457 | ||
|
254c315852 |
53 changed files with 848 additions and 211 deletions
27
.mailmap
Normal file
27
.mailmap
Normal file
|
@ -0,0 +1,27 @@
|
|||
Paul Schaub <vanitasvitae@fsfe.org>
|
||||
Aditya Borikar <adityaborikar2@gmail.com>
|
||||
Anno van Vliet <annovanvliet@gmail.com>
|
||||
Daryl E. Herzmann <akrherz@iastate.edu>
|
||||
Damian Minkov <damencho@jitsi.org>
|
||||
Craig Hesling <craig@hesling.com>
|
||||
Dave Stanley <dave.stanley@gossinteractive.com>
|
||||
Marcel Heckel <marcel.heckel@ivi.fraunhofer.de>
|
||||
Candy Lohse <candy.lohse@ivi.fraunhofer.de>
|
||||
Luca Stucchi <stucchi@skebby.it>
|
||||
Luke Granger-Brown <git@lukegb.com>
|
||||
Florian Kimmann <florian.kimmann@tu-dortmund.de>
|
||||
Adam Stawicki <adamstawicki91@gmail.homas>
|
||||
Andrey Sokolov <andrey.sokolov@billing.ru>
|
||||
Andri Khrisharyadi <andri.khrisharyadi@gmail.com>
|
||||
Andriy Tsykholyas <andriy.tsykholyas@gmail.com>
|
||||
Fernando Ramirez <f.e.ramirez94@gmail.com>
|
||||
Marcel Heckel <marcel.heckel@ivi.fraunhofer.de>
|
||||
Robin Collier <rcollier@b35dd754-fafc-0310-a699-88a17e54d16e>
|
||||
Thibaut Le Guilly <leguilly.thibaut@gmail.com>
|
||||
Thomas Pocreau <thomas.pocreau@iadvize.com>
|
||||
Vadim Fite <vadim.fite@quickblox.com>
|
||||
Vaibhav Ranglani <vaibhav.ranglani@talentica.com>
|
||||
Xiaowei YAN <xwyan@minigui.org>
|
||||
|
||||
Guus der Kinderen <guus.der.kinderen@gmail.com> guus <guus@b35dd754-fafc-0310-a699-88a17e54d16e>
|
||||
Jesus Fuentes <fuentes.jesus1010010@gmail.com> Jesus <fuentes31j@gmail.com>
|
101
NOTICE
Normal file
101
NOTICE
Normal file
|
@ -0,0 +1,101 @@
|
|||
Smack
|
||||
|
||||
An open-source XMPP library
|
||||
maintained by Florian Schmaus
|
||||
|
||||
https://igniterealtime.org/projects/smack
|
||||
|
||||
|
||||
Authors:
|
||||
|
||||
Abmar Barros
|
||||
Aditya Borikar
|
||||
Alexander Tovstonozhenko
|
||||
Alex Wenckus
|
||||
Andrew Wright
|
||||
Andrey Prokopenko
|
||||
Andrey Sokolov
|
||||
Andrey Starodubtsev
|
||||
Andri Khrisharyadi
|
||||
Andriy Tsykholyas
|
||||
Anno van Vliet
|
||||
Bastien Rouiller
|
||||
Benjamin JALON
|
||||
Bill Lynch
|
||||
Boris Grozev
|
||||
Candy Lohse
|
||||
Cem Yabansu
|
||||
Chris Deering
|
||||
Christoph Fiehe
|
||||
Craig Hesling
|
||||
Damian Minkov
|
||||
Daniele Ricci
|
||||
Daniel Henninger
|
||||
Daniel Hintze
|
||||
Daryl E. Herzmann
|
||||
Dave Cridland
|
||||
Dave Stanley
|
||||
David Black
|
||||
Derek DeMoro
|
||||
Dmitry Deshevoy
|
||||
Eng ChongMeng
|
||||
Fernando Martinez Herrera
|
||||
Fernando Ramirez
|
||||
Florian Kimmann
|
||||
Florian Schmaus
|
||||
Francisco Vives
|
||||
Gaston Dombiak
|
||||
Georg Lukas
|
||||
Gilles Cornu
|
||||
Gligor Selimovic
|
||||
Greg Thomas
|
||||
Grigory Fedorov
|
||||
Günther Niess
|
||||
Guus der Kinderen
|
||||
Henning Staib
|
||||
Holger Bergunde
|
||||
Hugues Bruant
|
||||
Ingo Bauersachs
|
||||
Ishan Khanna
|
||||
Jae Jang
|
||||
Jared DiCioccio
|
||||
Jason Sipula
|
||||
Jay Kline
|
||||
Jeff Williams
|
||||
Jesus Fuentes
|
||||
John Haubrich
|
||||
Júlio Cesar Bueno Cotta
|
||||
Lars Noschinski
|
||||
Luca Stucchi
|
||||
Luke Granger-Brown
|
||||
Marcel Heckel
|
||||
Marilyn Daum
|
||||
Matteo Campana
|
||||
Matthew Wild
|
||||
Matt Tucker
|
||||
Michael Will
|
||||
Miguel Hincapie
|
||||
Mohsen Hariri
|
||||
Oliver Mihatsch
|
||||
Paul Schaub
|
||||
Pete Matern
|
||||
Piotr Nosek
|
||||
Rajat Kumar Gupta
|
||||
Robin Collier
|
||||
Simon Schuster
|
||||
Son Goku
|
||||
Tairs Rzajevs
|
||||
Thiago Camargo
|
||||
Thibaut Le Guilly
|
||||
Thomas Pocreau
|
||||
Tim Jentz
|
||||
Timothy Pitt
|
||||
Tomáš Havlas
|
||||
Tomas Nosek
|
||||
Vadim Fite
|
||||
Vaibhav Ranglani
|
||||
V Lau
|
||||
Vyacheslav Blinov
|
||||
Wolf Posdorfer
|
||||
Xiaowei YAN
|
||||
Yash Thakkar
|
13
README.md
13
README.md
|
@ -20,6 +20,15 @@ Start with having a look at the **[Documentation]** and the **[Javadoc]**.
|
|||
|
||||
Instructions on how to use Smack in your Java or Android project are provided in the [Smack Readme and Upgrade Guide](https://igniterealtime.org/projects/smack/readme).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Most of Smack is governed by the Apache License 2.0 (SPDX License Identifier: Apache 2.0). This license requires that the contents of a NOICE text file are shown "…within a display generated by the Derivative Works, if and wherever such third-party notices normally appear.".
|
||||
|
||||
Smack comes which such a NOTICE file. Moreover, since `smack-core` is licensed under the Apache License 2.0, the conditions apply to every project using Smack. The content of Smack's NOTICE file can conveniently be retrieved using `Smack.getNoticeStream()`.
|
||||
|
||||
Some subprojects of Smack are governed by other licenses. Please refer to the individual subprojects.
|
||||
|
||||
Professional Services
|
||||
---------------------
|
||||
|
||||
|
@ -52,7 +61,7 @@ If you find Smack useful and feel like donating, then you can use one of the fol
|
|||
Contact
|
||||
-------
|
||||
|
||||
The developers hang around in `#smack` (freenode, IRC) and `open_chat@conference.igniterealtime.org` (XMPP MUC room).
|
||||
The developers hang around in [smack@conference.igniterealtime.org](xmpp:smack@conference.igniterealtime.org?join). You may use [this link](https://inverse.chat/badge.svg?room=smack@conference.igniterealtime.org) to join the room via [inverse.chat](https://inverse.chat).
|
||||
Remember that it may take some time (~hours) to get a response.
|
||||
|
||||
You can also reach us via the [Smack Support Forum] if you have questions or need support, or the [Smack Developers Forum] if you want to discuss Smack development.
|
||||
|
@ -75,7 +84,7 @@ Resources
|
|||
- Dev Forum: https://discourse.igniterealtime.org/c/smack/smack-dev
|
||||
- Maven Releases: https://oss.sonatype.org/content/repositories/releases/org/igniterealtime/smack/
|
||||
- Maven Snapshots: https://oss.sonatype.org/content/repositories/snapshots/org/igniterealtime/smack/
|
||||
- Nightly Unique Maven Snapshots: https://igniterealtime.org/repo/
|
||||
- Nightly Unique Maven Snapshots: https://www.igniterealtime.org/archiva/repository/maven/
|
||||
|
||||
Ignite Realtime
|
||||
===============
|
||||
|
|
7
resources/get-contributors.sh
Executable file
7
resources/get-contributors.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
git shortlog -s |\
|
||||
cut -f2- |\
|
||||
grep -v '(no author)' |\
|
||||
grep '\w \w.*' |\
|
||||
sort
|
|
@ -141,6 +141,112 @@ hr {
|
|||
|
||||
<div id="pageBody">
|
||||
|
||||
|
||||
|
||||
<h2>4.4.0 -- <span style="font-weight: normal;">2020-12-06</span></h2>
|
||||
|
||||
<h2> Bug
|
||||
</h2>
|
||||
<ul>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-561'>SMACK-561</a>] - Smack should not reply with multiple stream types after stream initiation is offered
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-624'>SMACK-624</a>] - AdHocCommandManager's session sweeping thread does never stop
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-729'>SMACK-729</a>] - Not all providers from smack-legacy.jar are loaded
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-770'>SMACK-770</a>] - There is no Bits of Binary Extension Element provider registered
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-848'>SMACK-848</a>] - Make MultiUserChat.leave() wait for response
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-874'>SMACK-874</a>] - PacketParserUtilsTest#invalidXMLInMessageBody() fails on non-english machines
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-881'>SMACK-881</a>] - Deadlock between reader and writer if Stream Mangement unacked stanza queue is full
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-888'>SMACK-888</a>] - MUC roomDestroyed() callback is not invoked
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2> New Feature
|
||||
</h2>
|
||||
<ul>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-257'>SMACK-257</a>] - Add support for XEP-0118: User Tune
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-636'>SMACK-636</a>] - Add support for XEP-0319: Last User Interaction in Presence
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-743'>SMACK-743</a>] - Add support for XEP-0384: OMEMO Encryption
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-801'>SMACK-801</a>] - Update Smack to Java 8
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-824'>SMACK-824</a>] - Add support for XEP-0221: Data Forms Media Element
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-862'>SMACK-862</a>] - Add support for XEP-0418: DNS Queries over XMPP (DoX)
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-871'>SMACK-871</a>] - Add support for XEP-0350: Data Forms Geolocation Element
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-872'>SMACK-872</a>] - Add support for XEP-0315: Data Forms XML Element
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-878'>SMACK-878</a>] - Add support for XEP-0328: JID Prep
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-884'>SMACK-884</a>] - Add support for XEP-0422: Message Fastening
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-885'>SMACK-885</a>] - Add support for XEP-0420 Stanza Content Encryption
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-889'>SMACK-889</a>] - Add support for XEP-0428: Fallback Indication
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2> Improvement
|
||||
</h2>
|
||||
<ul>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-591'>SMACK-591</a>] - Replace XPP3 by SmackXmlPullParser (wrapping Stax's XmlStreamReader and XPP3 on Android)
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-650'>SMACK-650</a>] - Enable Java8's javadoc doclint
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-651'>SMACK-651</a>] - Perform sound cross-compilation: Use newer javac's --release feature
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-718'>SMACK-718</a>] - Prevent extremely long reply timeouts from being set
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-821'>SMACK-821</a>] - Make Forwarded a generic type
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-822'>SMACK-822</a>] - Add API for XEP-0313 § 6.2 Advanced configuration via Ad-Hoc commands
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-825'>SMACK-825</a>] - Discourage Stanza.getExtension(String, String) in favor of Stanza.getExtension(Class<E extends ExtensionElement>)
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-826'>SMACK-826</a>] - Add support for XEP-0373:" OpenPGP for XMPP" and XEP-0374: "OpenPGP for XMPP Instant Messaging"
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-828'>SMACK-828</a>] - Add support for XEP-0107: User Mood
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-836'>SMACK-836</a>] - Save a ServiceDiscoveryManager instance in a private field of MultiUserChatManger
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-839'>SMACK-839</a>] - Provider.parse() should not throw a generic Exception, but instead IOException and XmlPullParserException
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-852'>SMACK-852</a>] - Message thread and subject should be designed and implemented as ExtensionElements
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-854'>SMACK-854</a>] - Rename smack-java7 to smack-java8
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-866'>SMACK-866</a>] - Remove all tabs from the source code and add checkstyle rule that enforces no-tabs
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-867'>SMACK-867</a>] - Extend HttpFileUploadManager by methods with InputStream parameter
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-882'>SMACK-882</a>] - Add support for MUC status code 333
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-883'>SMACK-883</a>] - Add generic MUC callback for "participant left" caused by unavailable presences
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-890'>SMACK-890</a>] - Update Message Archive Management (XEP-0313) support to urn:xmpp:mam:2
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-892'>SMACK-892</a>] - Smack performs unnecessary escaping in XML text
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2> Task
|
||||
</h2>
|
||||
<ul>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-750'>SMACK-750</a>] - Raise Smack's minimum required Android SDK level to 19 (Android 4.4, Kit Kat, 2013-10)
|
||||
</li>
|
||||
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-840'>SMACK-840</a>] - Remove smack-compression-jzlib, as it is obsolete (Smack uses Java 7 de- and inflate API now)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>4.3.4 -- <span style="font-weight: normal;">2019-05-27</span></h2>
|
||||
|
||||
<h2> Bug
|
||||
|
|
|
@ -33,6 +33,7 @@ dependencies {
|
|||
testFixturesApi "org.assertj:assertj-core:3.11.1"
|
||||
testFixturesApi "org.xmlunit:xmlunit-assertj:$xmlUnitVersion"
|
||||
testFixturesApi 'org.hamcrest:hamcrest-library:2.2'
|
||||
testFixturesApi 'com.google.guava:guava:28.2-jre'
|
||||
}
|
||||
|
||||
class CreateFileTask extends DefaultTask {
|
||||
|
|
|
@ -172,8 +172,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
|||
private static final AtomicInteger connectionCounter = new AtomicInteger(0);
|
||||
|
||||
static {
|
||||
// Ensure the SmackConfiguration class is loaded by calling a method in it.
|
||||
SmackConfiguration.getVersion();
|
||||
Smack.ensureInitialized();
|
||||
}
|
||||
|
||||
protected enum SyncPointState {
|
||||
|
|
|
@ -112,9 +112,7 @@ import org.minidns.util.InetAddressUtil;
|
|||
public abstract class ConnectionConfiguration {
|
||||
|
||||
static {
|
||||
// Ensure that Smack is initialized when ConnectionConfiguration is used, or otherwise e.g.
|
||||
// SmackConfiguration.DEBUG may not be initialized yet.
|
||||
SmackConfiguration.getVersion();
|
||||
Smack.ensureInitialized();
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ConnectionConfiguration.class.getName());
|
||||
|
|
53
smack-core/src/main/java/org/jivesoftware/smack/Smack.java
Normal file
53
smack-core/src/main/java/org/jivesoftware/smack/Smack.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus
|
||||
*
|
||||
* 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.smack;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Smack {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Smack.class.getName());
|
||||
|
||||
private static final String SMACK_ORG = "org.jivesoftware";
|
||||
|
||||
public static final String SMACK_PACKAGE = SMACK_ORG + ".smack";
|
||||
|
||||
/**
|
||||
* Returns the Smack version information, eg "1.3.0".
|
||||
*
|
||||
* @return the Smack version information.
|
||||
*/
|
||||
public static String getVersion() {
|
||||
return SmackInitialization.SMACK_VERSION;
|
||||
}
|
||||
|
||||
private static final String NOTICE_RESOURCE = SMACK_PACKAGE + "/NOTICE";
|
||||
|
||||
public static InputStream getNoticeStream() {
|
||||
return ClassLoader.getSystemResourceAsStream(NOTICE_RESOURCE);
|
||||
}
|
||||
|
||||
public static void ensureInitialized() {
|
||||
if (SmackConfiguration.isSmackInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String version = getVersion();
|
||||
LOGGER.finest("Smack " + version + " has been initialized");
|
||||
}
|
||||
}
|
|
@ -105,7 +105,10 @@ public final class SmackConfiguration {
|
|||
* Returns the Smack version information, eg "1.3.0".
|
||||
*
|
||||
* @return the Smack version information.
|
||||
* @deprecated use {@link Smack#getVersion()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
// TODO: Remove in Smack 4.6
|
||||
public static String getVersion() {
|
||||
return SmackInitialization.SMACK_VERSION;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,7 +16,9 @@
|
|||
*/
|
||||
package org.jivesoftware.smack.datatypes;
|
||||
|
||||
public abstract class Scalar extends java.lang.Number {
|
||||
import org.jivesoftware.smack.util.DefaultCharSequence;
|
||||
|
||||
public abstract class Scalar extends java.lang.Number implements DefaultCharSequence {
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -83,4 +85,11 @@ public abstract class Scalar extends java.lang.Number {
|
|||
public final String toString() {
|
||||
return number.toString();
|
||||
}
|
||||
|
||||
public abstract Scalar getMinValue();
|
||||
|
||||
public abstract Scalar getMaxValue();
|
||||
|
||||
public abstract Scalar incrementedByOne();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -21,12 +21,18 @@ import org.jivesoftware.smack.util.NumberUtil;
|
|||
/**
|
||||
* A number representing an unsigned 16-bit integer. Can be used for values with the XML schema type "xs:unsingedShort".
|
||||
*/
|
||||
public final class UInt16 extends Scalar {
|
||||
public final class UInt16 extends Scalar implements Comparable<UInt16> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int number;
|
||||
|
||||
public static final int MIN_VALUE_INT = 0;
|
||||
public static final int MAX_VALUE_INT = (1 << 16) - 1;
|
||||
|
||||
public static final UInt16 MIN_VALUE = UInt16.from(MIN_VALUE_INT);
|
||||
public static final UInt16 MAX_VALUE = UInt16.from(MAX_VALUE_INT);
|
||||
|
||||
private UInt16(int number) {
|
||||
super(NumberUtil.requireUShort16(number));
|
||||
this.number = number;
|
||||
|
@ -54,4 +60,25 @@ public final class UInt16 extends Scalar {
|
|||
|
||||
return super.equals(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(UInt16 o) {
|
||||
return Integer.compare(number, o.number);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt16 getMinValue() {
|
||||
return MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt16 getMaxValue() {
|
||||
return MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt16 incrementedByOne() {
|
||||
int incrementedValue = number < MAX_VALUE_INT ? number + 1 : 0;
|
||||
return UInt16.from(incrementedValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -27,6 +27,12 @@ public final class UInt32 extends Scalar {
|
|||
|
||||
private final long number;
|
||||
|
||||
public static final long MIN_VALUE_LONG = 0;
|
||||
public static final long MAX_VALUE_LONG = (1L << 32) - 1;
|
||||
|
||||
public static final UInt32 MIN_VALUE = UInt32.from(MAX_VALUE_LONG);
|
||||
public static final UInt32 MAX_VALUE = UInt32.from(MAX_VALUE_LONG);
|
||||
|
||||
private UInt32(long number) {
|
||||
super(NumberUtil.requireUInt32(number));
|
||||
this.number = number;
|
||||
|
@ -55,4 +61,20 @@ public final class UInt32 extends Scalar {
|
|||
|
||||
return super.equals(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt32 getMinValue() {
|
||||
return MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt32 getMaxValue() {
|
||||
return MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt32 incrementedByOne() {
|
||||
long incrementedValue = number < MAX_VALUE_LONG ? number + 1 : 0;
|
||||
return UInt32.from(incrementedValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ public abstract class IqBuilder<IB extends IqBuilder<IB, I>, I extends IQ>
|
|||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract I build();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -41,4 +41,9 @@ public final class IqData extends AbstractIqBuilder<IqData> {
|
|||
public IqData getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stanza build() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ public abstract class MessageOrPresenceBuilder<MP extends MessageOrPresence<? ex
|
|||
super(stanzaId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract MP build();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -184,6 +184,8 @@ public abstract class StanzaBuilder<B extends StanzaBuilder<B>> implements Stanz
|
|||
return getThis();
|
||||
}
|
||||
|
||||
public abstract Stanza build();
|
||||
|
||||
public abstract B getThis();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -55,4 +55,28 @@ public class SmackParsingException extends Exception {
|
|||
super(uriSyntaxException);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RequiredValueMissingException extends SmackParsingException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RequiredValueMissingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class RequiredAttributeMissingException extends RequiredValueMissingException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RequiredAttributeMissingException(String attributeName) {
|
||||
super("The required attribute '" + attributeName + "' is missing (or has the empty String as value)");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Nonza;
|
||||
|
@ -122,7 +122,7 @@ public final class ProviderManager {
|
|||
// registered providers do not get overwritten by a following Smack
|
||||
// initialization. This guarantees that Smack is initialized before a
|
||||
// new provider is registered
|
||||
SmackConfiguration.getVersion();
|
||||
Smack.ensureInitialized();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus
|
||||
*
|
||||
* 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.smack.util;
|
||||
|
||||
public interface DefaultCharSequence extends CharSequence {
|
||||
|
||||
@Override
|
||||
default int length() {
|
||||
return toString().length();
|
||||
}
|
||||
|
||||
@Override
|
||||
default char charAt(int index) {
|
||||
return toString().charAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
default CharSequence subSequence(int start, int end) {
|
||||
return toString().subSequence(start, end);
|
||||
}
|
||||
|
||||
}
|
|
@ -299,7 +299,7 @@ public class PacketParserUtils {
|
|||
*/
|
||||
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
|
||||
if (parser.supportsRoundtrip()) {
|
||||
return parseContentDepthWithRoundtrip(parser, depth, fullNamespaces);
|
||||
return parseContentDepthWithRoundtrip(parser, depth);
|
||||
} else {
|
||||
return parseContentDepthWithoutRoundtrip(parser, depth, fullNamespaces);
|
||||
}
|
||||
|
@ -368,8 +368,7 @@ public class PacketParserUtils {
|
|||
return xml;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedVariable")
|
||||
private static CharSequence parseContentDepthWithRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces)
|
||||
private static XmlStringBuilder parseContentDepthWithRoundtrip(XmlPullParser parser, int depth)
|
||||
throws XmlPullParserException, IOException {
|
||||
XmlStringBuilder sb = new XmlStringBuilder();
|
||||
XmlPullParser.Event event = parser.getEventType();
|
||||
|
@ -377,10 +376,9 @@ public class PacketParserUtils {
|
|||
outerloop: while (true) {
|
||||
switch (event) {
|
||||
case START_ELEMENT:
|
||||
if (startElementJustSeen) {
|
||||
sb.rightAngleBracket();
|
||||
}
|
||||
startElementJustSeen = true;
|
||||
String openElementTag = parser.getText();
|
||||
sb.append(openElementTag);
|
||||
break;
|
||||
case END_ELEMENT:
|
||||
boolean isEmptyElement = false;
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.jivesoftware.smack.datatypes.UInt16;
|
|||
import org.jivesoftware.smack.datatypes.UInt32;
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException.RequiredAttributeMissingException;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException.SmackTextParseException;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException.SmackUriSyntaxParsingException;
|
||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||
|
@ -231,6 +232,14 @@ public class ParserUtils {
|
|||
return UInt16.from(integer);
|
||||
}
|
||||
|
||||
public static UInt16 getRequiredUInt16Attribute(XmlPullParser parser, String name) throws RequiredAttributeMissingException {
|
||||
UInt16 uint16 = getUInt16Attribute(parser, name);
|
||||
if (uint16 == null) {
|
||||
throw new SmackParsingException.RequiredAttributeMissingException(name);
|
||||
}
|
||||
return uint16;
|
||||
}
|
||||
|
||||
public static int getIntegerFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
String intString = parser.nextText();
|
||||
return Integer.valueOf(intString);
|
||||
|
|
|
@ -361,6 +361,20 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #optAttribute(String, CharSequence)}, but with a different method name. This method can be used if
|
||||
* the provided attribute value argument type causes ambiguity in method overloading. For example if the type is a
|
||||
* subclass of Number and CharSequence.
|
||||
*
|
||||
* @param name the name of the attribute.
|
||||
* @param value the value of the attribute.
|
||||
* @return a reference to this object.
|
||||
* @since 4.5
|
||||
*/
|
||||
public XmlStringBuilder optAttributeCs(String name, CharSequence value) {
|
||||
return optAttribute(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given attribute if {@code value => 0}.
|
||||
*
|
||||
|
|
1
smack-core/src/main/resources/org.jivesoftware.smack/NOTICE
Symbolic link
1
smack-core/src/main/resources/org.jivesoftware.smack/NOTICE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../../NOTICE
|
|
@ -49,8 +49,8 @@ public class SmackConfigurationTest {
|
|||
// *every* test, those tests are currently disabled. Hopefully this will change in the future.
|
||||
@Ignore
|
||||
@Test
|
||||
public void smackconfigurationVersionShouldInitialzieSmacktTest() {
|
||||
SmackConfiguration.getVersion();
|
||||
public void smackEnsureInitializedShouldInitialzieSmacktTest() {
|
||||
Smack.ensureInitialized();
|
||||
|
||||
// Only a call to SmackConfiguration.getVersion() should cause Smack to become initialized.
|
||||
assertTrue(SmackConfiguration.isSmackInitialized());
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus
|
||||
*
|
||||
* 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.smack;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SmackTest {
|
||||
|
||||
@Test
|
||||
public void getNoticeStreamTest() throws IOException {
|
||||
Set<String> expectedStrings = Sets.newHashSet(
|
||||
"Florian Schmaus"
|
||||
, "Paul Schaub"
|
||||
);
|
||||
int maxLineLength = 0;
|
||||
|
||||
try (InputStream inputStream = Smack.getNoticeStream()) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
|
||||
while (reader.ready()) {
|
||||
String line = reader.readLine();
|
||||
|
||||
int lineLength = line.length();
|
||||
maxLineLength = Math.max(maxLineLength, lineLength);
|
||||
|
||||
expectedStrings.removeIf(s -> s.equals(line));
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(expectedStrings.isEmpty());
|
||||
assertTrue(maxLineLength < 60);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* 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.smack.datatypes;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class UInt16Test {
|
||||
|
||||
@Test
|
||||
public void testMaxValue() {
|
||||
assertEquals(65535, UInt16.MAX_VALUE_INT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2020 Florian Schmaus.
|
||||
*
|
||||
* 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.smack.datatypes;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class UInt32Test {
|
||||
|
||||
@Test
|
||||
public void testMaxValue() {
|
||||
assertEquals(4294967295L, UInt32.MAX_VALUE_LONG);
|
||||
}
|
||||
|
||||
}
|
|
@ -854,4 +854,40 @@ public class PacketParserUtilsTest {
|
|||
StanzaError error = PacketParserUtils.parseError(parser);
|
||||
assertEquals(text, error.getDescriptiveText());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||
public void testParseElementSimple(SmackTestUtil.XmlPullParserKind parserKind) throws TransformerException, ParserConfigurationException, FactoryConfigurationError, XmlPullParserException, IOException {
|
||||
String unknownElement = XMLBuilder.create("unknown-element")
|
||||
.ns("https://example.org/non-existent")
|
||||
.e("inner")
|
||||
.t("test")
|
||||
.asString(outputProperties);
|
||||
|
||||
XmlPullParser xmlPullParser = SmackTestUtil.getParserFor(unknownElement, parserKind);
|
||||
|
||||
CharSequence unknownElementParsed = PacketParserUtils.parseElement(xmlPullParser);
|
||||
assertXmlSimilar(unknownElement, unknownElementParsed);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||
public void testParseElementExtended(SmackTestUtil.XmlPullParserKind parserKind) throws TransformerException, ParserConfigurationException, FactoryConfigurationError, XmlPullParserException, IOException {
|
||||
String unknownElement = XMLBuilder.create("unknown-element")
|
||||
.ns("https://example.org/non-existent")
|
||||
.a("attribute-outer", "foo")
|
||||
.e("inner")
|
||||
.a("attribute-inner", "bar")
|
||||
.a("attribute-inner-2", "baz")
|
||||
.t("test")
|
||||
.up()
|
||||
.e("empty-element")
|
||||
.up()
|
||||
.asString(outputProperties);
|
||||
|
||||
XmlPullParser xmlPullParser = SmackTestUtil.getParserFor(unknownElement, parserKind);
|
||||
|
||||
CharSequence unknownElementParsed = PacketParserUtils.parseElement(xmlPullParser);
|
||||
assertXmlSimilar(unknownElement, unknownElementParsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ package org.jivesoftware.smack.test.util;
|
|||
import java.security.Security;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
@ -31,7 +31,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|||
public class SmackTestSuite {
|
||||
|
||||
static {
|
||||
SmackConfiguration.getVersion();
|
||||
Smack.ensureInitialized();
|
||||
org.jivesoftware.smack.util.stringencoder.Base64.setEncoder(new Encoder() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,7 +43,7 @@ import javax.swing.JPopupMenu;
|
|||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
|
||||
/**
|
||||
|
@ -232,7 +232,7 @@ public final class EnhancedDebuggerWindow {
|
|||
versionPanel.setLayout(new BoxLayout(versionPanel, BoxLayout.X_AXIS));
|
||||
versionPanel.setMaximumSize(new Dimension(2000, 31));
|
||||
versionPanel.add(new JLabel(" Smack version: "));
|
||||
JFormattedTextField field = new JFormattedTextField(SmackConfiguration.getVersion());
|
||||
JFormattedTextField field = new JFormattedTextField(Smack.getVersion());
|
||||
field.setEditable(false);
|
||||
field.setBorder(null);
|
||||
versionPanel.add(field);
|
||||
|
|
|
@ -26,8 +26,13 @@ import org.jivesoftware.smack.SmackException.NoResponseException;
|
|||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smack.packet.StanzaBuilder;
|
||||
import org.jivesoftware.smack.packet.StanzaFactory;
|
||||
import org.jivesoftware.smack.packet.StanzaView;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.address.packet.MultipleAddresses;
|
||||
|
@ -207,25 +212,44 @@ public class MultipleRecipientManager {
|
|||
return extension == null ? null : new MultipleRecipientInfo(extension);
|
||||
}
|
||||
|
||||
private static void sendToIndividualRecipients(XMPPConnection connection, Stanza packet,
|
||||
private static void sendToIndividualRecipients(XMPPConnection connection, StanzaView stanza,
|
||||
Collection<? extends Jid> to, Collection<? extends Jid> cc, Collection<? extends Jid> bcc) throws NotConnectedException, InterruptedException {
|
||||
final StanzaFactory stanzaFactory = connection.getStanzaFactory();
|
||||
final StanzaBuilder<?> stanzaBuilder;
|
||||
if (stanza instanceof Message) {
|
||||
Message message = (Message) stanza;
|
||||
stanzaBuilder = stanzaFactory.buildMessageStanzaFrom(message);
|
||||
} else if (stanza instanceof Presence) {
|
||||
Presence presence = (Presence) stanza;
|
||||
stanzaBuilder = stanzaFactory.buildPresenceStanzaFrom(presence);
|
||||
} else if (stanza instanceof IQ) {
|
||||
throw new IllegalArgumentException("IQ stanzas have no supported fallback in case no XEP-0033 service is available");
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
final int numRecipients = to.size() + cc.size() + bcc.size();
|
||||
final List<Jid> recipients = new ArrayList<>(numRecipients);
|
||||
|
||||
if (to != null) {
|
||||
for (Jid jid : to) {
|
||||
packet.setTo(jid);
|
||||
connection.sendStanza(new PacketCopy(packet));
|
||||
}
|
||||
recipients.addAll(to);
|
||||
}
|
||||
if (cc != null) {
|
||||
for (Jid jid : cc) {
|
||||
packet.setTo(jid);
|
||||
connection.sendStanza(new PacketCopy(packet));
|
||||
}
|
||||
recipients.addAll(cc);
|
||||
}
|
||||
if (bcc != null) {
|
||||
for (Jid jid : bcc) {
|
||||
packet.setTo(jid);
|
||||
connection.sendStanza(new PacketCopy(packet));
|
||||
}
|
||||
recipients.addAll(bcc);
|
||||
}
|
||||
|
||||
final List<Stanza> stanzasToSend = new ArrayList<>(numRecipients);
|
||||
for (Jid recipient : recipients) {
|
||||
Stanza stanzaToSend = stanzaBuilder.to(recipient).build();
|
||||
stanzasToSend.add(stanzaToSend);
|
||||
}
|
||||
|
||||
// TODO: Use XMPPConnection.sendStanzas(Collection<? extends Stanza>) once this method exists.
|
||||
for (Stanza stanzaToSend : stanzasToSend) {
|
||||
connection.sendStanza(stanzaToSend);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,43 +313,4 @@ public class MultipleRecipientManager {
|
|||
return sdm.findService(MultipleAddresses.NAMESPACE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stanza that holds the XML stanza to send. This class is useful when the same packet
|
||||
* is needed to be sent to different recipients. Since using the same stanza is not possible
|
||||
* (i.e. cannot change the TO address of a queues stanza to be sent) then this class was
|
||||
* created to keep the XML stanza to send.
|
||||
*/
|
||||
private static final class PacketCopy extends Stanza {
|
||||
|
||||
private final String elementName;
|
||||
private final CharSequence text;
|
||||
|
||||
/**
|
||||
* Create a copy of a stanza with the text to send. The passed text must be a valid text to
|
||||
* send to the server, no validation will be done on the passed text.
|
||||
*
|
||||
* @param text the whole text of the stanza to send
|
||||
*/
|
||||
private PacketCopy(Stanza stanza) {
|
||||
this.elementName = stanza.getElementName();
|
||||
this.text = stanza.toXML();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toXML().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return elementName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,11 +23,14 @@ import java.net.SocketTimeoutException;
|
|||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
||||
import org.jivesoftware.smack.StanzaListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.filter.AndFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaTypeFilter;
|
||||
|
@ -61,6 +64,10 @@ import org.jxmpp.jid.Jid;
|
|||
*/
|
||||
public class InBandBytestreamSession implements BytestreamSession {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(InBandBytestreamSession.class.getName());
|
||||
|
||||
static final String UNEXPECTED_IBB_SEQUENCE = "Unexpected IBB sequence";
|
||||
|
||||
/* XMPP connection */
|
||||
private final XMPPConnection connection;
|
||||
|
||||
|
@ -261,7 +268,7 @@ public class InBandBytestreamSession implements BytestreamSession {
|
|||
private int bufferPointer = -1;
|
||||
|
||||
/* data packet sequence (range from 0 to 65535) */
|
||||
private long seq = -1;
|
||||
private UInt16 expectedSeq = UInt16.MIN_VALUE;
|
||||
|
||||
/* flag to indicate if input stream is closed */
|
||||
private boolean isClosed = false;
|
||||
|
@ -383,21 +390,16 @@ public class InBandBytestreamSession implements BytestreamSession {
|
|||
return false;
|
||||
}
|
||||
|
||||
// handle sequence overflow
|
||||
if (this.seq == 65535) {
|
||||
this.seq = -1;
|
||||
}
|
||||
|
||||
final UInt16 dataSeq = data.getSeq();
|
||||
// check if data packets sequence is successor of last seen sequence
|
||||
long seq = data.getSeq();
|
||||
if (seq - 1 != this.seq) {
|
||||
if (!expectedSeq.equals(dataSeq)) {
|
||||
// packets out of order; close stream/session
|
||||
InBandBytestreamSession.this.close();
|
||||
throw new IOException("Packets out of sequence");
|
||||
}
|
||||
else {
|
||||
this.seq = seq;
|
||||
String message = UNEXPECTED_IBB_SEQUENCE + " " + dataSeq + " received, expected "
|
||||
+ expectedSeq;
|
||||
throw new IOException(message);
|
||||
}
|
||||
expectedSeq = dataSeq.incrementedByOne();
|
||||
|
||||
// set buffer to decoded data
|
||||
buffer = data.getDecodedData();
|
||||
|
@ -465,22 +467,41 @@ public class InBandBytestreamSession implements BytestreamSession {
|
|||
protected StanzaListener getDataPacketListener() {
|
||||
return new StanzaListener() {
|
||||
|
||||
private long lastSequence = -1;
|
||||
private UInt16 expectedSequence = UInt16.MIN_VALUE;;
|
||||
|
||||
@Override
|
||||
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
|
||||
final Data dataIq = (Data) packet;
|
||||
// get data packet extension
|
||||
DataPacketExtension data = ((Data) packet).getDataPacketExtension();
|
||||
DataPacketExtension data = dataIq.getDataPacketExtension();
|
||||
|
||||
final UInt16 seq = data.getSeq();
|
||||
/*
|
||||
* check if sequence was not used already (see XEP-0047 Section 2.2)
|
||||
*/
|
||||
if (data.getSeq() <= this.lastSequence) {
|
||||
IQ unexpectedRequest = IQ.createErrorResponse((IQ) packet,
|
||||
StanzaError.Condition.unexpected_request);
|
||||
if (!expectedSequence.equals(seq)) {
|
||||
String descriptiveEnTest = UNEXPECTED_IBB_SEQUENCE + " " + seq + " received, expected "
|
||||
+ expectedSequence;
|
||||
StanzaError stanzaError = StanzaError.getBuilder()
|
||||
.setCondition(StanzaError.Condition.unexpected_request)
|
||||
.setDescriptiveEnText(descriptiveEnTest)
|
||||
.build();
|
||||
IQ unexpectedRequest = IQ.createErrorResponse(dataIq, stanzaError);
|
||||
connection.sendStanza(unexpectedRequest);
|
||||
return;
|
||||
|
||||
try {
|
||||
// TODO: It would be great if close would take a "close error reason" argument. Also there
|
||||
// is the question if this is really a reason to close the stream. We could have some more
|
||||
// tolerance regarding out-of-sequence stanzas arriving: Even though XMPP has the in-order
|
||||
// guarantee, I could imagine that there are cases where stanzas are, for example,
|
||||
// duplicated because of stream resumption.
|
||||
close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.log(Level.FINER, "Could not close session, because of IOException. Close reason: "
|
||||
+ descriptiveEnTest);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// check if encoded data is valid (see XEP-0047 Section 2.2)
|
||||
|
@ -492,19 +513,14 @@ public class InBandBytestreamSession implements BytestreamSession {
|
|||
return;
|
||||
}
|
||||
|
||||
expectedSequence = seq.incrementedByOne();
|
||||
|
||||
// data is valid; add to data queue
|
||||
dataQueue.offer(data);
|
||||
|
||||
// confirm IQ
|
||||
IQ confirmData = IQ.createResultIQ((IQ) packet);
|
||||
connection.sendStanza(confirmData);
|
||||
|
||||
// set last seen sequence
|
||||
this.lastSequence = data.getSeq();
|
||||
if (this.lastSequence == 65535) {
|
||||
this.lastSequence = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -618,7 +634,7 @@ public class InBandBytestreamSession implements BytestreamSession {
|
|||
protected int bufferPointer = 0;
|
||||
|
||||
/* data packet sequence (range from 0 to 65535) */
|
||||
protected long seq = 0;
|
||||
protected UInt16 seq = UInt16.from(0);
|
||||
|
||||
/* flag to indicate if output stream is closed */
|
||||
protected boolean isClosed = false;
|
||||
|
@ -756,7 +772,7 @@ public class InBandBytestreamSession implements BytestreamSession {
|
|||
bufferPointer = 0;
|
||||
|
||||
// increment sequence, considering sequence overflow
|
||||
this.seq = this.seq + 1 == 65535 ? 0 : this.seq + 1;
|
||||
seq = seq.incrementedByOne();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,10 @@ package org.jivesoftware.smackx.bytestreams.ibb.packet;
|
|||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.IQ.IQChildElementXmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
|
@ -47,7 +49,7 @@ public class DataPacketExtension implements ExtensionElement {
|
|||
private final String sessionID;
|
||||
|
||||
/* sequence of this packet in regard to the other data packets */
|
||||
private final long seq;
|
||||
private final UInt16 seq;
|
||||
|
||||
/* the data contained in this packet */
|
||||
private final String data;
|
||||
|
@ -60,19 +62,28 @@ public class DataPacketExtension implements ExtensionElement {
|
|||
* @param sessionID unique session ID identifying this In-Band Bytestream
|
||||
* @param seq sequence of this stanza in regard to the other data packets
|
||||
* @param data the base64 encoded data contained in this packet
|
||||
* @throws IllegalArgumentException if seq is not within the range [0, 65535].
|
||||
*/
|
||||
public DataPacketExtension(String sessionID, long seq, String data) {
|
||||
public DataPacketExtension(String sessionID, int seq, String data) {
|
||||
this(sessionID, UInt16.from(seq), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new In-Band Bytestream data packet.
|
||||
*
|
||||
* @param sessionID unique session ID identifying this In-Band Bytestream
|
||||
* @param seq sequence of this stanza in regard to the other data packets
|
||||
* @param data the base64 encoded data contained in this packet
|
||||
*/
|
||||
public DataPacketExtension(String sessionID, UInt16 seq, String data) {
|
||||
if (sessionID == null || "".equals(sessionID)) {
|
||||
throw new IllegalArgumentException("Session ID must not be null or empty");
|
||||
}
|
||||
if (seq < 0 || seq > 65535) {
|
||||
throw new IllegalArgumentException("Sequence must not be between 0 and 65535");
|
||||
}
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Data must not be null");
|
||||
}
|
||||
this.sessionID = sessionID;
|
||||
this.seq = seq;
|
||||
this.seq = Objects.requireNonNull(seq);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
@ -90,7 +101,7 @@ public class DataPacketExtension implements ExtensionElement {
|
|||
*
|
||||
* @return the sequence of this stanza in regard to the other data packets.
|
||||
*/
|
||||
public long getSeq() {
|
||||
public UInt16 getSeq() {
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
@ -148,7 +159,7 @@ public class DataPacketExtension implements ExtensionElement {
|
|||
}
|
||||
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("seq", Long.toString(seq));
|
||||
xml.attribute("seq", seq);
|
||||
xml.attribute("sid", sessionID);
|
||||
xml.rightAngleBracket();
|
||||
xml.append(data);
|
||||
|
|
|
@ -18,8 +18,11 @@ package org.jivesoftware.smackx.bytestreams.ibb.provider;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.parsing.SmackParsingException.RequiredAttributeMissingException;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||
|
||||
|
@ -51,9 +54,9 @@ public class DataPacketProvider {
|
|||
@Override
|
||||
public DataPacketExtension parse(XmlPullParser parser,
|
||||
int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException,
|
||||
IOException {
|
||||
IOException, RequiredAttributeMissingException {
|
||||
String sessionID = parser.getAttributeValue("", "sid");
|
||||
long seq = Long.parseLong(parser.getAttributeValue("", "seq"));
|
||||
UInt16 seq = ParserUtils.getRequiredUInt16Attribute(parser, "seq");
|
||||
String data = parser.nextText();
|
||||
return new DataPacketExtension(sessionID, seq, data);
|
||||
}
|
||||
|
|
|
@ -214,8 +214,10 @@ public abstract class FileTransfer {
|
|||
amountWritten += count;
|
||||
}
|
||||
|
||||
// the connection was likely terminated abruptly if these are not equal
|
||||
if (!getStatus().equals(Status.cancelled) && getError() == Error.none
|
||||
// When the amount of data written does not equal the expected amount, and
|
||||
// the transfer was not explicitly cancelled, register an error (unless another
|
||||
// error has already been logged).
|
||||
if (!getStatus().equals(Status.cancelled) && getError() == null
|
||||
&& amountWritten != fileSize) {
|
||||
setStatus(Status.error);
|
||||
this.error = Error.connection;
|
||||
|
@ -313,11 +315,6 @@ public abstract class FileTransfer {
|
|||
|
||||
@SuppressWarnings("JavaLangClash")
|
||||
public enum Error {
|
||||
/**
|
||||
* No error.
|
||||
*/
|
||||
none("No error"),
|
||||
|
||||
/**
|
||||
* The peer did not find any of the provided stream mechanisms
|
||||
* acceptable.
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.WeakHashMap;
|
|||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
@ -152,7 +152,7 @@ public final class VersionManager extends Manager {
|
|||
|
||||
private static Version generateVersionFrom(String name, String version, String os) {
|
||||
if (autoAppendSmackVersion) {
|
||||
name += " (Smack " + SmackConfiguration.getVersion() + ')';
|
||||
name += " (Smack " + Smack.getVersion() + ')';
|
||||
}
|
||||
return new Version(name, version, os);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2019-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -83,8 +83,8 @@ public class MediaElement implements FormFieldChildElement {
|
|||
@Override
|
||||
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this, xmlEnvironment);
|
||||
xml.optAttribute("height", height)
|
||||
.optAttribute("width", width)
|
||||
xml.optAttributeCs("height", height)
|
||||
.optAttributeCs("width", width)
|
||||
.rightAngleBracket();
|
||||
|
||||
xml.append(uris);
|
||||
|
|
|
@ -149,6 +149,11 @@ public class MultiUserChat {
|
|||
private EntityFullJid myRoomJid;
|
||||
private StanzaCollector messageCollector;
|
||||
|
||||
/**
|
||||
* Used to signal that the reflected self-presence was received <b>and</b> processed by us.
|
||||
*/
|
||||
private volatile boolean processedReflectedSelfPresence;
|
||||
|
||||
MultiUserChat(XMPPConnection connection, EntityBareJid room, MultiUserChatManager multiUserChatManager) {
|
||||
this.connection = connection;
|
||||
this.room = room;
|
||||
|
@ -195,6 +200,7 @@ public class MultiUserChat {
|
|||
}
|
||||
final EntityFullJid myRoomJID = myRoomJid;
|
||||
final boolean isUserStatusModification = presence.getFrom().equals(myRoomJID);
|
||||
final MUCUser mucUser = MUCUser.from(packet);
|
||||
|
||||
switch (presence.getType()) {
|
||||
case available:
|
||||
|
@ -205,9 +211,8 @@ public class MultiUserChat {
|
|||
MUCAffiliation oldAffiliation = mucExtension.getItem().getAffiliation();
|
||||
MUCRole oldRole = mucExtension.getItem().getRole();
|
||||
// Get the new occupant's affiliation & role
|
||||
mucExtension = MUCUser.from(packet);
|
||||
MUCAffiliation newAffiliation = mucExtension.getItem().getAffiliation();
|
||||
MUCRole newRole = mucExtension.getItem().getRole();
|
||||
MUCAffiliation newAffiliation = mucUser.getItem().getAffiliation();
|
||||
MUCRole newRole = mucUser.getItem().getRole();
|
||||
// Fire role modification events
|
||||
checkRoleModifications(oldRole, newRole, isUserStatusModification, from);
|
||||
// Fire affiliation modification events
|
||||
|
@ -216,19 +221,20 @@ public class MultiUserChat {
|
|||
newAffiliation,
|
||||
isUserStatusModification,
|
||||
from);
|
||||
}
|
||||
else {
|
||||
} else if (mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)) {
|
||||
processedReflectedSelfPresence = true;
|
||||
synchronized (this) {
|
||||
notify();
|
||||
}
|
||||
} else {
|
||||
// A new occupant has joined the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
}
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case unavailable:
|
||||
occupantsMap.remove(from);
|
||||
MUCUser mucUser = MUCUser.from(packet);
|
||||
if (mucUser != null && mucUser.hasStatus()) {
|
||||
if (isUserStatusModification) {
|
||||
userHasLeft();
|
||||
|
@ -377,8 +383,9 @@ public class MultiUserChat {
|
|||
)
|
||||
);
|
||||
// @formatter:on
|
||||
processedReflectedSelfPresence = false;
|
||||
StanzaCollector presenceStanzaCollector = null;
|
||||
Presence presence;
|
||||
final Presence reflectedSelfPresence;
|
||||
try {
|
||||
// This stanza collector will collect the final self presence from the MUC, which also signals that we have successful entered the MUC.
|
||||
StanzaCollector selfPresenceCollector = connection.createStanzaCollectorAndSend(responseFilter, joinPresence);
|
||||
|
@ -386,7 +393,7 @@ public class MultiUserChat {
|
|||
selfPresenceCollector).setStanzaFilter(presenceFromRoomFilter);
|
||||
// This stanza collector is used to reset the timeout of the selfPresenceCollector.
|
||||
presenceStanzaCollector = connection.createStanzaCollector(presenceStanzaCollectorConfguration);
|
||||
presence = selfPresenceCollector.nextResultOrThrow(conf.getTimeout());
|
||||
reflectedSelfPresence = selfPresenceCollector.nextResultOrThrow(conf.getTimeout());
|
||||
}
|
||||
catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) {
|
||||
// Ensure that all callbacks are removed if there is an exception
|
||||
|
@ -399,14 +406,24 @@ public class MultiUserChat {
|
|||
}
|
||||
}
|
||||
|
||||
synchronized (presenceListener) {
|
||||
// Only continue after we have received *and* processed the reflected self-presence. Since presences are
|
||||
// handled in an extra listener, we may return from enter() without having processed all presences of the
|
||||
// participants, resulting in a e.g. to low participant counter after enter(). Hence we wait here until the
|
||||
// processing is done.
|
||||
while (!processedReflectedSelfPresence) {
|
||||
presenceListener.wait();
|
||||
}
|
||||
}
|
||||
|
||||
// This presence must be send from a full JID. We use the resourcepart of this JID as nick, since the room may
|
||||
// performed roomnick rewriting
|
||||
Resourcepart receivedNickname = presence.getFrom().getResourceOrThrow();
|
||||
Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow();
|
||||
setNickname(receivedNickname);
|
||||
|
||||
// Update the list of joined rooms
|
||||
multiUserChatManager.addJoinedRoom(room);
|
||||
return presence;
|
||||
return reflectedSelfPresence;
|
||||
}
|
||||
|
||||
private void setNickname(Resourcepart nickname) {
|
||||
|
|
|
@ -51,14 +51,9 @@ public class OptionsExtension extends NodeExtension {
|
|||
|
||||
@Override
|
||||
protected void addXml(XmlStringBuilder xml) {
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.halfOpenElement(getElementName());
|
||||
xml.attribute("jid", jid);
|
||||
xml.optAttribute("node", getNode());
|
||||
xml.optAttribute("subid", id);
|
||||
|
||||
xml.closeEmptyElement();
|
||||
xml.closeElement(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -401,8 +401,8 @@ public abstract class ValidateElement implements FormFieldChildElement {
|
|||
@Override
|
||||
public XmlStringBuilder toXML(XmlEnvironment enclosingXmlEnvironment) {
|
||||
XmlStringBuilder buf = new XmlStringBuilder(this, enclosingXmlEnvironment);
|
||||
buf.optAttribute("min", getMin());
|
||||
buf.optAttribute("max", getMax());
|
||||
buf.optAttributeCs("min", getMin());
|
||||
buf.optAttributeCs("max", getMax());
|
||||
buf.closeEmptyElement();
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package org.jivesoftware.smackx.bytestreams.ibb;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -102,7 +102,7 @@ public class InBandBytestreamSessionMessageTest extends SmackTestSuite {
|
|||
public void verify(Message request, IQ response) {
|
||||
DataPacketExtension dpe = request.getExtension(
|
||||
DataPacketExtension.class);
|
||||
assertEquals(lastSeq++, dpe.getSeq());
|
||||
assertEquals(lastSeq++, dpe.getSeq().longValue());
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -275,16 +275,13 @@ public class InBandBytestreamSessionMessageTest extends SmackTestSuite {
|
|||
listener.processStanza(dataMessage);
|
||||
|
||||
// read until exception is thrown
|
||||
try {
|
||||
inputStream.read();
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
catch (IOException e) {
|
||||
assertTrue(e.getMessage().contains("Packets out of sequence"));
|
||||
}
|
||||
IOException ioException = assertThrows(IOException.class, () ->
|
||||
inputStream.read()
|
||||
);
|
||||
String ioExceptionMessage = ioException.getMessage();
|
||||
assertTrue(ioExceptionMessage.startsWith(InBandBytestreamSession.UNEXPECTED_IBB_SEQUENCE));
|
||||
|
||||
protocol.verifyAll();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.jivesoftware.smackx.bytestreams.ibb;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
@ -29,6 +30,7 @@ import org.jivesoftware.smack.SmackException;
|
|||
import org.jivesoftware.smack.StanzaListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.StanzaError;
|
||||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||
|
@ -96,11 +98,11 @@ public class InBandBytestreamSessionTest extends SmackTestSuite {
|
|||
|
||||
incrementingSequence = new Verification<Data, IQ>() {
|
||||
|
||||
long lastSeq = 0;
|
||||
int lastSeq = 0;
|
||||
|
||||
@Override
|
||||
public void verify(Data request, IQ response) {
|
||||
assertEquals(lastSeq++, request.getDataPacketExtension().getSeq());
|
||||
assertEquals(lastSeq++, request.getDataPacketExtension().getSeq().intValue());
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -266,9 +268,9 @@ public class InBandBytestreamSessionTest extends SmackTestSuite {
|
|||
@Override
|
||||
public void verify(Data request, IQ response) {
|
||||
byte[] decodedData = request.getDataPacketExtension().getDecodedData();
|
||||
int seq = (int) request.getDataPacketExtension().getSeq();
|
||||
UInt16 seq = request.getDataPacketExtension().getSeq();
|
||||
for (int i = 0; i < decodedData.length; i++) {
|
||||
assertEquals(controlData[(seq * blockSize) + i], decodedData[i]);
|
||||
assertEquals(controlData[(seq.intValue() * blockSize) + i], decodedData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,15 +443,6 @@ public class InBandBytestreamSessionTest extends SmackTestSuite {
|
|||
*/
|
||||
@Test
|
||||
public void shouldSendCloseRequestIfInvalidSequenceReceived() throws Exception {
|
||||
IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID);
|
||||
|
||||
// confirm data packet with invalid sequence
|
||||
protocol.addResponse(resultIQ);
|
||||
|
||||
// confirm close request
|
||||
protocol.addResponse(resultIQ, Verification.requestTypeSET,
|
||||
Verification.correspondingSenderReceiver);
|
||||
|
||||
// get IBB sessions data packet listener
|
||||
InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream,
|
||||
initiatorJID);
|
||||
|
@ -465,16 +458,11 @@ public class InBandBytestreamSessionTest extends SmackTestSuite {
|
|||
listener.processStanza(data);
|
||||
|
||||
// read until exception is thrown
|
||||
try {
|
||||
inputStream.read();
|
||||
fail("exception should be thrown");
|
||||
}
|
||||
catch (IOException e) {
|
||||
assertTrue(e.getMessage().contains("Packets out of sequence"));
|
||||
}
|
||||
|
||||
protocol.verifyAll();
|
||||
|
||||
IOException ioException = assertThrows(IOException.class, () ->
|
||||
inputStream.read()
|
||||
);
|
||||
String ioExceptionMessage = ioException.getMessage();
|
||||
assertTrue(ioExceptionMessage.equals("Stream is closed"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,7 +75,7 @@ public class DataPacketExtensionTest extends SmackTestSuite {
|
|||
public void shouldSetAllFieldsCorrectly() {
|
||||
DataPacketExtension data = new DataPacketExtension("sessionID", 0, "data");
|
||||
assertEquals("sessionID", data.getSessionID());
|
||||
assertEquals(0, data.getSeq());
|
||||
assertEquals(0, data.getSeq().intValue());
|
||||
assertEquals("data", data.getData());
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import java.util.logging.Logger;
|
|||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
|
@ -171,7 +172,7 @@ public class SmackIntegrationTestFramework {
|
|||
// Create a connection manager *after* we created the testRunId (in testRunResult).
|
||||
this.connectionManager = new XmppConnectionManager(this);
|
||||
|
||||
LOGGER.info("SmackIntegrationTestFramework [" + testRunResult.testRunId + ']' + ": Starting\nSmack version: " + SmackConfiguration.getVersion());
|
||||
LOGGER.info("SmackIntegrationTestFramework [" + testRunResult.testRunId + ']' + ": Starting\nSmack version: " + Smack.getVersion());
|
||||
if (config.debugger != Configuration.Debugger.none) {
|
||||
// JUL Debugger will not print any information until configured to print log messages of
|
||||
// level FINE
|
||||
|
@ -457,7 +458,7 @@ public class SmackIntegrationTestFramework {
|
|||
sb.append("Available tests: ").append(numberOfAvailableTests);
|
||||
if (!testRunResult.disabledTestClasses.isEmpty() || !testRunResult.disabledTests.isEmpty()) {
|
||||
sb.append(" (Disabled ").append(testRunResult.disabledTestClasses.size()).append(" classes")
|
||||
.append(" and ").append(testRunResult.disabledTests.size()).append(" tests");
|
||||
.append(" and ").append(testRunResult.disabledTests.size()).append(" tests)");
|
||||
}
|
||||
sb.append('\n');
|
||||
LOGGER.info(sb.toString());
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.muc;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -144,9 +146,9 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
|
||||
muc.addUserStatusListener(userStatusListener);
|
||||
|
||||
assertTrue(mucManagerOne.getJoinedRooms().size() == 1);
|
||||
assertTrue(muc.getOccupantsCount() == 1);
|
||||
assertTrue(muc.getNickname() != null);
|
||||
assertEquals(1, mucManagerOne.getJoinedRooms().size());
|
||||
assertEquals(1, muc.getOccupantsCount());
|
||||
assertNotNull(muc.getNickname());
|
||||
|
||||
try {
|
||||
muc.destroy("Dummy reason", null);
|
||||
|
@ -155,8 +157,8 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
muc.removeUserStatusListener(userStatusListener);
|
||||
}
|
||||
|
||||
assertTrue(mucManagerOne.getJoinedRooms().size() == 0);
|
||||
assertTrue(muc.getOccupantsCount() == 0);
|
||||
assertTrue(muc.getNickname() == null);
|
||||
assertEquals(0, mucManagerOne.getJoinedRooms().size());
|
||||
assertEquals(0, muc.getOccupantsCount());
|
||||
assertNull(muc.getNickname());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ dependencies {
|
|||
api project(':smack-websocket')
|
||||
api project(':smack-tcp')
|
||||
|
||||
testImplementation 'com.google.guava:guava:28.2-jre'
|
||||
testImplementation(testFixtures(project(":smack-core")))
|
||||
testImplementation 'org.jgrapht:jgrapht-io:1.3.1'
|
||||
}
|
||||
|
||||
|
|
|
@ -295,14 +295,9 @@ public final class OpenPgpManager extends Manager {
|
|||
|
||||
throwIfNoProviderSet();
|
||||
OpenPgpStore store = provider.getStore();
|
||||
PGPKeyRing keys = store.generateKeyRing(ourJid);
|
||||
try {
|
||||
store.importSecretKey(ourJid, keys.getSecretKeys());
|
||||
store.importPublicKey(ourJid, keys.getPublicKeys());
|
||||
} catch (MissingUserIdOnKeyException e) {
|
||||
// This should never throw, since we set our jid literally one line above this comment.
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
PGPKeyRing keys = generateKeyRing(ourJid);
|
||||
importKeyRing(ourJid, keys);
|
||||
|
||||
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(keys.getSecretKeys());
|
||||
|
||||
|
@ -311,6 +306,23 @@ public final class OpenPgpManager extends Manager {
|
|||
return fingerprint;
|
||||
}
|
||||
|
||||
public PGPKeyRing generateKeyRing(BareJid ourJid)
|
||||
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
|
||||
throwIfNoProviderSet();
|
||||
PGPKeyRing keys = provider.getStore().generateKeyRing(ourJid);
|
||||
return keys;
|
||||
}
|
||||
|
||||
private void importKeyRing(BareJid ourJid, PGPKeyRing keyRing) throws IOException, PGPException {
|
||||
try {
|
||||
provider.getStore().importSecretKey(ourJid, keyRing.getSecretKeys());
|
||||
provider.getStore().importPublicKey(ourJid, keyRing.getPublicKeys());
|
||||
} catch (MissingUserIdOnKeyException e) {
|
||||
// This should never throw, since we set our jid literally one line above this comment.
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the upper-case hex encoded OpenPGP v4 fingerprint of our key pair.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Florian Schmaus
|
||||
* Copyright 2016-2020 Florian Schmaus
|
||||
*
|
||||
* This file is part of smack-repl.
|
||||
*
|
||||
|
@ -20,13 +20,13 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.smackrepl;
|
||||
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.util.dns.javax.JavaxResolver;
|
||||
|
||||
public class SmackRepl {
|
||||
|
||||
public static void init() {
|
||||
SmackConfiguration.getVersion();
|
||||
Smack.ensureInitialized();
|
||||
// smack-repl also pulls in smack-resolver-minidns which has higher precedence the smack-resolver-javax but
|
||||
// won't work on Java SE platforms. Therefore explicitly setup JavaxResolver.
|
||||
JavaxResolver.setup();
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.jivesoftware.smack.tcp.rce;
|
|||
import java.net.InetAddress;
|
||||
|
||||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.rce.SingleAddressRemoteConnectionEndpoint;
|
||||
|
||||
import org.minidns.record.InternetAddressRR;
|
||||
|
@ -33,9 +34,9 @@ public final class IpTcpRemoteConnectionEndpoint<IARR extends InternetAddressRR<
|
|||
private final IARR internetAddressResourceRecord;
|
||||
|
||||
public IpTcpRemoteConnectionEndpoint(CharSequence host, UInt16 port, IARR internetAddressResourceRecord) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.internetAddressResourceRecord = internetAddressResourceRecord;
|
||||
this.host = Objects.requireNonNull(host);
|
||||
this.port = Objects.requireNonNull(port);
|
||||
this.internetAddressResourceRecord = Objects.requireNonNull(internetAddressResourceRecord);
|
||||
}
|
||||
|
||||
public static IpTcpRemoteConnectionEndpoint<InternetAddressRR<?>> from(CharSequence host, UInt16 port,
|
||||
|
|
|
@ -192,8 +192,10 @@ public class RemoteXmppTcpConnectionEndpoints {
|
|||
|
||||
for (SRV srv : sortedSrvRecords) {
|
||||
List<InetAddress> targetInetAddresses = dnsResolver.lookupHostAddress(srv.target, lookupFailures, dnssecMode);
|
||||
SrvXmppRemoteConnectionEndpoint endpoint = new SrvXmppRemoteConnectionEndpoint(srv, targetInetAddresses);
|
||||
endpoints.add(endpoint);
|
||||
if (targetInetAddresses != null) {
|
||||
SrvXmppRemoteConnectionEndpoint endpoint = new SrvXmppRemoteConnectionEndpoint(srv, targetInetAddresses);
|
||||
endpoints.add(endpoint);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGGER.info("Could not resolve DNS SRV resource records for " + srvDomain + ". Consider adding those.");
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.datatypes.UInt16;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpoint;
|
||||
|
||||
import org.minidns.record.SRV;
|
||||
|
@ -36,7 +37,7 @@ public abstract class SrvRemoteConnectionEndpoint implements RemoteConnectionEnd
|
|||
protected SrvRemoteConnectionEndpoint(SRV srv, List<? extends InetAddress> inetAddresses) {
|
||||
this.srv = srv;
|
||||
this.port = UInt16.from(srv.port);
|
||||
this.inetAddresses = inetAddresses;
|
||||
this.inetAddresses = Objects.requireNonNull(inetAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 Florian Schmaus
|
||||
* Copyright 2020-2020 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -34,7 +34,10 @@ public class StaxXmlPullParserFactory implements XmlPullParserFactory {
|
|||
// getText().
|
||||
xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
|
||||
// Internal and external entity references are prohibited in XMPP (RFC 6120 § 11.1).
|
||||
xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
|
||||
xmlInputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
|
||||
// We don't need to support DTDs in XMPP.
|
||||
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue