mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-25 15:52:06 +01:00
Merge branch '4.0'
Conflicts: build.gradle documentation/connections.html documentation/gettingstarted.html smack-core/src/main/java/org/jivesoftware/smack/SmackException.java smack-core/src/test/java/org/jivesoftware/smack/parsing/ParsingExceptionTest.java smack-core/src/test/java/org/jivesoftware/smack/test/util/TestUtils.java smack-core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java smack-extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java smack-extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java smack-tcp/src/main/java/org/jivesoftware/smack/tcp/PacketReader.java
This commit is contained in:
commit
94a16ba41e
61 changed files with 806 additions and 300 deletions
22
build.gradle
22
build.gradle
|
@ -19,6 +19,7 @@ allprojects {
|
||||||
sonatypeStagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2'
|
sonatypeStagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2'
|
||||||
buildDate = (new java.text.SimpleDateFormat("yyyy-MM-dd")).format(new Date())
|
buildDate = (new java.text.SimpleDateFormat("yyyy-MM-dd")).format(new Date())
|
||||||
oneLineDesc = 'An Open Source XMPP (Jabber) client library'
|
oneLineDesc = 'An Open Source XMPP (Jabber) client library'
|
||||||
|
jxmppVersion = "0.1.0"
|
||||||
}
|
}
|
||||||
group = 'org.igniterealtime.smack'
|
group = 'org.igniterealtime.smack'
|
||||||
sourceCompatibility = 1.7
|
sourceCompatibility = 1.7
|
||||||
|
@ -35,7 +36,12 @@ allprojects {
|
||||||
// first occurence of an dash with a dot.
|
// first occurence of an dash with a dot.
|
||||||
// For example 4.0.0-rc1 becomes 4.0.0.rc1, but
|
// For example 4.0.0-rc1 becomes 4.0.0.rc1, but
|
||||||
// 4.0.0-SNAPSHOT-2014-05-01 becomes 4.0.0.SNAPSHOT-2014-05-01
|
// 4.0.0-SNAPSHOT-2014-05-01 becomes 4.0.0.SNAPSHOT-2014-05-01
|
||||||
'Bundle-Version': version.replaceFirst("-", "."))
|
'Bundle-Version': version.replaceFirst("-", "."),
|
||||||
|
'Built-Date': new Date(),
|
||||||
|
'Built-JDK': System.getProperty('java.version'),
|
||||||
|
'Built-Gradle': gradle.gradleVersion,
|
||||||
|
'Built-By': System.getProperty('user.name')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
eclipse {
|
eclipse {
|
||||||
|
@ -73,6 +79,9 @@ task javadocAll(type: Javadoc) {
|
||||||
// Might need a classpath
|
// Might need a classpath
|
||||||
classpath = files(subprojects.collect {project ->
|
classpath = files(subprojects.collect {project ->
|
||||||
project.sourceSets.main.compileClasspath})
|
project.sourceSets.main.compileClasspath})
|
||||||
|
options.linkSource = true
|
||||||
|
options.use = true
|
||||||
|
options.links = ["http://docs.oracle.com/javase/$sourceCompatibility/docs/api/"] as String[]
|
||||||
}
|
}
|
||||||
|
|
||||||
import org.apache.tools.ant.filters.ReplaceTokens
|
import org.apache.tools.ant.filters.ReplaceTokens
|
||||||
|
@ -100,6 +109,9 @@ jar {
|
||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable upload archives for the root project
|
||||||
|
uploadArchives.enabled = false
|
||||||
|
|
||||||
description = """\
|
description = """\
|
||||||
Smack ${version}
|
Smack ${version}
|
||||||
${oneLineDesc}."""
|
${oneLineDesc}."""
|
||||||
|
@ -157,7 +169,7 @@ subprojects {
|
||||||
|
|
||||||
issueManagement {
|
issueManagement {
|
||||||
system 'JIRA'
|
system 'JIRA'
|
||||||
url 'http://issues.igniterealtime.org/browse/SMACK'
|
url 'https://igniterealtime.org/issues/browse/SMACK'
|
||||||
}
|
}
|
||||||
|
|
||||||
distributionManagement {
|
distributionManagement {
|
||||||
|
@ -195,7 +207,9 @@ subprojects {
|
||||||
rootProject.distributionZip {
|
rootProject.distributionZip {
|
||||||
dependsOn build
|
dependsOn build
|
||||||
from(buildDir) {
|
from(buildDir) {
|
||||||
include "$libsDirName/**"
|
include "$libsDirName/*${version}.jar"
|
||||||
|
include "$libsDirName/*${version}-javadoc.jar"
|
||||||
|
include "$libsDirName/*${version}-sources.jar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signing {
|
signing {
|
||||||
|
@ -204,7 +218,7 @@ subprojects {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
['smack-extensions', 'smack-experimental', 'smack-legacy'].each { name ->
|
['smack-resolver-javax', 'smack-extensions', 'smack-experimental', 'smack-legacy'].each { name ->
|
||||||
project(":$name") {
|
project(":$name") {
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
manifest {
|
||||||
|
|
|
@ -16,8 +16,8 @@ Debugging with Smack
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Smack includes two built-in debugging consoles that will let you track all XML traffic between
|
Smack includes two built-in debugging consoles that will let you track all XML traffic between
|
||||||
the client and server. A <a href="#lite">lite debugger</a> which is part of the <tt>smack.jar</tt>
|
the client and server. A <a href="#lite">lite debugger</a> which is part of the <tt>smack-core.jar</tt>
|
||||||
and an <a href="#enhanced">enhanced debugger</a> contained in <tt>smackx-debug.jar</tt>.
|
and an <a href="#enhanced">enhanced debugger</a> contained in <tt>smack-debug.jar</tt>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -56,7 +56,7 @@ Smack uses the following logic to decide the debugger console to use:
|
||||||
<li>If step 1 fails then Smack will try to use the enhanced debugger. The
|
<li>If step 1 fails then Smack will try to use the enhanced debugger. The
|
||||||
file <tt>smackx-debug.jar</tt> contains the enhanced debugger. Therefore you will need
|
file <tt>smackx-debug.jar</tt> contains the enhanced debugger. Therefore you will need
|
||||||
to place the jar file in the classpath. For situations where space is an issue you
|
to place the jar file in the classpath. For situations where space is an issue you
|
||||||
may want to only deploy <tt>smack.jar</tt> in which case the enhanced debugger won't be
|
may want to only deploy <tt>smack-core.jar</tt> in which case the enhanced debugger won't be
|
||||||
available.<p>
|
available.<p>
|
||||||
|
|
||||||
<li>The last option if the previous two steps fail is to use the lite debugger. The lite
|
<li>The last option if the previous two steps fail is to use the lite debugger. The lite
|
||||||
|
|
|
@ -15,7 +15,7 @@ tasks such as registration and searching using Forms.
|
||||||
<li><a href="#gather">Create a Form to fill out</a></li>
|
<li><a href="#gather">Create a Form to fill out</a></li>
|
||||||
<li><a href="#fillout">Answer a Form</a></li>
|
<li><a href="#fillout">Answer a Form</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0004.html">JEP-4</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0004.html">XEP-4</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ entities. Follow these links to learn how to use this extension.
|
||||||
<li><a href="#discoinfo">Discover information about an XMPP entity</a></li>
|
<li><a href="#discoinfo">Discover information about an XMPP entity</a></li>
|
||||||
<li><a href="#discopublish">Publish publicly available items</a></li>
|
<li><a href="#discopublish">Publish publicly available items</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0030.html">JEP-30</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0030.html">XEP-30</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,10 @@ The file transfer extension allows the user to transmit and receive files.
|
||||||
<li><a href="#recievefile">Recieving a file from another user</a></li>
|
<li><a href="#recievefile">Recieving a file from another user</a></li>
|
||||||
<li><a href="#monitorprogress">Monitoring the progress of a file transfer</a></li>
|
<li><a href="#monitorprogress">Monitoring the progress of a file transfer</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0095.html">JEP-95</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0095.html">XEP-95</a>
|
||||||
<a href="http://www.jabber.org/jeps/jep-0096.html">JEP-96</a>
|
<a href="http://www.xmpp.org/extensions/xep-0096.html">XEP-96</a>
|
||||||
<a href="http://www.jabber.org/jeps/jep-0065.html">JEP-65</a>
|
<a href="http://www.xmpp.org/extensions/xep-0065.html">XEP-65</a>
|
||||||
<a href="http://www.jabber.org/jeps/jep-0047.html">JEP-47</a>
|
<a href="http://www.xmpp.org/extensions/xep-0047.html">XEP-47</a>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="subheader"><a name="sendfile">Send a file to another user</a></div><p>
|
<div class="subheader"><a name="sendfile">Send a file to another user</a></div><p>
|
||||||
|
|
|
@ -32,17 +32,17 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="messageevents.html">Message Events</a></td>
|
<td><a href="messageevents.html">Message Events</a></td>
|
||||||
<td><a href="http://www.xmpp.org/extensions/xep-0022.html">JEP-0022</a></td>
|
<td><a href="http://www.xmpp.org/extensions/xep-0022.html">XEP-0022</a></td>
|
||||||
<td>Requests and responds to message events.</td>
|
<td>Requests and responds to message events.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="dataforms.html">Data Forms</a></td>
|
<td><a href="dataforms.html">Data Forms</a></td>
|
||||||
<td><a href="http://www.xmpp.org/extensions/xep-0004.html">JEP-0004</a></td>
|
<td><a href="http://www.xmpp.org/extensions/xep-0004.html">XEP-0004</a></td>
|
||||||
<td>Allows to gather data using Forms.</td>
|
<td>Allows to gather data using Forms.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="muc.html">Multi User Chat</a></td>
|
<td><a href="muc.html">Multi User Chat</a></td>
|
||||||
<td><a href="http://www.xmpp.org/extensions/xep-0045.html">JEP-0045</a></td>
|
<td><a href="http://www.xmpp.org/extensions/xep-0045.html">XEP-0045</a></td>
|
||||||
<td>Allows configuration of, participation in, and administration of individual text-based conference rooms.</td>
|
<td>Allows configuration of, participation in, and administration of individual text-based conference rooms.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -17,8 +17,8 @@ users to a group chat room.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>JEP related:</b> N/A -- this protocol is outdated now that the Multi-User Chat (MUC) JEP is available
|
<b>XEP related:</b> N/A -- this protocol is outdated now that the Multi-User Chat (MUC) XEP is available
|
||||||
(<a href="http://www.jabber.org/jeps/jep-0045.html">JEP-45</a>). However, most
|
(<a href="http://www.xmpp.org/extensions/xep-0045.html">XEP-45</a>). However, most
|
||||||
existing clients still use this older protocol. Once MUC support becomes more
|
existing clients still use this older protocol. Once MUC support becomes more
|
||||||
widespread, this API may be deprecated.
|
widespread, this API may be deprecated.
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ display, and composition of messages. There are three stages in this extension:<
|
||||||
<li><a href="#lstevnotreq">Reacting to Event Notification Requests</a></li>
|
<li><a href="#lstevnotreq">Reacting to Event Notification Requests</a></li>
|
||||||
<li><a href="#lstevnot">Reacting to Event Notifications</a></li>
|
<li><a href="#lstevnot">Reacting to Event Notifications</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0022.html">JEP-22</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0022.html">XEP-22</a>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="subheader"><a name="reqevnot">Requesting Event Notifications</a></div><p>
|
<div class="subheader"><a name="reqevnot">Requesting Event Notifications</a></div><p>
|
||||||
<b>Description</b><p>
|
<b>Description</b><p>
|
||||||
|
|
|
@ -22,7 +22,7 @@ Allows configuration of, participation in, and administration of individual text
|
||||||
<li><a href="#role">Manage role modifications</a></li>
|
<li><a href="#role">Manage role modifications</a></li>
|
||||||
<li><a href="#afiliation">Manage affiliation modifications</a></li>
|
<li><a href="#afiliation">Manage affiliation modifications</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0045.html">JEP-45</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0045.html">XEP-45</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ XML namespace. Example private data:
|
||||||
</color>
|
</color>
|
||||||
</pre><p>
|
</pre><p>
|
||||||
|
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0049.html">JEP-49</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0049.html">XEP-49</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ are received from other XMPP clients.
|
||||||
<li><a href="#riesendentry">Send a roster's entry</a></li>
|
<li><a href="#riesendentry">Send a roster's entry</a></li>
|
||||||
<li><a href="#riercventry">Receive roster entries</a></li>
|
<li><a href="#riercventry">Receive roster entries</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0093.html">JEP-93</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0093.html">XEP-93</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
Supports a protocol that XMPP clients use to exchange their respective local
|
Supports a protocol that XMPP clients use to exchange their respective local
|
||||||
times and time zones.<p>
|
times and time zones.<p>
|
||||||
|
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0090.html">JEP-90</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0090.html">XEP-90</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ XHTML messages:</p>
|
||||||
<li><a href="#xhtmlreceive">Receive an XHTML Message</a></li>
|
<li><a href="#xhtmlreceive">Receive an XHTML Message</a></li>
|
||||||
<li><a href="#xhtmldiscover">Discover support for XHTML Messages</a></li>
|
<li><a href="#xhtmldiscover">Discover support for XHTML Messages</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0071.html">JEP-71</a>
|
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0071.html">XEP-71</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ to be as small as possible. The library ships as several JAR files to provide mo
|
||||||
over which features applications require:
|
over which features applications require:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>smack-core.jar</tt> -- provides core XMPP functionality and is the only <b>required</b>
|
<li><tt>smack-core.jar</tt> -- provides core XMPP functionality. All XMPP features that are
|
||||||
library. All XMPP features that are part of the XMPP RFCs are included.</li>
|
part of the XMPP RFCs are included.</li>
|
||||||
<li><tt>smack-extensions.jar</tt> -- support for many of the extensions (XEPs) defined
|
<li><tt>smack-extensions.jar</tt> -- support for many of the extensions (XEPs) defined
|
||||||
by the XMPP Standards Foundation, including multi-user chat, file transfer, user search, etc.
|
by the XMPP Standards Foundation, including multi-user chat, file transfer, user search, etc.
|
||||||
The extensions are documented in the <a href="extensions/index.html">extensions manual</a>.</li>
|
The extensions are documented in the <a href="extensions/index.html">extensions manual</a>.</li>
|
||||||
|
@ -52,7 +52,6 @@ over which features applications require:
|
||||||
is enabled.</li>
|
is enabled.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<p class="subheader">Configuration</p>
|
<p class="subheader">Configuration</p>
|
||||||
Smack has an initialization process that involves 2 phases.
|
Smack has an initialization process that involves 2 phases.
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -28,7 +28,7 @@ Smack Key Advantages
|
||||||
can be accomplished in only a few lines of code:
|
can be accomplished in only a few lines of code:
|
||||||
|
|
||||||
<div class="code"><pre>
|
<div class="code"><pre>
|
||||||
Connection connection = <font color="navy"><b>new</b></font> XMPPConnection(<font color="green">"jabber.org"</font>);
|
XMPPConnection connection = <font color="navy"><b>new</b></font> XMPPTCPConnection(<font color="green">"jabber.org"</font>);
|
||||||
connection.connect();
|
connection.connect();
|
||||||
connection.login(<font color="green">"mtucker"</font>, <font color="green">"password"</font>);
|
connection.login(<font color="green">"mtucker"</font>, <font color="green">"password"</font>);
|
||||||
Chat chat = connection.getChatManager().createChat(<font color="green">"jsmith@jivesoftware.com"</font>, new MessageListener() {
|
Chat chat = connection.getChatManager().createChat(<font color="green">"jsmith@jivesoftware.com"</font>, new MessageListener() {
|
||||||
|
|
|
@ -55,9 +55,9 @@ possible, instructions are provided for both Unix/Linux and Windows users.
|
||||||
<p>
|
<p>
|
||||||
<b><a name="javaSetup">Configure Java</a></b>
|
<b><a name="javaSetup">Configure Java</a></b>
|
||||||
<ul>
|
<ul>
|
||||||
Java 6 (JDK 1.6 or later) must be installed and setup on your machine. To test the installation,
|
A Java Development Kit (JDK) must be installed and setup on your machine. To test the installation,
|
||||||
open a shell in a Unix or a MS-DOS prompt in Windows. Check your version of
|
open a shell in a Unix or a MS-DOS prompt in Windows. Check your version of
|
||||||
Java with "java -version".
|
Java with "javac -version".
|
||||||
If Java isn't installed, download a copy from the
|
If Java isn't installed, download a copy from the
|
||||||
<a href="http://java.oracle.com/">Java website</a>.
|
<a href="http://java.oracle.com/">Java website</a>.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -163,12 +163,11 @@ that can be found in the "documentation" directory included with this distributi
|
||||||
Further information can be found on the <a href="http://www.igniterealtime.org/projects/smack">
|
Further information can be found on the <a href="http://www.igniterealtime.org/projects/smack">
|
||||||
Smack website</a>. If you need help using or would like to make contributions or
|
Smack website</a>. If you need help using or would like to make contributions or
|
||||||
fixes to the code, please visit the
|
fixes to the code, please visit the
|
||||||
<a href="http://www.igniterealtime.org/forum/forum.jspa?forumID=39">online forum</a>.
|
<a href="https://community.igniterealtime.org">online forum</a>.
|
||||||
|
|
||||||
<p><b>About the Distribution</b><p>
|
<p><b>About the Distribution</b><p>
|
||||||
|
|
||||||
The <tt>smack.jar</tt> file in the main distribution folder is the only binary file
|
The <tt>smack-core.jar</tt> file in the main distribution folder. The optional
|
||||||
required for embedding XMPP functionality into client applications. The optional
|
|
||||||
<tt>smack-extensions.jar</tt> contains the <a href="documentation/extensions/index.html">Smack extensions</a>
|
<tt>smack-extensions.jar</tt> contains the <a href="documentation/extensions/index.html">Smack extensions</a>
|
||||||
while <tt>smack-debug.jar</tt> contains an enhanced debugger.<p>
|
while <tt>smack-debug.jar</tt> contains an enhanced debugger.<p>
|
||||||
|
|
||||||
|
@ -176,6 +175,7 @@ while <tt>smack-debug.jar</tt> contains an enhanced debugger.<p>
|
||||||
|
|
||||||
View the <a href="changelog.html">changelog</a> for a list of changes since the
|
View the <a href="changelog.html">changelog</a> for a list of changes since the
|
||||||
last release.
|
last release.
|
||||||
|
If you are upgrading from Smack 3 to Smack 4, then please consult the <a href="https://community.igniterealtime.org/docs/DOC-2703">Smack 4 Readme and Upgrade Guide</a>
|
||||||
|
|
||||||
<p><b>License Agreements</b><p>
|
<p><b>License Agreements</b><p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -141,6 +141,129 @@ hr {
|
||||||
|
|
||||||
<div id="pageBody">
|
<div id="pageBody">
|
||||||
|
|
||||||
|
<h2>4.0.0 -- <span style="font-weight: normal;">2014-06-08</span></h2>
|
||||||
|
|
||||||
|
<h2> Sub-task
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-399'>SMACK-399</a>] - Add support for Roster Versioning (was XEP-0237, now in RFC 6121)
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-400'>SMACK-400</a>] - Change xml-not-well-formed to not-well-formed
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-401'>SMACK-401</a>] - Remove <invalid-id/>
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-445'>SMACK-445</a>] - XMPPError class is based on deprecated XEP-0086
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2> Bug
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-357'>SMACK-357</a>] - Error in SASL authentication when SASL authzid parameter is null
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-410'>SMACK-410</a>] - Any valid SSL server certificate can be used to perform a man-in-the-middle attack
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-411'>SMACK-411</a>] - ServiceDiscoveryManager identities should be non-static and kept in a Set to allow multiple identities as per XEP-30
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-414'>SMACK-414</a>] - Smack does not announce the support for XEP-54 aka vcard-temp
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-427'>SMACK-427</a>] - Typo in code - StreamInitiation.setSesssionID()
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-467'>SMACK-467</a>] - Don't use the default locale for machine-readable output, use Locale.US instead
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-531'>SMACK-531</a>] - Add missing namespace attribute to XHTML-IM body tags
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-533'>SMACK-533</a>] - Smack should prevent IQ response spoofing
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-535'>SMACK-535</a>] - jul.properties should only configure the 'org.igniterealtime' namespace
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-538'>SMACK-538</a>] - ParseRoster does not check the sender of the roster and for pending roster queries
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-541'>SMACK-541</a>] - XHTMLExtensionProvider relies on incorrect behavior of MXParser, violating the contract of the XMLPullParser interface
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-543'>SMACK-543</a>] - packet.Time is not thread-safe
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-546'>SMACK-546</a>] - PubSub's Item needs to escape its XML payload
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-548'>SMACK-548</a>] - PingManager notifies pingFailedListeners multiple times
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-551'>SMACK-551</a>] - ChatManager throws NPE, when Message has no 'from' attribute
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-554'>SMACK-554</a>] - Memory leak in BookmarkManager
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-555'>SMACK-555</a>] - VCardProvider should consider some elements as optional
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-558'>SMACK-558</a>] - connect() must wait until the stream features have been parsed
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-559'>SMACK-559</a>] - Roster entries without a group are not updated
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-560'>SMACK-560</a>] - Race condition in PacketWriter
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-567'>SMACK-567</a>] - XMPPConnection leaks listenerExecutor ExecutorService
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2> Improvement
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-343'>SMACK-343</a>] - Make Smack jar an OSGi bundle.
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-356'>SMACK-356</a>] - There is no way to reliably end a Chat and have a new one created.
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-454'>SMACK-454</a>] - Follow XEP-0170 recommendation: Compression before Resource Binding
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-459'>SMACK-459</a>] - Add option to configure the default identity in ServiceDiscoveryManager
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-465'>SMACK-465</a>] - Replace custom wrapped Throwable in XMPPException with Exception.cause
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-468'>SMACK-468</a>] - Don't throw an IOException in IBBStreams when the stream got closed by the remote
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-536'>SMACK-536</a>] - JUL Loggers should become final
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-537'>SMACK-537</a>] - Move XMPP Ping code to smackx, add keep-alive functionality to PingManager
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-545'>SMACK-545</a>] - Change API to the style mentioned in Smack's Code Guidelines
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-547'>SMACK-547</a>] - Consistent behavior for "from" attribute on outgoing stanzas
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-556'>SMACK-556</a>] - Make ConnectionConfigration getters public
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-557'>SMACK-557</a>] - Provide a MultiUserChat method to create *or* join a room
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-568'>SMACK-568</a>] - Don't exclude groupchat messages without body element in MultiUserChat MessageListeners
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2> New Feature
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-53'>SMACK-53</a>] - Add support for XEP-0092: Software Version
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-71'>SMACK-71</a>] - Create new FromFilter that checks for exact matching
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-187'>SMACK-187</a>] - Add HTTP Binding support (BOSH / XEP-0124)
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-265'>SMACK-265</a>] - Move to a newer build process with artifacts published to maven central repo
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-426'>SMACK-426</a>] - Improve XMPPException
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-544'>SMACK-544</a>] - Add support for XEP-0079: Advanced Message Processing
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-552'>SMACK-552</a>] - Add support for "HTTP over XMPP transport" aka. XEP-0332
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2> Task
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-371'>SMACK-371</a>] - Some MUC tasks are using stanza's as defined in an older version of the spec. Fails to work on some servers.
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-432'>SMACK-432</a>] - Code cleanup of deprecated methods
|
||||||
|
</li>
|
||||||
|
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-446'>SMACK-446</a>] - Remove non-SASL authentication code
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2>3.4.1 -- <span style="font-weight: normal;">Feb 9, 2014</span></h2>
|
<h2>3.4.1 -- <span style="font-weight: normal;">Feb 9, 2014</span></h2>
|
||||||
|
|
||||||
<h2>Bug</h2>
|
<h2>Bug</h2>
|
||||||
|
|
|
@ -4,6 +4,7 @@ include 'smack-core',
|
||||||
'smack-experimental',
|
'smack-experimental',
|
||||||
'smack-debug',
|
'smack-debug',
|
||||||
'smack-resolver-dnsjava',
|
'smack-resolver-dnsjava',
|
||||||
|
'smack-resolver-minidns',
|
||||||
'smack-resolver-javax',
|
'smack-resolver-javax',
|
||||||
'smack-compression-jzlib',
|
'smack-compression-jzlib',
|
||||||
'smack-legacy',
|
'smack-legacy',
|
||||||
|
|
|
@ -35,6 +35,7 @@ task dnsJar(type: Jar) {
|
||||||
from sourceSets.main.output
|
from sourceSets.main.output
|
||||||
include('org/jivesoftware/smack/util/dns/**')
|
include('org/jivesoftware/smack/util/dns/**')
|
||||||
include('org/jivesoftware/smack/util/DNSUtil.class')
|
include('org/jivesoftware/smack/util/DNSUtil.class')
|
||||||
|
include('org/jivesoftware/smack/initializer/**')
|
||||||
}
|
}
|
||||||
|
|
||||||
artifacts {
|
artifacts {
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack;
|
package org.jivesoftware.smack;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -34,6 +36,7 @@ import org.jivesoftware.smack.compression.XMPPInputOutputStream;
|
||||||
import org.jivesoftware.smack.initializer.SmackInitializer;
|
import org.jivesoftware.smack.initializer.SmackInitializer;
|
||||||
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
|
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
|
||||||
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
|
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
|
||||||
|
import org.jivesoftware.smack.util.DNSUtil;
|
||||||
import org.jivesoftware.smack.util.FileUtils;
|
import org.jivesoftware.smack.util.FileUtils;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
@ -49,8 +52,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||||
* via the API will override settings in the configuration file.
|
* via the API will override settings in the configuration file.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* Configuration settings are stored in org.jivesoftware.smack/smack-config.xml (typically inside the
|
* Configuration settings are stored in org.jivesoftware.smack/smack-config.xml.
|
||||||
* smack.jar file).
|
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
|
@ -95,10 +97,13 @@ public final class SmackConfiguration {
|
||||||
static {
|
static {
|
||||||
String smackVersion;
|
String smackVersion;
|
||||||
try {
|
try {
|
||||||
InputStream is = FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null);
|
BufferedReader reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null)));
|
||||||
byte[] buf = new byte[1024];
|
smackVersion = reader.readLine();
|
||||||
is.read(buf);
|
try {
|
||||||
smackVersion = new String(buf, "UTF-8");
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "IOException closing stream", e);
|
||||||
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
|
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
|
||||||
smackVersion = "unkown";
|
smackVersion = "unkown";
|
||||||
|
@ -162,6 +167,9 @@ public final class SmackConfiguration {
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
// Ignore.
|
// Ignore.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the DNS resolvers
|
||||||
|
DNSUtil.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -134,6 +134,12 @@ public class SmackException extends Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConnectionException is thrown if Smack is unable to connect to all hosts of a given XMPP
|
||||||
|
* service. The failed hosts can be retrieved with
|
||||||
|
* {@link ConnectionException#getFailedAddresses()}, which will have the exception causing the
|
||||||
|
* connection failure set and retrievable with {@link HostAddress#getException()}.
|
||||||
|
*/
|
||||||
public static class ConnectionException extends SmackException {
|
public static class ConnectionException extends SmackException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -39,6 +41,31 @@ public class DNSUtil {
|
||||||
private static final Logger LOGGER = Logger.getLogger(DNSUtil.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(DNSUtil.class.getName());
|
||||||
private static DNSResolver dnsResolver = null;
|
private static DNSResolver dnsResolver = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes DNSUtil. This method is automatically called by SmackConfiguration, you don't
|
||||||
|
* have to call it manually.
|
||||||
|
*/
|
||||||
|
public static void init() {
|
||||||
|
final String[] RESOLVERS = new String[] { "javax.JavaxResolver", "minidns.MiniDnsResolver",
|
||||||
|
"dnsjava.DNSJavaResolver" };
|
||||||
|
for (String resolver :RESOLVERS) {
|
||||||
|
DNSResolver availableResolver = null;
|
||||||
|
String resolverFull = "org.jivesoftware.smack.util.dns" + resolver;
|
||||||
|
try {
|
||||||
|
Class<?> resolverClass = Class.forName(resolverFull);
|
||||||
|
Method getInstanceMethod = resolverClass.getMethod("getInstance");
|
||||||
|
availableResolver = (DNSResolver) getInstanceMethod.invoke(null);
|
||||||
|
if (availableResolver != null) {
|
||||||
|
setDNSResolver(availableResolver);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException|NoSuchMethodException|SecurityException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e) {
|
||||||
|
LOGGER.log(Level.FINE, "Exception on init", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the DNS resolver that should be used to perform DNS lookups.
|
* Set the DNS resolver that should be used to perform DNS lookups.
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,13 +22,20 @@ import java.util.List;
|
||||||
public class LazyStringBuilder implements Appendable, CharSequence {
|
public class LazyStringBuilder implements Appendable, CharSequence {
|
||||||
|
|
||||||
private final List<CharSequence> list;
|
private final List<CharSequence> list;
|
||||||
|
|
||||||
|
private String cache;
|
||||||
|
|
||||||
|
private void invalidateCache() {
|
||||||
|
cache = null;
|
||||||
|
}
|
||||||
|
|
||||||
public LazyStringBuilder() {
|
public LazyStringBuilder() {
|
||||||
list = new ArrayList<CharSequence>(20);
|
list = new ArrayList<CharSequence>(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LazyStringBuilder append(LazyStringBuilder lsb) {
|
public LazyStringBuilder append(LazyStringBuilder lsb) {
|
||||||
list.addAll(lsb.list);
|
list.addAll(lsb.list);
|
||||||
|
invalidateCache();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +43,7 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
||||||
public LazyStringBuilder append(CharSequence csq) {
|
public LazyStringBuilder append(CharSequence csq) {
|
||||||
assert csq != null;
|
assert csq != null;
|
||||||
list.add(csq);
|
list.add(csq);
|
||||||
|
invalidateCache();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,17 +51,22 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
||||||
public LazyStringBuilder append(CharSequence csq, int start, int end) {
|
public LazyStringBuilder append(CharSequence csq, int start, int end) {
|
||||||
CharSequence subsequence = csq.subSequence(start, end);
|
CharSequence subsequence = csq.subSequence(start, end);
|
||||||
list.add(subsequence);
|
list.add(subsequence);
|
||||||
|
invalidateCache();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LazyStringBuilder append(char c) {
|
public LazyStringBuilder append(char c) {
|
||||||
list.add(Character.toString(c));
|
list.add(Character.toString(c));
|
||||||
|
invalidateCache();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int length() {
|
public int length() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.length();
|
||||||
|
}
|
||||||
int length = 0;
|
int length = 0;
|
||||||
for (CharSequence csq : list) {
|
for (CharSequence csq : list) {
|
||||||
length += csq.length();
|
length += csq.length();
|
||||||
|
@ -63,6 +76,9 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char charAt(int index) {
|
public char charAt(int index) {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.charAt(index);
|
||||||
|
}
|
||||||
for (CharSequence csq : list) {
|
for (CharSequence csq : list) {
|
||||||
if (index < csq.length()) {
|
if (index < csq.length()) {
|
||||||
return csq.charAt(index);
|
return csq.charAt(index);
|
||||||
|
@ -80,10 +96,13 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder(length());
|
if (cache == null) {
|
||||||
for (CharSequence csq : list) {
|
StringBuilder sb = new StringBuilder(length());
|
||||||
sb.append(csq);
|
for (CharSequence csq : list) {
|
||||||
|
sb.append(csq);
|
||||||
|
}
|
||||||
|
cache = sb.toString();
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,24 @@ public class PacketParserUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new XmlPullParser suitable for parsing XMPP. This means in particular that
|
||||||
|
* FEATURE_PROCESS_NAMESPACES is enabled.
|
||||||
|
* <p>
|
||||||
|
* Note that not all XmlPullParser implementations will return a String on
|
||||||
|
* <code>getText()</code> if the parser is on START_TAG or END_TAG. So you must not rely on this
|
||||||
|
* behavior when using the parser.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return A suitable XmlPullParser for XMPP parsing
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
*/
|
||||||
|
public static XmlPullParser newXmppParser() throws XmlPullParserException {
|
||||||
|
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||||
|
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a message packet.
|
* Parses a message packet.
|
||||||
*
|
*
|
||||||
|
@ -179,7 +197,7 @@ public class PacketParserUtils {
|
||||||
xmlLang = defaultLanguage;
|
xmlLang = defaultLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
String subject = parseContent(parser);
|
String subject = parseElementText(parser);
|
||||||
|
|
||||||
if (message.getSubject(xmlLang) == null) {
|
if (message.getSubject(xmlLang) == null) {
|
||||||
message.addSubject(xmlLang, subject);
|
message.addSubject(xmlLang, subject);
|
||||||
|
@ -191,8 +209,8 @@ public class PacketParserUtils {
|
||||||
xmlLang = defaultLanguage;
|
xmlLang = defaultLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
String body = parseContent(parser);
|
String body = parseElementText(parser);
|
||||||
|
|
||||||
if (message.getBody(xmlLang) == null) {
|
if (message.getBody(xmlLang) == null) {
|
||||||
message.addBody(xmlLang, body);
|
message.addBody(xmlLang, body);
|
||||||
}
|
}
|
||||||
|
@ -223,29 +241,156 @@ public class PacketParserUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the content of a tag as string regardless of any tags included.
|
* Returns the textual content of an element as String.
|
||||||
|
* <p>
|
||||||
|
* The parser must be positioned on a START_TAG of an element which MUST NOT contain Mixed
|
||||||
|
* Content (as defined in XML 3.2.2), or else an XmlPullParserException will be thrown.
|
||||||
|
* </p>
|
||||||
|
* This method is used for the parts where the XMPP specification requires elements that contain
|
||||||
|
* only text or are the empty element.
|
||||||
|
*
|
||||||
|
* @param parser
|
||||||
|
* @return the textual content of the element as String
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
||||||
|
String res;
|
||||||
|
if (parser.isEmptyElementTag()) {
|
||||||
|
res = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Advance to the text of the Element
|
||||||
|
int event = parser.next();
|
||||||
|
if (event != XmlPullParser.TEXT) {
|
||||||
|
throw new XmlPullParserException(
|
||||||
|
"Non-empty element tag not followed by text, while Mixed Content (XML 3.2.2) is disallowed");
|
||||||
|
}
|
||||||
|
res = parser.getText();
|
||||||
|
event = parser.next();
|
||||||
|
if (event != XmlPullParser.END_TAG) {
|
||||||
|
throw new XmlPullParserException(
|
||||||
|
"Non-empty element tag contains child-elements, while Mixed Content (XML 3.2.2) is disallowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current element as string.
|
||||||
|
* <p>
|
||||||
|
* The parser must be positioned on START_TAG.
|
||||||
|
* </p>
|
||||||
|
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
|
||||||
|
*
|
||||||
|
* @param parser the XML pull parser
|
||||||
|
* @return the element as string
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static String parseElement(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
assert(parser.getEventType() == XmlPullParser.START_TAG);
|
||||||
|
return parseContentDepth(parser, parser.getDepth());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content of a element as string.
|
||||||
|
* <p>
|
||||||
|
* The parser must be positioned on the START_TAG of the element which content is going to get
|
||||||
|
* returned. If the current element is the empty element, then the empty string is returned. If
|
||||||
|
* it is a element which contains just text, then just the text is returned. If it contains
|
||||||
|
* nested elements (and text), then everything from the current opening tag to the corresponding
|
||||||
|
* closing tag of the same depth is returned as String.
|
||||||
|
* </p>
|
||||||
|
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
|
||||||
*
|
*
|
||||||
* @param parser the XML pull parser
|
* @param parser the XML pull parser
|
||||||
* @return the content of a tag as string
|
* @return the content of a tag as string
|
||||||
* @throws XmlPullParserException if parser encounters invalid XML
|
* @throws XmlPullParserException if parser encounters invalid XML
|
||||||
* @throws IOException if an IO error occurs
|
* @throws IOException if an IO error occurs
|
||||||
*/
|
*/
|
||||||
private static String parseContent(XmlPullParser parser)
|
public static String parseContent(XmlPullParser parser)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
int parserDepth = parser.getDepth();
|
assert(parser.getEventType() == XmlPullParser.START_TAG);
|
||||||
return parseContentDepth(parser, parserDepth);
|
if (parser.isEmptyElementTag()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// Advance the parser, since we want to parse the content of the current element
|
||||||
|
parser.next();
|
||||||
|
return parseContentDepth(parser, parser.getDepth());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content from the current position of the parser up to the closing tag of the
|
||||||
|
* given depth. Note that only the outermost namespace attributes ("xmlns") will be returned,
|
||||||
|
* not nested ones.
|
||||||
|
* <p>
|
||||||
|
* This method is able to parse the content with MX- and KXmlParser. In order to achieve
|
||||||
|
* this some trade-off has to be make, because KXmlParser does not support xml-roundtrip (ie.
|
||||||
|
* return a String on getText() on START_TAG and END_TAG). We are therefore required to work
|
||||||
|
* around this limitation, which results in only partial support for XML namespaces ("xmlns"):
|
||||||
|
* Only the outermost namespace of elements will be included in the resulting String.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param parser
|
||||||
|
* @param depth
|
||||||
|
* @return the content of the current depth
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public static String parseContentDepth(XmlPullParser parser, int depth) throws XmlPullParserException, IOException {
|
public static String parseContentDepth(XmlPullParser parser, int depth) throws XmlPullParserException, IOException {
|
||||||
StringBuilder content = new StringBuilder();
|
XmlStringBuilder xml = new XmlStringBuilder();
|
||||||
while (!(parser.next() == XmlPullParser.END_TAG && parser.getDepth() == depth)) {
|
int event = parser.getEventType();
|
||||||
String text = parser.getText();
|
boolean isEmptyElement = false;
|
||||||
if (text == null) {
|
// XmlPullParser reports namespaces in nested elements even if *only* the outer ones defines
|
||||||
throw new IllegalStateException("Parser should never return 'null' on getText() here");
|
// it. This 'flag' ensures that when a namespace is set for an element, it won't be set again
|
||||||
|
// in a nested element. It's an ugly workaround that has the potential to break things.
|
||||||
|
String namespaceElement = null;;
|
||||||
|
while (true) {
|
||||||
|
if (event == XmlPullParser.START_TAG) {
|
||||||
|
xml.halfOpenElement(parser.getName());
|
||||||
|
if (namespaceElement == null) {
|
||||||
|
String namespace = parser.getNamespace();
|
||||||
|
if (StringUtils.isNotEmpty(namespace)) {
|
||||||
|
xml.attribute("xmlns", namespace);
|
||||||
|
namespaceElement = parser.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||||
|
xml.attribute(parser.getAttributeName(i), parser.getAttributeValue(i));
|
||||||
|
}
|
||||||
|
if (parser.isEmptyElementTag()) {
|
||||||
|
xml.closeEmptyElement();
|
||||||
|
isEmptyElement = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xml.rightAngelBracket();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
content.append(text);
|
else if (event == XmlPullParser.END_TAG) {
|
||||||
|
if (isEmptyElement) {
|
||||||
|
// Do nothing as the element was already closed, just reset the flag
|
||||||
|
isEmptyElement = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xml.closeElement(parser.getName());
|
||||||
|
}
|
||||||
|
if (namespaceElement != null && namespaceElement.equals(parser.getName())) {
|
||||||
|
// We are on the closing tag, which defined the namespace as starting tag, reset the 'flag'
|
||||||
|
namespaceElement = null;
|
||||||
|
}
|
||||||
|
if (parser.getDepth() <= depth) {
|
||||||
|
// Abort parsing, we are done
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event == XmlPullParser.TEXT) {
|
||||||
|
xml.append(parser.getText());
|
||||||
|
}
|
||||||
|
event = parser.next();
|
||||||
}
|
}
|
||||||
return content.toString();
|
return xml.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -174,6 +174,25 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XmlStringBuilder emptyElement(String element) {
|
||||||
|
halfOpenElement(element);
|
||||||
|
return closeEmptyElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlStringBuilder condEmptyElement(boolean condition, String element) {
|
||||||
|
if (condition) {
|
||||||
|
emptyElement(element);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlStringBuilder condAttribute(boolean condition, String name, String value) {
|
||||||
|
if (condition) {
|
||||||
|
attribute(name, value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XmlStringBuilder append(CharSequence csq) {
|
public XmlStringBuilder append(CharSequence csq) {
|
||||||
assert csq != null;
|
assert csq != null;
|
||||||
|
@ -213,4 +232,18 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (!(other instanceof XmlStringBuilder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
XmlStringBuilder otherXmlStringBuilder = (XmlStringBuilder) other;
|
||||||
|
return toString().equals(otherXmlStringBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return toString().hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2013 Florian Schmaus
|
* Copyright © 2013-2014 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,9 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util.dns;
|
package org.jivesoftware.smack.util.dns;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException.ConnectionException;
|
||||||
|
|
||||||
public class HostAddress {
|
public class HostAddress {
|
||||||
private String fqdn;
|
private final String fqdn;
|
||||||
private int port;
|
private final int port;
|
||||||
private Exception exception;
|
private Exception exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,16 +30,8 @@ public class HostAddress {
|
||||||
* @throws IllegalArgumentException If the fqdn is null.
|
* @throws IllegalArgumentException If the fqdn is null.
|
||||||
*/
|
*/
|
||||||
public HostAddress(String fqdn) {
|
public HostAddress(String fqdn) {
|
||||||
if (fqdn == null)
|
|
||||||
throw new IllegalArgumentException("FQDN is null");
|
|
||||||
if (fqdn.charAt(fqdn.length() - 1) == '.') {
|
|
||||||
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.fqdn = fqdn;
|
|
||||||
}
|
|
||||||
// Set port to the default port for XMPP client communication
|
// Set port to the default port for XMPP client communication
|
||||||
this.port = 5222;
|
this(fqdn, 5222);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,11 +42,17 @@ public class HostAddress {
|
||||||
* @throws IllegalArgumentException If the fqdn is null or port is out of valid range (0 - 65535).
|
* @throws IllegalArgumentException If the fqdn is null or port is out of valid range (0 - 65535).
|
||||||
*/
|
*/
|
||||||
public HostAddress(String fqdn, int port) {
|
public HostAddress(String fqdn, int port) {
|
||||||
this(fqdn);
|
if (fqdn == null)
|
||||||
|
throw new IllegalArgumentException("FQDN is null");
|
||||||
if (port < 0 || port > 65535)
|
if (port < 0 || port > 65535)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port);
|
"Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port);
|
||||||
|
if (fqdn.charAt(fqdn.length() - 1) == '.') {
|
||||||
|
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.fqdn = fqdn;
|
||||||
|
}
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,17 @@ public class HostAddress {
|
||||||
this.exception = e;
|
this.exception = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the Exception that caused a connection failure to this HostAddress. Every
|
||||||
|
* HostAddress found in {@link ConnectionException} will have an Exception set,
|
||||||
|
* which can be retrieved with this method.
|
||||||
|
*
|
||||||
|
* @return the Exception causing this HostAddress to fail
|
||||||
|
*/
|
||||||
|
public Exception getException() {
|
||||||
|
return this.exception;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return fqdn + ":" + port;
|
return fqdn + ":" + port;
|
||||||
|
|
|
@ -19,7 +19,6 @@ package org.jivesoftware.smack;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
@ -31,11 +30,11 @@ import org.jivesoftware.smack.packet.RosterPacket;
|
||||||
import org.jivesoftware.smack.packet.IQ.Type;
|
import org.jivesoftware.smack.packet.IQ.Type;
|
||||||
import org.jivesoftware.smack.packet.RosterPacket.Item;
|
import org.jivesoftware.smack.packet.RosterPacket.Item;
|
||||||
import org.jivesoftware.smack.packet.RosterPacket.ItemType;
|
import org.jivesoftware.smack.packet.RosterPacket.ItemType;
|
||||||
|
import org.jivesoftware.smack.test.util.TestUtils;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,8 +314,6 @@ public class RosterTest {
|
||||||
final String contactJID = "nurse@example.com";
|
final String contactJID = "nurse@example.com";
|
||||||
final Roster roster = connection.getRoster();
|
final Roster roster = connection.getRoster();
|
||||||
assertNotNull("Can't get the roster from the provided connection!", roster);
|
assertNotNull("Can't get the roster from the provided connection!", roster);
|
||||||
final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append("<iq id=\"rostertest1\" type=\"set\" ")
|
sb.append("<iq id=\"rostertest1\" type=\"set\" ")
|
||||||
.append("to=\"").append(connection.getUser()).append("\">")
|
.append("to=\"").append(connection.getUser()).append("\">")
|
||||||
|
@ -324,8 +321,7 @@ public class RosterTest {
|
||||||
.append("<item jid=\"").append(contactJID).append("\"/>")
|
.append("<item jid=\"").append(contactJID).append("\"/>")
|
||||||
.append("</query>")
|
.append("</query>")
|
||||||
.append("</iq>");
|
.append("</iq>");
|
||||||
parser.setInput(new StringReader(sb.toString()));
|
final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
|
||||||
parser.next();
|
|
||||||
final IQ rosterPush = PacketParserUtils.parseIQ(parser, connection);
|
final IQ rosterPush = PacketParserUtils.parseIQ(parser, connection);
|
||||||
initRoster(connection, roster);
|
initRoster(connection, roster);
|
||||||
rosterListener.reset();
|
rosterListener.reset();
|
||||||
|
@ -449,8 +445,6 @@ public class RosterTest {
|
||||||
final String contactJID = "nurse@example.com";
|
final String contactJID = "nurse@example.com";
|
||||||
final Roster roster = connection.getRoster();
|
final Roster roster = connection.getRoster();
|
||||||
assertNotNull("Can't get the roster from the provided connection!", roster);
|
assertNotNull("Can't get the roster from the provided connection!", roster);
|
||||||
final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append("<iq id=\"rostertest2\" type=\"set\" ")
|
sb.append("<iq id=\"rostertest2\" type=\"set\" ")
|
||||||
.append("to=\"").append(connection.getUser()).append("\">")
|
.append("to=\"").append(connection.getUser()).append("\">")
|
||||||
|
@ -460,8 +454,7 @@ public class RosterTest {
|
||||||
.append("</item>")
|
.append("</item>")
|
||||||
.append("</query>")
|
.append("</query>")
|
||||||
.append("</iq>");
|
.append("</iq>");
|
||||||
parser.setInput(new StringReader(sb.toString()));
|
final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
|
||||||
parser.next();
|
|
||||||
final IQ rosterPush = PacketParserUtils.parseIQ(parser, connection);
|
final IQ rosterPush = PacketParserUtils.parseIQ(parser, connection);
|
||||||
initRoster(connection, roster);
|
initRoster(connection, roster);
|
||||||
rosterListener.reset();
|
rosterListener.reset();
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
import org.jivesoftware.smack.provider.ProviderManager;
|
import org.jivesoftware.smack.provider.ProviderManager;
|
||||||
|
import org.jivesoftware.smack.test.util.TestUtils;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -34,7 +35,7 @@ public class ParsingExceptionTest {
|
||||||
private final static String EXTENSION2 =
|
private final static String EXTENSION2 =
|
||||||
"<extension2 xmlns='namespace'>" +
|
"<extension2 xmlns='namespace'>" +
|
||||||
"<bar node='testNode'>" +
|
"<bar node='testNode'>" +
|
||||||
"<i id='testid1' >" +
|
"<i id='testid1'>" +
|
||||||
"</i>" +
|
"</i>" +
|
||||||
"</bar>" +
|
"</bar>" +
|
||||||
"</extension2>";
|
"</extension2>";
|
||||||
|
@ -51,12 +52,14 @@ public class ParsingExceptionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void consumeUnparsedInput() throws Exception {
|
public void consumeUnparsedInput() throws Exception {
|
||||||
XmlPullParser parser = PacketParserUtils.getParserFor(
|
final String MESSAGE_EXCEPTION_ELEMENT =
|
||||||
|
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
|
||||||
|
"<nothingInHere>" +
|
||||||
|
"</nothingInHere>" +
|
||||||
|
"</" + ThrowException.ELEMENT + ">";
|
||||||
|
XmlPullParser parser = TestUtils.getMessageParser(
|
||||||
"<message from='user@server.example' to='francisco@denmark.lit' id='foo'>" +
|
"<message from='user@server.example' to='francisco@denmark.lit' id='foo'>" +
|
||||||
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
|
MESSAGE_EXCEPTION_ELEMENT +
|
||||||
"<nothingInHere>" +
|
|
||||||
"</nothingInHere>" +
|
|
||||||
"</" + ThrowException.ELEMENT + ">" +
|
|
||||||
EXTENSION2 +
|
EXTENSION2 +
|
||||||
"</message>");
|
"</message>");
|
||||||
int parserDepth = parser.getDepth();
|
int parserDepth = parser.getDepth();
|
||||||
|
@ -67,8 +70,7 @@ public class ParsingExceptionTest {
|
||||||
content = PacketParserUtils.parseContentDepth(parser, parserDepth);
|
content = PacketParserUtils.parseContentDepth(parser, parserDepth);
|
||||||
}
|
}
|
||||||
assertNotNull(content);
|
assertNotNull(content);
|
||||||
assertEquals(content, "<nothingInHere></nothingInHere>" + "</" + ThrowException.ELEMENT + ">" + EXTENSION2);
|
assertEquals(MESSAGE_EXCEPTION_ELEMENT + EXTENSION2 + "</message>", content);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ThrowException implements PacketExtensionProvider {
|
static class ThrowException implements PacketExtensionProvider {
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2013 Robin Collier
|
||||||
|
*
|
||||||
|
* 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.test.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
final public class TestUtils {
|
||||||
|
private TestUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlPullParser getIQParser(String stanza) {
|
||||||
|
return getParser(stanza, "iq");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlPullParser getMessageParser(String stanza) {
|
||||||
|
return getParser(stanza, "message");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlPullParser getPresenceParser(String stanza) {
|
||||||
|
return getParser(stanza, "presence");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlPullParser getParser(String string, String startTag) {
|
||||||
|
return getParser(new StringReader(string), startTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlPullParser getParser(Reader reader, String startTag) {
|
||||||
|
XmlPullParser parser;
|
||||||
|
try {
|
||||||
|
parser = PacketParserUtils.newXmppParser();
|
||||||
|
parser.setInput(reader);
|
||||||
|
if (startTag == null) {
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
while (!found) {
|
||||||
|
if ((parser.next() == XmlPullParser.START_TAG) && parser.getName().equals(startTag))
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
throw new IllegalArgumentException("Can not find start tag '" + startTag + "'");
|
||||||
|
} catch (XmlPullParserException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,12 +27,12 @@ import static org.junit.Assert.fail;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.custommonkey.xmlunit.DetailedDiff;
|
|
||||||
import org.custommonkey.xmlunit.Diff;
|
import org.custommonkey.xmlunit.Diff;
|
||||||
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
|
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
import org.jivesoftware.smack.packet.Presence;
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
|
import org.jivesoftware.smack.test.util.TestUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
@ -653,7 +653,13 @@ public class PacketParserUtilsTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
/**
|
||||||
|
* RFC6121 5.2.3 explicitly disallows mixed content in <body/> elements. Make sure that we throw
|
||||||
|
* an exception if we encounter such an element.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test(expected=XmlPullParserException.class)
|
||||||
public void invalidMessageBodyContainingTagTest() throws Exception {
|
public void invalidMessageBodyContainingTagTest() throws Exception {
|
||||||
String control = XMLBuilder.create("message")
|
String control = XMLBuilder.create("message")
|
||||||
.a("from", "romeo@montague.lit/orchard")
|
.a("from", "romeo@montague.lit/orchard")
|
||||||
|
@ -667,23 +673,10 @@ public class PacketParserUtilsTest {
|
||||||
.a("style", "font-weight: bold;")
|
.a("style", "font-weight: bold;")
|
||||||
.t("Bad Message Body")
|
.t("Bad Message Body")
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
try {
|
Message message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
Message message = (Message) PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
|
||||||
String body = "<span style=\"font-weight: bold;\">"
|
fail("Should throw exception. Instead got message: " + message.toXML().toString());
|
||||||
+ "Bad Message Body</span>";
|
|
||||||
assertEquals(body, message.getBody());
|
|
||||||
|
|
||||||
assertXMLNotEqual(control, message.toXML().toString());
|
|
||||||
|
|
||||||
DetailedDiff diffs = new DetailedDiff(new Diff(control, message.toXML().toString()));
|
|
||||||
|
|
||||||
// body has no namespace URI, span is escaped
|
|
||||||
assertEquals(6, diffs.getAllDifferences().size());
|
|
||||||
} catch(XmlPullParserException e) {
|
|
||||||
fail("No parser exception should be thrown" + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -792,8 +785,8 @@ public class PacketParserUtilsTest {
|
||||||
@Test
|
@Test
|
||||||
public void parseContentDepthTest() throws Exception {
|
public void parseContentDepthTest() throws Exception {
|
||||||
final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
|
final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
|
||||||
XmlPullParser parser = PacketParserUtils.getParserFor(stanza, "iq");
|
XmlPullParser parser = TestUtils.getParser(stanza, "iq");
|
||||||
String content = PacketParserUtils.parseContentDepth(parser, 1);
|
String content = PacketParserUtils.parseContent(parser);
|
||||||
assertEquals("", content);
|
assertEquals("", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.jivesoftware.smack.test.SmackTestCase;
|
||||||
import org.jivesoftware.smackx.packet.Version;
|
import org.jivesoftware.smackx.packet.Version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that stream compression (JEP-138) is correctly supported by Smack.
|
* Ensure that stream compression (XEP-138) is correctly supported by Smack.
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that JEP-33 support in Smack is correct.
|
* Tests that XEP-33 support in Smack is correct.
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,7 +32,7 @@ import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests handling of offline messaging using OfflineMessageManager. This server requires the
|
* Tests handling of offline messaging using OfflineMessageManager. This server requires the
|
||||||
* server to support JEP-0013: Flexible Offline Message Retrieval.
|
* server to support XEP-0013: Flexible Offline Message Retrieval.
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
|
@ -44,7 +44,7 @@ public class OfflineMessageManagerTest extends SmackTestCase {
|
||||||
|
|
||||||
public void testDiscoverFlexibleRetrievalSupport() throws XMPPException {
|
public void testDiscoverFlexibleRetrievalSupport() throws XMPPException {
|
||||||
OfflineMessageManager offlineManager = new OfflineMessageManager(getConnection(1));
|
OfflineMessageManager offlineManager = new OfflineMessageManager(getConnection(1));
|
||||||
assertTrue("Server does not support JEP-13", offlineManager.supportsFlexibleRetrieval());
|
assertTrue("Server does not support XEP-13", offlineManager.supportsFlexibleRetrieval());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,7 +40,7 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MultipleRecipientManager allows to send packets to multiple recipients by making use of
|
* A MultipleRecipientManager allows to send packets to multiple recipients by making use of
|
||||||
* <a href="http://www.jabber.org/jeps/jep-0033.html">JEP-33: Extended Stanza Addressing</a>.
|
* <a href="http://www.xmpp.org/extensions/jep-0033.html">XEP-33: Extended Stanza Addressing</a>.
|
||||||
* It also allows to send replies to packets that were sent to multiple recipients.
|
* It also allows to send replies to packets that were sent to multiple recipients.
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
|
@ -57,9 +57,9 @@ public class MultipleRecipientManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the specified packet to the list of specified recipients using the
|
* Sends the specified packet to the list of specified recipients using the
|
||||||
* specified connection. If the server has support for JEP-33 then only one
|
* specified connection. If the server has support for XEP-33 then only one
|
||||||
* packet is going to be sent to the server with the multiple recipient instructions.
|
* packet is going to be sent to the server with the multiple recipient instructions.
|
||||||
* However, if JEP-33 is not supported by the server then the client is going to send
|
* However, if XEP-33 is not supported by the server then the client is going to send
|
||||||
* the packet to each recipient.
|
* the packet to each recipient.
|
||||||
*
|
*
|
||||||
* @param connection the connection to use to send the packet.
|
* @param connection the connection to use to send the packet.
|
||||||
|
@ -72,8 +72,8 @@ public class MultipleRecipientManager {
|
||||||
* list exists.
|
* list exists.
|
||||||
* @throws FeatureNotSupportedException if special XEP-33 features where requested, but the
|
* @throws FeatureNotSupportedException if special XEP-33 features where requested, but the
|
||||||
* server does not support them.
|
* server does not support them.
|
||||||
* @throws XMPPErrorException if server does not support JEP-33: Extended Stanza Addressing and
|
* @throws XMPPErrorException if server does not support XEP-33: Extended Stanza Addressing and
|
||||||
* some JEP-33 specific features were requested.
|
* some XEP-33 specific features were requested.
|
||||||
* @throws NoResponseException if there was no response from the server.
|
* @throws NoResponseException if there was no response from the server.
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
*/
|
*/
|
||||||
|
@ -84,8 +84,8 @@ public class MultipleRecipientManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the specified packet to the list of specified recipients using the specified
|
* Sends the specified packet to the list of specified recipients using the specified
|
||||||
* connection. If the server has support for JEP-33 then only one packet is going to be sent to
|
* connection. If the server has support for XEP-33 then only one packet is going to be sent to
|
||||||
* the server with the multiple recipient instructions. However, if JEP-33 is not supported by
|
* the server with the multiple recipient instructions. However, if XEP-33 is not supported by
|
||||||
* the server then the client is going to send the packet to each recipient.
|
* the server then the client is going to send the packet to each recipient.
|
||||||
*
|
*
|
||||||
* @param connection the connection to use to send the packet.
|
* @param connection the connection to use to send the packet.
|
||||||
|
@ -99,8 +99,8 @@ public class MultipleRecipientManager {
|
||||||
* @param replyRoom JID of a MUC room to which responses should be sent or <tt>null</tt>
|
* @param replyRoom JID of a MUC room to which responses should be sent or <tt>null</tt>
|
||||||
* indicating that they can reply to any address.
|
* indicating that they can reply to any address.
|
||||||
* @param noReply true means that receivers should not reply to the message.
|
* @param noReply true means that receivers should not reply to the message.
|
||||||
* @throws XMPPErrorException if server does not support JEP-33: Extended Stanza Addressing and
|
* @throws XMPPErrorException if server does not support XEP-33: Extended Stanza Addressing and
|
||||||
* some JEP-33 specific features were requested.
|
* some XEP-33 specific features were requested.
|
||||||
* @throws NoResponseException if there was no response from the server.
|
* @throws NoResponseException if there was no response from the server.
|
||||||
* @throws FeatureNotSupportedException if special XEP-33 features where requested, but the
|
* @throws FeatureNotSupportedException if special XEP-33 features where requested, but the
|
||||||
* server does not support them.
|
* server does not support them.
|
||||||
|
@ -115,10 +115,10 @@ public class MultipleRecipientManager {
|
||||||
serviceAddress);
|
serviceAddress);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Server does not support JEP-33 so try to send the packet to each recipient
|
// Server does not support XEP-33 so try to send the packet to each recipient
|
||||||
if (noReply || (replyTo != null && replyTo.trim().length() > 0) ||
|
if (noReply || (replyTo != null && replyTo.trim().length() > 0) ||
|
||||||
(replyRoom != null && replyRoom.trim().length() > 0)) {
|
(replyRoom != null && replyRoom.trim().length() > 0)) {
|
||||||
// Some specified JEP-33 features were requested so throw an exception alerting
|
// Some specified XEP-33 features were requested so throw an exception alerting
|
||||||
// the user that this features are not available
|
// the user that this features are not available
|
||||||
throw new FeatureNotSupportedException("Extended Stanza Addressing");
|
throw new FeatureNotSupportedException("Extended Stanza Addressing");
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ public class MultipleRecipientManager {
|
||||||
serviceAddress);
|
serviceAddress);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Server does not support JEP-33 so try to send the packet to each recipient
|
// Server does not support XEP-33 so try to send the packet to each recipient
|
||||||
sendToIndividualRecipients(connection, reply, to, cc, null);
|
sendToIndividualRecipients(connection, reply, to, cc, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@ import org.jivesoftware.smackx.iqprivate.PrivateDataManager;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides methods to manage bookmarks in accordance with JEP-0048. Methods for managing URLs and
|
* Provides methods to manage bookmarks in accordance with XEP-0048. Methods for managing URLs and
|
||||||
* Conferences are provided.
|
* Conferences are provided.
|
||||||
* </p>
|
* </p>
|
||||||
* It should be noted that some extensions have been made to the JEP. There is an attribute on URLs
|
* It should be noted that some extensions have been made to the XEP. There is an attribute on URLs
|
||||||
* that marks a url as a news feed and also a sub-element can be added to either a URL or conference
|
* that marks a url as a news feed and also a sub-element can be added to either a URL or conference
|
||||||
* indicated that it is shared amongst all users on a server.
|
* indicated that it is shared amongst all users on a server.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.jivesoftware.smackx.bookmarks;
|
package org.jivesoftware.smackx.bookmarks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Respresents a Conference Room bookmarked on the server using JEP-0048 Bookmark Storage JEP.
|
* Respresents a Conference Room bookmarked on the server using XEP-0048 Bookmark Storage XEP.
|
||||||
*
|
*
|
||||||
* @author Derek DeMoro
|
* @author Derek DeMoro
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.jivesoftware.smackx.bookmarks;
|
package org.jivesoftware.smackx.bookmarks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Respresents one instance of a URL defined using JEP-0048 Bookmark Storage JEP.
|
* Respresents one instance of a URL defined using XEP-0048 Bookmark Storage XEP.
|
||||||
*
|
*
|
||||||
* @author Derek DeMoro
|
* @author Derek DeMoro
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.bookmarks;
|
package org.jivesoftware.smackx.bookmarks;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
import org.jivesoftware.smackx.iqprivate.packet.PrivateData;
|
import org.jivesoftware.smackx.iqprivate.packet.PrivateData;
|
||||||
import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider;
|
import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
@ -27,7 +28,7 @@ import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bookmarks is used for storing and retrieving URLS and Conference rooms.
|
* Bookmarks is used for storing and retrieving URLS and Conference rooms.
|
||||||
* Bookmark Storage (JEP-0048) defined a protocol for the storage of bookmarks to conference rooms and other entities
|
* Bookmark Storage (XEP-0048) defined a protocol for the storage of bookmarks to conference rooms and other entities
|
||||||
* in a Jabber user's account.
|
* in a Jabber user's account.
|
||||||
* See the following code sample for saving Bookmarks:
|
* See the following code sample for saving Bookmarks:
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -59,6 +60,9 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class Bookmarks implements PrivateData {
|
public class Bookmarks implements PrivateData {
|
||||||
|
|
||||||
|
public static final String NAMESPACE = "storage:bookmarks";
|
||||||
|
public static final String ELEMENT = "storage";
|
||||||
|
|
||||||
private List<BookmarkedURL> bookmarkedURLS;
|
private List<BookmarkedURL> bookmarkedURLS;
|
||||||
private List<BookmarkedConference> bookmarkedConferences;
|
private List<BookmarkedConference> bookmarkedConferences;
|
||||||
|
|
||||||
|
@ -145,7 +149,7 @@ public class Bookmarks implements PrivateData {
|
||||||
* @return the element name.
|
* @return the element name.
|
||||||
*/
|
*/
|
||||||
public String getElementName() {
|
public String getElementName() {
|
||||||
return "storage";
|
return ELEMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,28 +158,26 @@ public class Bookmarks implements PrivateData {
|
||||||
* @return the namespace.
|
* @return the namespace.
|
||||||
*/
|
*/
|
||||||
public String getNamespace() {
|
public String getNamespace() {
|
||||||
return "storage:bookmarks";
|
return NAMESPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the XML reppresentation of the PrivateData.
|
* Returns the XML representation of the PrivateData.
|
||||||
*
|
*
|
||||||
* @return the private data as XML.
|
* @return the private data as XML.
|
||||||
*/
|
*/
|
||||||
public String toXML() {
|
@Override
|
||||||
StringBuilder buf = new StringBuilder();
|
public XmlStringBuilder toXML() {
|
||||||
buf.append("<storage xmlns=\"storage:bookmarks\">");
|
XmlStringBuilder buf = new XmlStringBuilder();
|
||||||
|
buf.openElement(ELEMENT).xmlnsAttribute(NAMESPACE);
|
||||||
|
|
||||||
for (BookmarkedURL urlStorage : getBookmarkedURLS()) {
|
for (BookmarkedURL urlStorage : getBookmarkedURLS()) {
|
||||||
if(urlStorage.isShared()) {
|
if(urlStorage.isShared()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
buf.append("<url name=\"").append(urlStorage.getName()).
|
buf.openElement("url").attribute("name", urlStorage.getName()).attribute("url", urlStorage.getURL());
|
||||||
append("\" url=\"").append(urlStorage.getURL()).append("\"");
|
buf.condAttribute(urlStorage.isRss(), "rss", "true");
|
||||||
if(urlStorage.isRss()) {
|
buf.closeEmptyElement();
|
||||||
buf.append(" rss=\"").append(true).append("\"");
|
|
||||||
}
|
|
||||||
buf.append(" />");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Conference additions
|
// Add Conference additions
|
||||||
|
@ -183,26 +185,20 @@ public class Bookmarks implements PrivateData {
|
||||||
if(conference.isShared()) {
|
if(conference.isShared()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
buf.append("<conference ");
|
buf.openElement("conference");
|
||||||
buf.append("name=\"").append(conference.getName()).append("\" ");
|
buf.attribute("name", conference.getName());
|
||||||
buf.append("autojoin=\"").append(conference.isAutoJoin()).append("\" ");
|
buf.attribute("autojoin", Boolean.toString(conference.isAutoJoin()));
|
||||||
buf.append("jid=\"").append(conference.getJid()).append("\" ");
|
buf.attribute("jid", conference.getJid());
|
||||||
buf.append(">");
|
buf.rightAngelBracket();
|
||||||
|
|
||||||
if (conference.getNickname() != null) {
|
buf.optElement("nick", conference.getNickname());
|
||||||
buf.append("<nick>").append(conference.getNickname()).append("</nick>");
|
buf.optElement("password", conference.getPassword());
|
||||||
}
|
|
||||||
|
|
||||||
|
buf.closeElement("conference");
|
||||||
if (conference.getPassword() != null) {
|
|
||||||
buf.append("<password>").append(conference.getPassword()).append("</password>");
|
|
||||||
}
|
|
||||||
buf.append("</conference>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf.closeElement(ELEMENT);
|
||||||
buf.append("</storage>");
|
return buf;
|
||||||
return buf.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item;
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item;
|
||||||
import org.jivesoftware.smackx.xdata.Form;
|
|
||||||
import org.jivesoftware.smackx.xdata.FormField;
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
|
@ -536,7 +535,7 @@ public class EntityCapsManager extends Manager {
|
||||||
protected static boolean verifyPacketExtensions(DiscoverInfo info) {
|
protected static boolean verifyPacketExtensions(DiscoverInfo info) {
|
||||||
List<FormField> foundFormTypes = new LinkedList<FormField>();
|
List<FormField> foundFormTypes = new LinkedList<FormField>();
|
||||||
for (PacketExtension pe : info.getExtensions()) {
|
for (PacketExtension pe : info.getExtensions()) {
|
||||||
if (pe.getNamespace().equals(Form.NAMESPACE)) {
|
if (pe.getNamespace().equals(DataForm.NAMESPACE)) {
|
||||||
DataForm df = (DataForm) pe;
|
DataForm df = (DataForm) pe;
|
||||||
for (FormField f : df.getFields()) {
|
for (FormField f : df.getFields()) {
|
||||||
if (f.getVariable().equals("FORM_TYPE")) {
|
if (f.getVariable().equals("FORM_TYPE")) {
|
||||||
|
@ -569,7 +568,7 @@ public class EntityCapsManager extends Manager {
|
||||||
if (md == null)
|
if (md == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
DataForm extendedInfo = (DataForm) discoverInfo.getExtension(Form.ELEMENT, Form.NAMESPACE);
|
DataForm extendedInfo = (DataForm) discoverInfo.getExtension(DataForm.ELEMENT, DataForm.NAMESPACE);
|
||||||
|
|
||||||
// 1. Initialize an empty string S ('sb' in this method).
|
// 1. Initialize an empty string S ('sb' in this method).
|
||||||
StringBuilder sb = new StringBuilder(); // Use StringBuilder as we don't
|
StringBuilder sb = new StringBuilder(); // Use StringBuilder as we don't
|
||||||
|
|
|
@ -43,7 +43,7 @@ import org.jivesoftware.smackx.xdata.FormField;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the negotiation of file transfers according to JEP-0096. If a file is
|
* Manages the negotiation of file transfers according to XEP-0096. If a file is
|
||||||
* being sent the remote user chooses the type of stream under which the file
|
* being sent the remote user chooses the type of stream under which the file
|
||||||
* will be sent.
|
* will be sent.
|
||||||
*
|
*
|
||||||
|
@ -287,13 +287,13 @@ public class FileTransferNegotiator extends Manager {
|
||||||
* If they accept, the packet will contain the other user's chosen stream
|
* If they accept, the packet will contain the other user's chosen stream
|
||||||
* type to send the file across. The two choices this implementation
|
* type to send the file across. The two choices this implementation
|
||||||
* provides to the other user for file transfer are <a
|
* provides to the other user for file transfer are <a
|
||||||
* href="http://www.jabber.org/jeps/jep-0065.html">SOCKS5 Bytestreams</a>,
|
* href="http://www.xmpp.org/extensions/jep-0065.html">SOCKS5 Bytestreams</a>,
|
||||||
* which is the preferred method of transfer, and <a
|
* which is the preferred method of transfer, and <a
|
||||||
* href="http://www.jabber.org/jeps/jep-0047.html">In-Band Bytestreams</a>,
|
* href="http://www.xmpp.org/extensions/jep-0047.html">In-Band Bytestreams</a>,
|
||||||
* which is the fallback mechanism.
|
* which is the fallback mechanism.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The other user may choose to decline the file request if they do not
|
* The other user may choose to decline the file request if they do not
|
||||||
* desire the file, their client does not support JEP-0096, or if there are
|
* desire the file, their client does not support XEP-0096, or if there are
|
||||||
* no acceptable means to transfer the file.
|
* no acceptable means to transfer the file.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Finally, if the other user does not respond this method will return null
|
* Finally, if the other user does not respond this method will return null
|
||||||
|
|
|
@ -36,7 +36,7 @@ import java.io.OutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After the file transfer negotiation process is completed according to
|
* After the file transfer negotiation process is completed according to
|
||||||
* JEP-0096, the negotiation process is passed off to a particular stream
|
* XEP-0096, the negotiation process is passed off to a particular stream
|
||||||
* negotiator. The stream negotiator will then negotiate the chosen stream and
|
* negotiator. The stream negotiator will then negotiate the chosen stream and
|
||||||
* return the stream to transfer the file.
|
* return the stream to transfer the file.
|
||||||
*
|
*
|
||||||
|
|
|
@ -50,7 +50,7 @@ import java.util.WeakHashMap;
|
||||||
* a {@link DefaultPrivateData} instance will be returned.<p>
|
* a {@link DefaultPrivateData} instance will be returned.<p>
|
||||||
*
|
*
|
||||||
* Warning: this is an non-standard protocol documented by
|
* Warning: this is an non-standard protocol documented by
|
||||||
* <a href="http://www.jabber.org/jeps/jep-0049.html">JEP-49</a>. Because this is a
|
* <a href="http://www.xmpp.org/extensions/jep-0049.html">XEP-49</a>. Because this is a
|
||||||
* non-standard protocol, it is subject to change.
|
* non-standard protocol, it is subject to change.
|
||||||
*
|
*
|
||||||
* @author Matt Tucker
|
* @author Matt Tucker
|
||||||
|
@ -285,7 +285,7 @@ public class PrivateDataManager extends Manager {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("<query xmlns=\"jabber:iq:private\">");
|
buf.append("<query xmlns=\"jabber:iq:private\">");
|
||||||
if (privateData != null) {
|
if (privateData != null) {
|
||||||
privateData.toXML();
|
buf.append(privateData.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</query>");
|
buf.append("</query>");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
|
|
|
@ -45,5 +45,5 @@ public interface PrivateData {
|
||||||
*
|
*
|
||||||
* @return the private data as XML.
|
* @return the private data as XML.
|
||||||
*/
|
*/
|
||||||
public String toXML();
|
public CharSequence toXML();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
* // Create a packet collector or packet listeners using the filter...
|
* // Create a packet collector or packet listeners using the filter...
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <b>Note</b>: this protocol is outdated now that the Multi-User Chat (MUC) JEP is available
|
* <b>Note</b>: this protocol is outdated now that the Multi-User Chat (MUC) XEP is available
|
||||||
* (<a href="http://www.jabber.org/jeps/jep-0045.html">JEP-45</a>). However, most
|
* (<a href="http://www.xmpp.org/extensions/jep-0045.html">XEP-45</a>). However, most
|
||||||
* existing clients still use this older protocol. Once MUC support becomes more
|
* existing clients still use this older protocol. Once MUC support becomes more
|
||||||
* widespread, this API may be deprecated.
|
* widespread, this API may be deprecated.
|
||||||
*
|
*
|
||||||
|
|
|
@ -520,7 +520,7 @@ public class MUCUser implements PacketExtension {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status code assists in presenting notification messages. The following link provides the
|
* Status code assists in presenting notification messages. The following link provides the
|
||||||
* list of existing error codes (@link http://www.jabber.org/jeps/jep-0045.html#errorstatus).
|
* list of existing error codes (@link http://www.xmpp.org/extensions/jep-0045.html#errorstatus).
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,7 +20,6 @@ import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
import org.jivesoftware.smack.provider.ProviderManager;
|
import org.jivesoftware.smack.provider.ProviderManager;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
import org.jivesoftware.smackx.pubsub.Item;
|
import org.jivesoftware.smackx.pubsub.Item;
|
||||||
import org.jivesoftware.smackx.pubsub.PayloadItem;
|
import org.jivesoftware.smackx.pubsub.PayloadItem;
|
||||||
import org.jivesoftware.smackx.pubsub.SimplePayload;
|
import org.jivesoftware.smackx.pubsub.SimplePayload;
|
||||||
|
@ -41,7 +40,6 @@ public class ItemProvider implements PacketExtensionProvider
|
||||||
{
|
{
|
||||||
String id = parser.getAttributeValue(null, "id");
|
String id = parser.getAttributeValue(null, "id");
|
||||||
String node = parser.getAttributeValue(null, "node");
|
String node = parser.getAttributeValue(null, "node");
|
||||||
String elem = parser.getName();
|
|
||||||
|
|
||||||
int tag = parser.next();
|
int tag = parser.next();
|
||||||
|
|
||||||
|
@ -56,57 +54,8 @@ public class ItemProvider implements PacketExtensionProvider
|
||||||
|
|
||||||
if (ProviderManager.getExtensionProvider(payloadElemName, payloadNS) == null)
|
if (ProviderManager.getExtensionProvider(payloadElemName, payloadNS) == null)
|
||||||
{
|
{
|
||||||
boolean done = false;
|
String payloadText = PacketParserUtils.parseElement(parser);
|
||||||
boolean isEmptyElement = false;
|
return new PayloadItem<SimplePayload>(id, node, new SimplePayload(payloadElemName, payloadNS, payloadText));
|
||||||
StringBuilder payloadText = new StringBuilder();
|
|
||||||
|
|
||||||
while (!done)
|
|
||||||
{
|
|
||||||
if (tag == XmlPullParser.END_TAG && parser.getName().equals(elem))
|
|
||||||
{
|
|
||||||
done = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (parser.getEventType() == XmlPullParser.START_TAG)
|
|
||||||
{
|
|
||||||
payloadText.append("<").append(parser.getName());
|
|
||||||
|
|
||||||
if (parser.getName().equals(payloadElemName) && (payloadNS.length() > 0))
|
|
||||||
payloadText.append(" xmlns=\"").append(payloadNS).append("\"");
|
|
||||||
int n = parser.getAttributeCount();
|
|
||||||
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
payloadText.append(" ").append(parser.getAttributeName(i)).append("=\"")
|
|
||||||
.append(parser.getAttributeValue(i)).append("\"");
|
|
||||||
|
|
||||||
if (parser.isEmptyElementTag())
|
|
||||||
{
|
|
||||||
payloadText.append("/>");
|
|
||||||
isEmptyElement = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
payloadText.append(">");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (parser.getEventType() == XmlPullParser.END_TAG)
|
|
||||||
{
|
|
||||||
if (isEmptyElement)
|
|
||||||
{
|
|
||||||
isEmptyElement = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
payloadText.append("</").append(parser.getName()).append(">");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (parser.getEventType() == XmlPullParser.TEXT)
|
|
||||||
{
|
|
||||||
payloadText.append(StringUtils.escapeForXML(parser.getText()));
|
|
||||||
}
|
|
||||||
tag = parser.next();
|
|
||||||
}
|
|
||||||
return new PayloadItem<SimplePayload>(id, node, new SimplePayload(payloadElemName, payloadNS, payloadText.toString()));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SimpleUserSearch is used to support the non-dataform type of JEP 55. This provides
|
* SimpleUserSearch is used to support the non-dataform type of XEP 55. This provides
|
||||||
* the mechanism for allowing always type ReportedData to be returned by any search result,
|
* the mechanism for allowing always type ReportedData to be returned by any search result,
|
||||||
* regardless of the form of the data returned from the server.
|
* regardless of the form of the data returned from the server.
|
||||||
*
|
*
|
||||||
|
|
|
@ -31,7 +31,7 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The UserSearchManager is a facade built upon Jabber Search Services (JEP-055) to allow for searching
|
* The UserSearchManager is a facade built upon Jabber Search Services (XEP-055) to allow for searching
|
||||||
* repositories on a Jabber Server. This implementation allows for transparency of implementation of
|
* repositories on a Jabber Server. This implementation allows for transparency of implementation of
|
||||||
* searching (DataForms or No DataForms), but allows the user to simply use the DataForm model for both
|
* searching (DataForms or No DataForms), but allows the user to simply use the DataForm model for both
|
||||||
* types of support.
|
* types of support.
|
||||||
|
|
|
@ -45,7 +45,7 @@ import org.jivesoftware.smackx.vcardtemp.VCardManager;
|
||||||
* <a href="http://www.jivesoftware.org/smack/" target="_blank">SMACK jabber library</a>.<p>
|
* <a href="http://www.jivesoftware.org/smack/" target="_blank">SMACK jabber library</a>.<p>
|
||||||
* <p/>
|
* <p/>
|
||||||
* You should refer to the
|
* You should refer to the
|
||||||
* <a href="http://www.jabber.org/jeps/jep-0054.html" target="_blank">JEP-54 documentation</a>.<p>
|
* <a href="http://www.xmpp.org/extensions/jep-0054.html" target="_blank">XEP-54 documentation</a>.<p>
|
||||||
* <p/>
|
* <p/>
|
||||||
* Please note that this class is incomplete but it does provide the most commonly found
|
* Please note that this class is incomplete but it does provide the most commonly found
|
||||||
* information in vCards. Also remember that VCard transfer is not a standard, and the protocol
|
* information in vCards. Also remember that VCard transfer is not a standard, and the protocol
|
||||||
|
@ -114,7 +114,7 @@ public class VCard extends IQ {
|
||||||
private String photoBinval;
|
private String photoBinval;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Such as DESC ROLE GEO etc.. see JEP-0054
|
* Such as DESC ROLE GEO etc.. see XEP-0054
|
||||||
*/
|
*/
|
||||||
private Map<String, String> otherSimpleFields = new HashMap<String, String>();
|
private Map<String, String> otherSimpleFields = new HashMap<String, String>();
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,6 @@ public class Form {
|
||||||
public static final String TYPE_CANCEL = "cancel";
|
public static final String TYPE_CANCEL = "cancel";
|
||||||
public static final String TYPE_RESULT = "result";
|
public static final String TYPE_RESULT = "result";
|
||||||
|
|
||||||
public static final String NAMESPACE = "jabber:x:data";
|
|
||||||
public static final String ELEMENT = "x";
|
|
||||||
|
|
||||||
private DataForm dataForm;
|
private DataForm dataForm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.xdata;
|
package org.jivesoftware.smackx.xdata;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -33,6 +32,8 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class FormField {
|
public class FormField {
|
||||||
|
|
||||||
|
public static final String ELEMENT = "field";
|
||||||
|
|
||||||
public static final String TYPE_BOOLEAN = "boolean";
|
public static final String TYPE_BOOLEAN = "boolean";
|
||||||
public static final String TYPE_FIXED = "fixed";
|
public static final String TYPE_FIXED = "fixed";
|
||||||
public static final String TYPE_HIDDEN = "hidden";
|
public static final String TYPE_HIDDEN = "hidden";
|
||||||
|
@ -263,25 +264,17 @@ public class FormField {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toXML() {
|
public XmlStringBuilder toXML() {
|
||||||
XmlStringBuilder buf = new XmlStringBuilder();
|
XmlStringBuilder buf = new XmlStringBuilder();
|
||||||
buf.append("<field");
|
buf.halfOpenElement(ELEMENT);
|
||||||
// Add attributes
|
// Add attributes
|
||||||
if (getLabel() != null) {
|
buf.optAttribute("label", getLabel());
|
||||||
buf.append(" label=\"").append(getLabel()).append("\"");
|
buf.optAttribute("var", getVariable());
|
||||||
}
|
buf.optAttribute("type", getType());
|
||||||
buf.attribute("var", getVariable());
|
buf.rightAngelBracket();
|
||||||
if (getType() != null) {
|
|
||||||
buf.append(" type=\"").append(getType()).append("\"");
|
|
||||||
}
|
|
||||||
buf.append(">");
|
|
||||||
// Add elements
|
// Add elements
|
||||||
if (getDescription() != null) {
|
buf.optElement("desc", getDescription());
|
||||||
buf.append("<desc>").append(getDescription()).append("</desc>");
|
buf.condEmptyElement(isRequired(), "required");
|
||||||
}
|
|
||||||
if (isRequired()) {
|
|
||||||
buf.append("<required/>");
|
|
||||||
}
|
|
||||||
// Loop through all the values and append them to the string buffer
|
// Loop through all the values and append them to the string buffer
|
||||||
for (String value : getValues()) {
|
for (String value : getValues()) {
|
||||||
buf.element("value", value);
|
buf.element("value", value);
|
||||||
|
@ -290,8 +283,8 @@ public class FormField {
|
||||||
for (Option option : getOptions()) {
|
for (Option option : getOptions()) {
|
||||||
buf.append(option.toXML());
|
buf.append(option.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</field>");
|
buf.closeElement(ELEMENT);
|
||||||
return buf.toString();
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -320,8 +313,10 @@ public class FormField {
|
||||||
*/
|
*/
|
||||||
public static class Option {
|
public static class Option {
|
||||||
|
|
||||||
|
public static final String ELEMNT = "option";
|
||||||
|
|
||||||
|
private final String value;
|
||||||
private String label;
|
private String label;
|
||||||
private String value;
|
|
||||||
|
|
||||||
public Option(String value) {
|
public Option(String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -355,19 +350,18 @@ public class FormField {
|
||||||
return getLabel();
|
return getLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toXML() {
|
public XmlStringBuilder toXML() {
|
||||||
StringBuilder buf = new StringBuilder();
|
XmlStringBuilder xml = new XmlStringBuilder();
|
||||||
buf.append("<option");
|
xml.halfOpenElement(ELEMNT);
|
||||||
// Add attribute
|
// Add attribute
|
||||||
if (getLabel() != null) {
|
xml.optAttribute("label", getLabel());
|
||||||
buf.append(" label=\"").append(getLabel()).append("\"");
|
xml.rightAngelBracket();
|
||||||
}
|
|
||||||
buf.append(">");
|
|
||||||
// Add element
|
|
||||||
buf.append("<value>").append(StringUtils.escapeForXML(getValue())).append("</value>");
|
|
||||||
|
|
||||||
buf.append("</option>");
|
// Add element
|
||||||
return buf.toString();
|
xml.element("value", getValue());
|
||||||
|
|
||||||
|
xml.closeElement(ELEMENT);
|
||||||
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.jivesoftware.smackx.xdata.packet;
|
package org.jivesoftware.smackx.xdata.packet;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
import org.jivesoftware.smackx.xdata.Form;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
import org.jivesoftware.smackx.xdata.FormField;
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -33,6 +33,9 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class DataForm implements PacketExtension {
|
public class DataForm implements PacketExtension {
|
||||||
|
|
||||||
|
public static final String NAMESPACE = "jabber:x:data";
|
||||||
|
public static final String ELEMENT = "x";
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
private String title;
|
private String title;
|
||||||
private List<String> instructions = new ArrayList<String>();
|
private List<String> instructions = new ArrayList<String>();
|
||||||
|
@ -120,11 +123,11 @@ public class DataForm implements PacketExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getElementName() {
|
public String getElementName() {
|
||||||
return Form.ELEMENT;
|
return ELEMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNamespace() {
|
public String getNamespace() {
|
||||||
return Form.NAMESPACE;
|
return NAMESPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,15 +210,15 @@ public class DataForm implements PacketExtension {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toXML() {
|
@Override
|
||||||
StringBuilder buf = new StringBuilder();
|
public XmlStringBuilder toXML() {
|
||||||
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
|
XmlStringBuilder buf = new XmlStringBuilder(this);
|
||||||
"\" type=\"" + getType() +"\">");
|
buf.attribute("type", getType());
|
||||||
if (getTitle() != null) {
|
buf.rightAngelBracket();
|
||||||
buf.append("<title>").append(getTitle()).append("</title>");
|
|
||||||
}
|
buf.optElement("title", getTitle());
|
||||||
for (String instruction : getInstructions()) {
|
for (String instruction : getInstructions()) {
|
||||||
buf.append("<instructions>").append(instruction).append("</instructions>");
|
buf.element("instructions", instruction);
|
||||||
}
|
}
|
||||||
// Append the list of fields returned from a search
|
// Append the list of fields returned from a search
|
||||||
if (getReportedData() != null) {
|
if (getReportedData() != null) {
|
||||||
|
@ -229,8 +232,8 @@ public class DataForm implements PacketExtension {
|
||||||
for (FormField field : getFields()) {
|
for (FormField field : getFields()) {
|
||||||
buf.append(field.toXML());
|
buf.append(field.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</").append(getElementName()).append(">");
|
buf.closeElement(this);
|
||||||
return buf.toString();
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,6 +244,8 @@ public class DataForm implements PacketExtension {
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
public static class ReportedData {
|
public static class ReportedData {
|
||||||
|
public static final String ELEMENT = "reported";
|
||||||
|
|
||||||
private List<FormField> fields = new ArrayList<FormField>();
|
private List<FormField> fields = new ArrayList<FormField>();
|
||||||
|
|
||||||
public ReportedData(List<FormField> fields) {
|
public ReportedData(List<FormField> fields) {
|
||||||
|
@ -256,15 +261,15 @@ public class DataForm implements PacketExtension {
|
||||||
return Collections.unmodifiableList(new ArrayList<FormField>(fields));
|
return Collections.unmodifiableList(new ArrayList<FormField>(fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toXML() {
|
public CharSequence toXML() {
|
||||||
StringBuilder buf = new StringBuilder();
|
XmlStringBuilder buf = new XmlStringBuilder();
|
||||||
buf.append("<reported>");
|
buf.openElement(ELEMENT);
|
||||||
// Loop through all the form items and append them to the string buffer
|
// Loop through all the form items and append them to the string buffer
|
||||||
for (FormField field : getFields()) {
|
for (FormField field : getFields()) {
|
||||||
buf.append(field.toXML());
|
buf.append(field.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</reported>");
|
buf.closeElement(ELEMENT);
|
||||||
return buf.toString();
|
return buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +280,8 @@ public class DataForm implements PacketExtension {
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
public static class Item {
|
public static class Item {
|
||||||
|
public static final String ELEMENT = "item";
|
||||||
|
|
||||||
private List<FormField> fields = new ArrayList<FormField>();
|
private List<FormField> fields = new ArrayList<FormField>();
|
||||||
|
|
||||||
public Item(List<FormField> fields) {
|
public Item(List<FormField> fields) {
|
||||||
|
@ -290,15 +297,15 @@ public class DataForm implements PacketExtension {
|
||||||
return Collections.unmodifiableList(new ArrayList<FormField>(fields));
|
return Collections.unmodifiableList(new ArrayList<FormField>(fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toXML() {
|
public CharSequence toXML() {
|
||||||
StringBuilder buf = new StringBuilder();
|
XmlStringBuilder buf = new XmlStringBuilder();
|
||||||
buf.append("<item>");
|
buf.openElement(ELEMENT);
|
||||||
// Loop through all the form items and append them to the string buffer
|
// Loop through all the form items and append them to the string buffer
|
||||||
for (FormField field : getFields()) {
|
for (FormField field : getFields()) {
|
||||||
buf.append(field.toXML());
|
buf.append(field.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</item>");
|
buf.closeElement(ELEMENT);
|
||||||
return buf.toString();
|
return buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@ import java.util.List;
|
||||||
* extension is only a subset of XHTML 1.0.<p>
|
* extension is only a subset of XHTML 1.0.<p>
|
||||||
*
|
*
|
||||||
* The following link summarizes the requirements of XHTML IM:
|
* The following link summarizes the requirements of XHTML IM:
|
||||||
* <a href="http://www.jabber.org/jeps/jep-0071.html#sect-id2598018">Valid tags</a>.<p>
|
* <a href="http://www.xmpp.org/extensions/jep-0071.html#sect-id2598018">Valid tags</a>.<p>
|
||||||
*
|
*
|
||||||
* Warning: this is an non-standard protocol documented by
|
* Warning: this is an non-standard protocol documented by
|
||||||
* <a href="http://www.jabber.org/jeps/jep-0071.html">JEP-71</a>. Because this is a
|
* <a href="http://www.xmpp.org/extensions/jep-0071.html">XEP-71</a>. Because this is a
|
||||||
* non-standard protocol, it is subject to change.
|
* non-standard protocol, it is subject to change.
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
|
|
|
@ -172,7 +172,7 @@
|
||||||
<className>org.jivesoftware.smackx.sharedgroups.packet.SharedGroupsInfo$Provider</className>
|
<className>org.jivesoftware.smackx.sharedgroups.packet.SharedGroupsInfo$Provider</className>
|
||||||
</iqProvider>
|
</iqProvider>
|
||||||
|
|
||||||
<!-- JEP-33: Extended Stanza Addressing -->
|
<!-- XEP-33: Extended Stanza Addressing -->
|
||||||
<extensionProvider>
|
<extensionProvider>
|
||||||
<elementName>addresses</elementName>
|
<elementName>addresses</elementName>
|
||||||
<namespace>http://jabber.org/protocol/address</namespace>
|
<namespace>http://jabber.org/protocol/address</namespace>
|
||||||
|
|
|
@ -51,6 +51,6 @@ public class FileTransferNegotiatorTest {
|
||||||
fileNeg.negotiateOutgoingTransfer("me", "streamid", "file", 1024, null, 10);
|
fileNeg.negotiateOutgoingTransfer("me", "streamid", "file", 1024, null, 10);
|
||||||
Packet packet = connection.getSentPacket();
|
Packet packet = connection.getSentPacket();
|
||||||
String xml = packet.toXML().toString();
|
String xml = packet.toXML().toString();
|
||||||
assertTrue(xml.indexOf("var='stream-method' type=\"list-single\"") != -1);
|
assertTrue(xml.indexOf("var='stream-method' type='list-single'") != -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@ import java.util.List;
|
||||||
* An Jingle sub-packet, which is used by XMPP clients to exchange info like
|
* An Jingle sub-packet, which is used by XMPP clients to exchange info like
|
||||||
* descriptions and transports. <p/> The following link summarizes the
|
* descriptions and transports. <p/> The following link summarizes the
|
||||||
* requirements of Jingle IM: <a
|
* requirements of Jingle IM: <a
|
||||||
* href="http://www.jabber.org/jeps/jep-0166.html">Valid tags</a>.
|
* href="http://www.xmpp.org/extensions/jep-0166.html">Valid tags</a>.
|
||||||
* <p/>
|
* <p/>
|
||||||
* <p/> Warning: this is an non-standard protocol documented by <a
|
* <p/> Warning: this is an non-standard protocol documented by <a
|
||||||
* href="http://www.jabber.org/jeps/jep-0166.html">JEP-166</a>. Because this is
|
* href="http://www.xmpp.org/extensions/jep-0166.html">XEP-166</a>. Because this is
|
||||||
* a non-standard protocol, it is subject to change.
|
* a non-standard protocol, it is subject to change.
|
||||||
*
|
*
|
||||||
* @author Alvaro Saurin
|
* @author Alvaro Saurin
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jivesoftware.smack.util.dns.javax;
|
package org.jivesoftware.smack.util.dns.javax;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ import javax.naming.directory.Attributes;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
import javax.naming.directory.InitialDirContext;
|
import javax.naming.directory.InitialDirContext;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.initializer.SmackInitializer;
|
||||||
import org.jivesoftware.smack.util.DNSUtil;
|
import org.jivesoftware.smack.util.DNSUtil;
|
||||||
import org.jivesoftware.smack.util.dns.DNSResolver;
|
import org.jivesoftware.smack.util.dns.DNSResolver;
|
||||||
import org.jivesoftware.smack.util.dns.SRVRecord;
|
import org.jivesoftware.smack.util.dns.SRVRecord;
|
||||||
|
@ -37,7 +39,7 @@ import org.jivesoftware.smack.util.dns.SRVRecord;
|
||||||
* @author Florian Schmaus
|
* @author Florian Schmaus
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class JavaxResolver implements DNSResolver {
|
public class JavaxResolver implements DNSResolver, SmackInitializer {
|
||||||
|
|
||||||
private static JavaxResolver instance;
|
private static JavaxResolver instance;
|
||||||
private static DirContext dirContext;
|
private static DirContext dirContext;
|
||||||
|
@ -52,24 +54,28 @@ public class JavaxResolver implements DNSResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to set this DNS resolver as primary one
|
// Try to set this DNS resolver as primary one
|
||||||
DNSUtil.setDNSResolver(getInstance());
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private JavaxResolver() {
|
public JavaxResolver() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DNSResolver getInstance() {
|
public static synchronized DNSResolver getInstance() {
|
||||||
if (instance == null && isSupported()) {
|
if (instance == null && isSupported()) {
|
||||||
instance = new JavaxResolver();
|
instance = new JavaxResolver();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSupported() {
|
public static boolean isSupported() {
|
||||||
return dirContext != null;
|
return dirContext != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setup() {
|
||||||
|
DNSUtil.setDNSResolver(getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SRVRecord> lookupSRVRecords(String name) throws NamingException {
|
public List<SRVRecord> lookupSRVRecords(String name) throws NamingException {
|
||||||
List<SRVRecord> res = new ArrayList<SRVRecord>();
|
List<SRVRecord> res = new ArrayList<SRVRecord>();
|
||||||
|
@ -93,4 +99,15 @@ public class JavaxResolver implements DNSResolver {
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Exception> initialize() {
|
||||||
|
return initialize(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Exception> initialize(ClassLoader classLoader) {
|
||||||
|
setup();
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.2.0"
|
||||||
|
enabled="true" immediate="true" name="Smack Resolver JavaX API">
|
||||||
|
<implementation
|
||||||
|
class="org.jivesoftware.smack.util.dns.javax.JavaxResolver" />
|
||||||
|
</scr:component>
|
10
smack-resolver-minidns/build.gradle
Normal file
10
smack-resolver-minidns/build.gradle
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
description = """\
|
||||||
|
DNS SRV with minidns
|
||||||
|
Use minidns for DNS SRV lookups. For platforms that don't provide the
|
||||||
|
javax.naming API (e.g. Android)."""
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(path: ':smack-core', configuration: 'dns')
|
||||||
|
compile 'de.measite.minidns:minidns:0.1.1'
|
||||||
|
compile "org.igniterealtime.jxmpp:jxmpp-util-cache:$jxmppVersion"
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 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.dns.minidns;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.dns.DNSResolver;
|
||||||
|
import org.jivesoftware.smack.util.dns.SRVRecord;
|
||||||
|
import org.jxmpp.util.cache.ExpirationCache;
|
||||||
|
|
||||||
|
import de.measite.minidns.Client;
|
||||||
|
import de.measite.minidns.DNSCache;
|
||||||
|
import de.measite.minidns.DNSMessage;
|
||||||
|
import de.measite.minidns.Question;
|
||||||
|
import de.measite.minidns.Record;
|
||||||
|
import de.measite.minidns.Record.CLASS;
|
||||||
|
import de.measite.minidns.Record.TYPE;
|
||||||
|
import de.measite.minidns.record.SRV;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This implementation uses the <a href="https://github.com/rtreffer/minidns/">minidns</a> implementation for
|
||||||
|
* resolving DNS addresses.
|
||||||
|
*/
|
||||||
|
public class MiniDnsResolver implements DNSResolver {
|
||||||
|
|
||||||
|
private static final long ONE_DAY = 24*60*60*1000;
|
||||||
|
private static final MiniDnsResolver instance = new MiniDnsResolver();
|
||||||
|
private static final ExpirationCache<Question, DNSMessage> cache = new ExpirationCache<Question, DNSMessage>(10, ONE_DAY);
|
||||||
|
private final Client client;
|
||||||
|
|
||||||
|
private MiniDnsResolver() {
|
||||||
|
client = new Client(new DNSCache() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DNSMessage get(Question question) {
|
||||||
|
return cache.get(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(Question question, DNSMessage message) {
|
||||||
|
long expirationTime = ONE_DAY;
|
||||||
|
for (Record record : message.getAnswers()) {
|
||||||
|
if (record.isAnswer(question)) {
|
||||||
|
expirationTime = record.getTtl();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache.put(question, message, expirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DNSResolver getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SRVRecord> lookupSRVRecords(String name) {
|
||||||
|
List<SRVRecord> res = new LinkedList<SRVRecord>();
|
||||||
|
DNSMessage message = client.query(name, TYPE.SRV, CLASS.IN);
|
||||||
|
for (Record record : message.getAnswers()) {
|
||||||
|
SRV srv = (SRV) record.getPayload();
|
||||||
|
res.add(new SRVRecord(srv.getName(), srv.getPort(), srv.getPriority(), srv.getWeight()));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue