1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-02-16 22:06:25 +01:00

Compare commits

...

37 commits

Author SHA1 Message Date
Florian Schmaus
d8642847ea Smack 4.4.0
-----BEGIN PGP SIGNATURE-----
 
 iQGTBAABCgB9FiEEl3UFnzoh3OFr5PuuIjmn6PWFIFIFAl/Msl5fFIAAAAAALgAo
 aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDk3
 NzUwNTlGM0EyMURDRTE2QkU0RkJBRTIyMzlBN0U4RjU4NTIwNTIACgkQIjmn6PWF
 IFIq8gf9GZp0Cl9Gr+seA/C8nczE/cNRKfHnDR224klbjlGrnojb+bL2QgeKG6wN
 u/eL3+UMus8uw3+R8NKARawqt/r6mbk4bgdGEbzoByLO6iiPYTr7TuZmTOQyZa5L
 tMNkFIvfvMzDeDDqI4z4uTgT3s7YBg0d4BT7cL8T6RaZGHF57OxqhWnKxMuaiTXH
 HJzVTPrtAcYg17QZl5+mrhiWyynE5+4QGeluYHlh7vvsniwNOqrwO1vWHg2BX003
 DjaHK+6oLjKxVljCklXxE7Wsx0VcMrBfv2qZwW3Q4ZzZVcrAn8TC4HrUtR8DL176
 DpGlEhmmdr3xKKX0JQ9RmIod+xSabw==
 =4wGX
 -----END PGP SIGNATURE-----

Merge tag '4.4.0'

Smack 4.4.0
2020-12-06 12:16:44 +01:00
Florian Schmaus
d8864b62ca Smack 4.4.0 2020-12-06 11:28:41 +01:00
Florian Schmaus
a4bb5bfda8 [ibb] Use UInt16 for 'seq' and fix its handling
Fixes a off-by-one error when incrementing 'seq'. Thanks to Kim
Alvefur <zash@zash.se> for spotting this.
2020-12-05 23:04:17 +01:00
Florian Schmaus
1a963cc794 Merge branch '4.4' 2020-11-25 20:57:44 +01:00
Florian Schmaus
02c9058c3d [core] Remove @SuppressWarnings for parseContentDepthWithRoundtrip()
Also use the most specific return type in the method's signature.
2020-11-25 20:55:05 +01:00
Florian Schmaus
ca497a2199 [core] Fix parseContentDepthWithRoundtrip() and add tests 2020-11-25 20:55:05 +01:00
Florian Schmaus
821bdf6d86 Smack 4.4.0-rc3-SNAPSHOT 2020-11-18 21:19:01 +01:00
Florian Schmaus
c1f3f8ce13 Smack 4.4.0-rc2 2020-11-18 20:04:55 +01:00
Florian Schmaus
a2636b2f60 Merge branch '4.4' 2020-11-14 15:33:42 +01:00
Florian Schmaus
f10cbb4a97 [core] Add requireNonNull() check to some connection endpoints 2020-11-14 12:47:35 +01:00
Florian Schmaus
c4228e072b [tcp] Add missing null check in resolveDomain()
The method lookupHostAddress() returns null in case of an error, hence
we need to test if the returned value is null prior adding the endpoint.

Should fix the following NPE:

java.lang.NullPointerException:
  at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration (XMPPTCPConnection.java:606)
  at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal (XMPPTCPConnection.java:846)
  at org.jivesoftware.smack.AbstractXMPPConnection.connect (AbstractXMPPConnection.java:530)
  at org.jivesoftware.smack.ReconnectionManager$2.run (ReconnectionManager.java:282)
  at java.lang.Thread.run (Thread.java:784)

Reported-by: Eng ChongMeng <cmeng.gm@gmail.com>
2020-11-14 12:47:34 +01:00
Florian Schmaus
3f3a7cb540 Merge branch '4.4' 2020-11-09 21:23:25 +01:00
Guus der Kinderen
59cf449799 Provide more detailed code comment. 2020-11-09 21:21:27 +01:00
Guus der Kinderen
0ff8040895 FileTransfer: replace Error.none with null
This fixes an inconsistent representation of a 'no error' representation, that
causes a file transfer in which not enough bytes were transferred to _not_ be
marked as having a problem.
2020-11-09 21:21:27 +01:00
Florian Schmaus
5522d6681e [README] Update contact information 2020-11-09 12:26:51 +01:00
Florian Schmaus
68f400616d [README] Update URL for Nightly Unique Maven Snapshots 2020-11-09 12:21:24 +01:00
Florian Schmaus
71f5cfe3da Merge branch '4.4' 2020-11-09 11:08:47 +01:00
Florian Schmaus
e117f431bc Smack 4.4.0-rc2-SNAPSHOT 2020-11-09 09:32:29 +01:00
Florian Schmaus
e6236b0c21 Smack 4.4.0-rc1 2020-11-09 08:54:18 +01:00
Florian Schmaus
afd18f95c9 Add Smack.getNoticeStream() and 'License' section to README 2020-11-09 08:46:57 +01:00
Florian Schmaus
1f5ada4822 Add org.jivesoftware.smack.Smack with getVersion() and ensureInitialized() 2020-11-09 08:46:57 +01:00
Florian Schmaus
df96c57093 [address] Get rid of PacketCopy workaround
PacketCopy subclassing Stanza was always a peculiarity. The only
subclasses of Stanza should be Message, Presence, and IQ.
2020-11-09 08:46:56 +01:00
Florian Schmaus
72acd8e095 [core] Add StanzaBuilder.build() 2020-11-09 08:46:56 +01:00
Florian Schmaus
7e311ab9df [muc] Prevent race condition on enter() by waiting
This prevents a race condition of enter() with the presence listern by
waiting until all presences have been processed.

Reported-by: Guus der Kinderen <guus@goodbytes.nl>
2020-11-09 08:46:56 +01:00
Florian Schmaus
f12fe2264a [muc] Only retrieve MUCUser once in Presence listener 2020-11-08 19:37:41 +01:00
Florian Schmaus
5dfed2935f Add NOTICE file 2020-11-05 12:54:54 +01:00
Florian Schmaus
e1624e1ab9 Add resources/get-contributors.sh 2020-11-05 12:52:22 +01:00
Florian Schmaus
74adcda23d Add .mailmap 2020-11-05 12:52:17 +01:00
Florian Schmaus
cfccc78ba0 [muc] Rename local variable 'presence' to 'reflectedSelfPresence'
To increase readability, and with that maintainability, we rename
'presence' to 'reflectedSelfPresence' in MultiUserChat.enter(), to
make it clear what kind of presence this variable holds.

Also mark the variable as final.
2020-11-03 22:31:22 +01:00
Florian Schmaus
5f66685949
Merge pull request #436 from guusdk/sint-use-specific-assertions
In tests, use specific assertion implementation
2020-10-27 11:57:21 +01:00
Guus der Kinderen
a809f181f5 In tests, use specific assertion implementation
These generate more helpful error messages when assertions fail and
help to show intent.
2020-10-27 11:30:44 +01:00
Florian Schmaus
b7a235f43c
Merge pull request #435 from guusdk/sint-cli-output-fix
Add missing right parenthesis in SINT output
2020-10-27 11:14:18 +01:00
Guus der Kinderen
55d7b9d4eb Fix pubsub options rendering
The exiting code generates an unintentional nested 'options' child element:

```
<iq to='pubsub.example.org' id='FQTHU-126' type='get'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='sinttest-multisubscribe-nodename-13pnc'>
      <options jid='smack-inttest-two-13pnc@example.org'
               node='sinttest-multisubscribe-nodename-13pnc'/>
    </options>
  </pubsub>
</iq>
```

This commit removes the undesired nesting, resulting in:

```
<iq to='pubsub.example.org' id='FQTHU-126' type='get'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options jid='smack-inttest-two-13pnc@example.org'
             node='sinttest-multisubscribe-nodename-13pnc'/>
  </pubsub>
</iq>
```
2020-10-27 10:23:17 +01:00
1a9ac238e8 OpenPgpManager: Expose methods to generate and import keys 2020-10-27 10:22:46 +01:00
Florian Schmaus
28dd56a13a
Merge pull request #438 from Flowdalic/stax-disable-xxe-and-dtd
[xmlparser-stax] Disable external entities and DTD
2020-10-05 09:15:42 +02:00
Florian Schmaus
c1b412c457 [xmlparser-stax] Disable external entities and DTD
Before that, the StAX parser used by Smack for XML parsing had
only external entity replacement disabled. We further harden the
parser by disabling DTDs.

See also:
https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser
2020-10-05 08:55:10 +02:00
Guus der Kinderen
254c315852 Add missing right parenthesis in SINT output
While running the Smack integration tests, a line like this is printed to std-out somewhere

    Available tests: 21 (Disabled 12 classes and 6 tests

There's a missing character on the end of that line, which makes the author of this commit twitch.
This commit adds the missing character, resulting in a line like this:

    Available tests: 21 (Disabled 12 classes and 6 tests)
2020-10-03 15:56:06 +02:00
53 changed files with 848 additions and 211 deletions

27
.mailmap Normal file
View 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
View 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

View file

@ -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
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
git shortlog -s |\
cut -f2- |\
grep -v '(no author)' |\
grep '\w \w.*' |\
sort

View file

@ -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&#39;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&#39;s XmlStreamReader and XPP3 on Android)
</li>
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-650'>SMACK-650</a>] - Enable Java8&#39;s javadoc doclint
</li>
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-651'>SMACK-651</a>] - Perform sound cross-compilation: Use newer javac&#39;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&lt;E extends ExtensionElement&gt;)
</li>
<li>[<a href='https://igniterealtime.atlassian.net/browse/SMACK-826'>SMACK-826</a>] - Add support for XEP-0373:&quot; OpenPGP for XMPP&quot; and XEP-0374: &quot;OpenPGP for XMPP Instant Messaging&quot;
</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 &quot;participant left&quot; 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&#39;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

View file

@ -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 {

View file

@ -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 {

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -43,6 +43,7 @@ public abstract class IqBuilder<IB extends IqBuilder<IB, I>, I extends IQ>
return getThis();
}
@Override
public abstract I build();
}

View file

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

View file

@ -37,6 +37,7 @@ public abstract class MessageOrPresenceBuilder<MP extends MessageOrPresence<? ex
super(stanzaId);
}
@Override
public abstract MP build();
}

View file

@ -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

View file

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

View file

@ -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")

View file

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

View file

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

View file

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

View file

@ -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}.
*

View file

@ -0,0 +1 @@
../../../../../NOTICE

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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"));
}
/**

View file

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

View file

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

View file

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

View file

@ -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'
}

View file

@ -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.
*

View file

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

View file

@ -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,

View file

@ -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.");

View file

@ -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

View file

@ -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