mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-26 14:02:06 +01:00
Added privacy list support and improved error handling from Francisco (SMACK-121, SMACK-31).
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@4603 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
1716c6ed22
commit
47abf627b7
20 changed files with 2099 additions and 81 deletions
|
@ -5,6 +5,7 @@
|
||||||
<!-- Classes that will be loaded when Smack starts -->
|
<!-- Classes that will be loaded when Smack starts -->
|
||||||
<startupClasses>
|
<startupClasses>
|
||||||
<className>org.jivesoftware.smackx.ServiceDiscoveryManager</className>
|
<className>org.jivesoftware.smackx.ServiceDiscoveryManager</className>
|
||||||
|
<className>org.jivesoftware.smack.PrivacyListManager</className>
|
||||||
<className>org.jivesoftware.smackx.XHTMLManager</className>
|
<className>org.jivesoftware.smackx.XHTMLManager</className>
|
||||||
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
|
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
|
||||||
<className>org.jivesoftware.smackx.filetransfer.FileTransferManager</className>
|
<className>org.jivesoftware.smackx.filetransfer.FileTransferManager</className>
|
||||||
|
|
|
@ -180,4 +180,11 @@
|
||||||
<className>org.jivesoftware.smackx.provider.IBBProviders$Data</className>
|
<className>org.jivesoftware.smackx.provider.IBBProviders$Data</className>
|
||||||
</extensionProvider>
|
</extensionProvider>
|
||||||
|
|
||||||
|
<!-- Privacy -->
|
||||||
|
<iqProvider>
|
||||||
|
<elementName>query</elementName>
|
||||||
|
<namespace>jabber:iq:privacy</namespace>
|
||||||
|
<className>org.jivesoftware.smack.provider.PrivacyProvider</className>
|
||||||
|
</iqProvider>
|
||||||
|
|
||||||
</smackProviders>
|
</smackProviders>
|
|
@ -25,12 +25,13 @@
|
||||||
<li><a href="providers.html">Provider Architecture</a>
|
<li><a href="providers.html">Provider Architecture</a>
|
||||||
<li><a href="properties.html">Packet Properties</a>
|
<li><a href="properties.html">Packet Properties</a>
|
||||||
<li><a href="debugging.html">Debugging with Smack</a>
|
<li><a href="debugging.html">Debugging with Smack</a>
|
||||||
|
<li><a href="privacy.html">Privacy</a>
|
||||||
<p>
|
<p>
|
||||||
<li><a href="extensions/index.html">Smack Extensions Manual</a>
|
<li><a href="extensions/index.html">Smack Extensions Manual</a>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
Copyright © Jive Software 2002-2005
|
Copyright © Jive Software 2002-2006
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
167
documentation/privacy.html
Normal file
167
documentation/privacy.html
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Smack: Privacy - Jive Software</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
Privacy
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav">
|
||||||
|
« <a href="index.html">Table of Contents</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="subheader">What is?</p>
|
||||||
|
<p>
|
||||||
|
<tt>Privacy</tt> is a method for users to block communications from particular other users. In XMPP this is done by managing one's privacy lists.<br />
|
||||||
|
Server-side privacy lists enable successful completion of the following use cases:
|
||||||
|
<ul>
|
||||||
|
<li>Retrieving one's privacy lists.
|
||||||
|
<li>Adding, removing, and editing one's privacy lists.
|
||||||
|
<li>Setting, changing, or declining active lists.
|
||||||
|
<li>Setting, changing, or declining the default list (i.e., the list that is active by default).
|
||||||
|
<li>Allowing or blocking messages based on JID, group, or subscription type (or globally).
|
||||||
|
<li>Allowing or blocking inbound presence notifications based on JID, group, or subscription type (or globally).
|
||||||
|
<li>Allowing or blocking outbound presence notifications based on JID, group, or subscription type (or globally).
|
||||||
|
<li>Allowing or blocking IQ stanzas based on JID, group, or subscription type (or globally).
|
||||||
|
<li>Allowing or blocking all communications based on JID, group, or subscription type (or globally).
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<p class="subheader">How can I use it?</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The API implementation releases three main public classes:
|
||||||
|
<ul>
|
||||||
|
<li><tt>PrivacyListManager</tt>: this is the main API class to retrieve and handle server privacy lists.
|
||||||
|
<li><tt>PrivacyList</tt>: witch represents one privacy list, with a name, a set of privacy items. For example, the list with visible or invisible.
|
||||||
|
<li><tt>PrivacyItem</tt>: block or allow one aspect of privacy. For example, to allow my friend to see my presence.
|
||||||
|
</ul>
|
||||||
|
<ol>
|
||||||
|
<li> Right from the start, a client MAY <b>get his/her privacy list</b> that is stored in the server:<br />
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Create a privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Retrieve server privacy lists</i></font>
|
||||||
|
PrivacyList[] lists = privacyManager.getPrivacyLists();
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
Now the client is able to show every <tt>PrivacyItem</tt> of the server and also for every list if it is active, default or none of them. The client is a listener of privacy changes.<br />
|
||||||
|
<br />
|
||||||
|
<li> In order to <b>add a new list in the server</b>, the client MAY implement something like:
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Set the name of the list</i></font>
|
||||||
|
String listName = <font color="green">"newList"</font>;
|
||||||
|
|
||||||
|
<font color="gray"><i>// Create the list of <tt>PrivacyItem</tt> that will allow or deny some privacy aspect</i></font>
|
||||||
|
String user = <font color="green">"tybalt@example.com"</font>;
|
||||||
|
String groupName = <font color="green">"enemies"</font>;
|
||||||
|
ArrayList privacyItems = new ArrayList();
|
||||||
|
|
||||||
|
PrivacyItem item = new PrivacyItem(PrivacyRule.<font color="navy"><i>JID</i></font>, <font color="navy">true</font>, 1);
|
||||||
|
item.setValue(user);
|
||||||
|
privacyItems.add(item);
|
||||||
|
|
||||||
|
item = new PrivacyItem(PrivacyRule.<font color="navy"><i>SUBSCRIPTION</i></font>, <font color="navy">true</font>, 2);
|
||||||
|
item.setValue(PrivacyRule.<font color="navy"><i>SUBSCRIPTION_BOTH</i></font>);
|
||||||
|
privacyItems.add(item);
|
||||||
|
|
||||||
|
item = new PrivacyItem(PrivacyRule.<font color="navy"><i>GROUP</i></font>, <font color="navy">false</font>, 3);
|
||||||
|
item.setValue(groupName);
|
||||||
|
item.setFilterMessage(<font color="navy">true</font>);
|
||||||
|
privacyItems.add(item);
|
||||||
|
|
||||||
|
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Create the new list.</i></font>
|
||||||
|
privacyManager.createPrivacyList(listName, Arrays.<i>asList</i>(privacyItems));
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<li> To <b>modify an existent list</b>, the client code MAY be like:
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Set the name of the list</i></font>
|
||||||
|
String listName = <font color="green">"existingList"</font>;
|
||||||
|
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Sent the new list to the server.</i></font>
|
||||||
|
privacyManager.updatePrivacyList(listName, items);
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
Notice <tt>items</tt> was defined at the example 2 and MUST contain all the elements in the list (not the "delta").
|
||||||
|
|
||||||
|
<li> In order to <b>delete an existing list</b>, the client MAY perform something like:
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Set the name of the list</i></font>
|
||||||
|
String listName = <font color="green">"existingList"</font>;
|
||||||
|
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Remove the list.</i></font>
|
||||||
|
privacyManager.deletePrivacyList(listName);
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<li> In order to <b>decline the use of an active list</b>, the client MAY perform something like:
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Decline the use of the active list.</i></font>
|
||||||
|
privacyManager.declineActiveList();
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<li> In order to <b>decline the use of a default list</b>, the client MAY perform something like:
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Decline the use of the default list.</i></font>
|
||||||
|
privacyManager.declineDefaultList();
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p class="subheader">Listening for Privacy Changes</p>
|
||||||
|
<p>
|
||||||
|
In order to handle privacy changes, clients SHOULD listen manager's updates.
|
||||||
|
When a list is changed the manager notifies every added listener. Listeners MUST implement the <tt>PrivacyListListener</tt> interface.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Clients may need to react when a privacy list is modified. The <tt>PrivacyListManager</tt> lets you add listerners that will be notified when a list has been changed. Listeners should implement the <tt>PrivacyListListener</tt> interface.<br />
|
||||||
|
The most important notification is <tt>updatedPrivacyList</tt> that is performed when a privacy list changes its privacy items.<br />
|
||||||
|
|
||||||
|
The listener becomes notified after performing:
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
|
||||||
|
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
|
||||||
|
<font color="gray"><i>// Add the listener (this) to get notified</i></font>
|
||||||
|
privacyManager.addListener(<font color="navy">this</font>);
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="subheader">References</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://www.xmpp.org/specs/rfc3921.html#privacy">Blocking communication</a> from the RFC3921.
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br clear="all" /><br><br>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
Copyright © Jive Software 2002-2006
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -607,7 +607,7 @@ class PacketReader {
|
||||||
iqPacket.setTo(from);
|
iqPacket.setTo(from);
|
||||||
iqPacket.setFrom(to);
|
iqPacket.setFrom(to);
|
||||||
iqPacket.setType(IQ.Type.ERROR);
|
iqPacket.setType(IQ.Type.ERROR);
|
||||||
iqPacket.setError(new XMPPError(501, "feature-not-implemented"));
|
iqPacket.setError(new XMPPError(XMPPError.Condition.feature_not_implemented));
|
||||||
connection.sendPacket(iqPacket);
|
connection.sendPacket(iqPacket);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
57
source/org/jivesoftware/smack/PrivacyList.java
Normal file
57
source/org/jivesoftware/smack/PrivacyList.java
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package org.jivesoftware.smack;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PrivacyItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Privacy List is a read only class used to represent a set of allowed or blocked communications.
|
||||||
|
* Basically it can:<ul>
|
||||||
|
*
|
||||||
|
* <li>Handle many {@link org.jivesoftware.smack.packet.PrivacyItem}.</li>
|
||||||
|
* <li>Answer if it is the default list.</li>
|
||||||
|
* <li>Answer if it is the active list.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* {@link PrivacyItem Privacy Items} can handle different kind of blocking communications based on JID, group,
|
||||||
|
* subscription type or globally.
|
||||||
|
*
|
||||||
|
* @author Francisco Vives
|
||||||
|
*/
|
||||||
|
public class PrivacyList {
|
||||||
|
|
||||||
|
/** Holds if it is an active list or not **/
|
||||||
|
private boolean isActiveList;
|
||||||
|
/** Holds if it is an default list or not **/
|
||||||
|
private boolean isDefaultList;
|
||||||
|
/** Holds the list name used to print **/
|
||||||
|
private String listName;
|
||||||
|
/** Holds the list of {@see PrivacyItem} **/
|
||||||
|
private List items;
|
||||||
|
|
||||||
|
protected PrivacyList(boolean isActiveList, boolean isDefaultList,
|
||||||
|
String listName, List<PrivacyItem> privacyItems) {
|
||||||
|
super();
|
||||||
|
this.isActiveList = isActiveList;
|
||||||
|
this.isDefaultList = isDefaultList;
|
||||||
|
this.listName = listName;
|
||||||
|
this.items = privacyItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActiveList() {
|
||||||
|
return isActiveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDefaultList() {
|
||||||
|
return isDefaultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return listName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
source/org/jivesoftware/smack/PrivacyListListener.java
Normal file
30
source/org/jivesoftware/smack/PrivacyListListener.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package org.jivesoftware.smack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to implement classes to listen for server events about privacy communication.
|
||||||
|
* Listeners are registered with the {@link PrivacyListManager}.
|
||||||
|
*
|
||||||
|
* @see {@link PrivacyListManager#addListener}
|
||||||
|
*
|
||||||
|
* @author Francisco Vives
|
||||||
|
*/
|
||||||
|
public interface PrivacyListListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or update a privacy list with PrivacyItem.
|
||||||
|
*
|
||||||
|
* @param listName the name of the new or updated privacy list.
|
||||||
|
* @param listItem the PrivacyItems that rules the list.
|
||||||
|
*/
|
||||||
|
public void setPrivacyList(String listName, List listItem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A privacy list has been modified by another. It gets notified.
|
||||||
|
*
|
||||||
|
* @param listName the name of the updated privacy list.
|
||||||
|
*/
|
||||||
|
public void updatedPrivacyList(String listName);
|
||||||
|
|
||||||
|
}
|
442
source/org/jivesoftware/smack/PrivacyListManager.java
Normal file
442
source/org/jivesoftware/smack/PrivacyListManager.java
Normal file
|
@ -0,0 +1,442 @@
|
||||||
|
package org.jivesoftware.smack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
|
import org.jivesoftware.smack.filter.IQTypeFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketExtensionFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smack.packet.Privacy;
|
||||||
|
import org.jivesoftware.smack.packet.PrivacyItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PrivacyListManager is used by XMPP clients to block or allow communications from other
|
||||||
|
* users. Use the manager to: <ul>
|
||||||
|
* <li>Retrieve privacy lists.
|
||||||
|
* <li>Add, remove, and edit privacy lists.
|
||||||
|
* <li>Set, change, or decline active lists.
|
||||||
|
* <li>Set, change, or decline the default list (i.e., the list that is active by default).
|
||||||
|
* </ul>
|
||||||
|
* Privacy Items can handle different kind of permission communications based on JID, group,
|
||||||
|
* subscription type or globally (@see PrivacyItem).
|
||||||
|
*
|
||||||
|
* @author Francisco Vives
|
||||||
|
*/
|
||||||
|
public class PrivacyListManager {
|
||||||
|
|
||||||
|
// Keep the list of instances of this class.
|
||||||
|
private static Map instances = new Hashtable();
|
||||||
|
|
||||||
|
private XMPPConnection connection;
|
||||||
|
private List listeners = new ArrayList();
|
||||||
|
PacketFilter packetFilter = new AndFilter(new IQTypeFilter(IQ.Type.SET),
|
||||||
|
new PacketExtensionFilter("query", "jabber:iq:privacy"));
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Create a new PrivacyListManager on every established connection. In the init()
|
||||||
|
// method of PrivacyListManager, we'll add a listener that will delete the
|
||||||
|
// instance when the connection is closed.
|
||||||
|
XMPPConnection.addConnectionListener(new ConnectionEstablishedListener() {
|
||||||
|
public void connectionEstablished(XMPPConnection connection) {
|
||||||
|
new PrivacyListManager(connection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a new privacy manager to maintain the communication privacy. Note: no
|
||||||
|
* information is sent to or received from the server until you attempt to
|
||||||
|
* get or set the privacy communication.<p>
|
||||||
|
*
|
||||||
|
* @param connection the XMPP connection.
|
||||||
|
*/
|
||||||
|
private PrivacyListManager(XMPPConnection connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Answer the connection userJID that owns the privacy.
|
||||||
|
* @return the userJID that owns the privacy
|
||||||
|
*/
|
||||||
|
private String getUser() {
|
||||||
|
return connection.getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the packet listeners of the connection that will notify for any set privacy
|
||||||
|
* package.
|
||||||
|
*/
|
||||||
|
private void init() {
|
||||||
|
// Register the new instance and associate it with the connection
|
||||||
|
instances.put(connection, this);
|
||||||
|
// Add a listener to the connection that removes the registered instance when
|
||||||
|
// the connection is closed
|
||||||
|
connection.addConnectionListener(new ConnectionListener() {
|
||||||
|
public void connectionClosed() {
|
||||||
|
// Unregister this instance since the connection has been closed
|
||||||
|
instances.remove(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connectionClosedOnError(Exception e) {
|
||||||
|
// Unregister this instance since the connection has been closed
|
||||||
|
instances.remove(connection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.addPacketListener(new PacketListener() {
|
||||||
|
public void processPacket(Packet packet) {
|
||||||
|
|
||||||
|
if (packet == null || packet.getError() != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The packet is correct.
|
||||||
|
Privacy privacy = (Privacy) packet;
|
||||||
|
|
||||||
|
// Prepare the information before starting the notification
|
||||||
|
int listNameSize = privacy.getItemLists().size();
|
||||||
|
Object[] listItemsPairs = privacy.getItemLists().entrySet().toArray();
|
||||||
|
|
||||||
|
// Notifies the event to the listeners.
|
||||||
|
synchronized (listeners) {
|
||||||
|
for (Iterator i = listeners.iterator(); i.hasNext();) {
|
||||||
|
PrivacyListListener listener = (PrivacyListListener) i.next();
|
||||||
|
|
||||||
|
// Notifies the created or updated privacy lists
|
||||||
|
for (int j = 0; j < listNameSize; j++) {
|
||||||
|
Map.Entry entry = (Map.Entry) listItemsPairs[j];
|
||||||
|
String listName = (String) entry.getKey();
|
||||||
|
List items = (List) entry.getValue();
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
listener.updatedPrivacyList(listName);
|
||||||
|
} else {
|
||||||
|
listener.setPrivacyList(listName, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a result package acknowledging the reception of a privacy package.
|
||||||
|
|
||||||
|
// Prepare the IQ packet to send
|
||||||
|
IQ iq = new IQ() {
|
||||||
|
public String getChildElementXML() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
iq.setType(IQ.Type.RESULT);
|
||||||
|
iq.setFrom(packet.getFrom());
|
||||||
|
iq.setPacketID(packet.getPacketID());
|
||||||
|
|
||||||
|
// Send create & join packet.
|
||||||
|
connection.sendPacket(iq);
|
||||||
|
}
|
||||||
|
}, packetFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the PrivacyListManager instance associated with a given XMPPConnection.
|
||||||
|
*
|
||||||
|
* @param connection the connection used to look for the proper PrivacyListManager.
|
||||||
|
* @return the PrivacyListManager associated with a given XMPPConnection.
|
||||||
|
*/
|
||||||
|
public static PrivacyListManager getInstanceFor(XMPPConnection connection) {
|
||||||
|
return (PrivacyListManager) instances.get(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the {@link Privacy} packet to the server in order to know some privacy content and then
|
||||||
|
* waits for the answer.
|
||||||
|
*
|
||||||
|
* @param requestPrivacy is the {@link Privacy} packet configured properly whose XML
|
||||||
|
* will be sent to the server.
|
||||||
|
* @return a new {@link Privacy} with the data received from the server.
|
||||||
|
* @exception XMPPException if the request or the answer failed, it raises an exception.
|
||||||
|
*/
|
||||||
|
private Privacy getRequest(Privacy requestPrivacy) throws XMPPException {
|
||||||
|
// The request is a get iq type
|
||||||
|
requestPrivacy.setType(Privacy.Type.GET);
|
||||||
|
requestPrivacy.setFrom(this.getUser());
|
||||||
|
|
||||||
|
// Filter packets looking for an answer from the server.
|
||||||
|
PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
|
||||||
|
PacketCollector response = connection.createPacketCollector(responseFilter);
|
||||||
|
|
||||||
|
// Send create & join packet.
|
||||||
|
connection.sendPacket(requestPrivacy);
|
||||||
|
|
||||||
|
// Wait up to a certain number of seconds for a reply.
|
||||||
|
Privacy privacyAnswer =
|
||||||
|
(Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||||
|
|
||||||
|
// Stop queuing results
|
||||||
|
response.cancel();
|
||||||
|
|
||||||
|
// Interprete the result and answer the privacy only if it is valid
|
||||||
|
if (privacyAnswer == null) {
|
||||||
|
throw new XMPPException("No response from server.");
|
||||||
|
}
|
||||||
|
else if (privacyAnswer.getError() != null) {
|
||||||
|
throw new XMPPException(privacyAnswer.getError());
|
||||||
|
}
|
||||||
|
return privacyAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the {@link Privacy} packet to the server in order to modify the server privacy and
|
||||||
|
* waits for the answer.
|
||||||
|
*
|
||||||
|
* @param requestPrivacy is the {@link Privacy} packet configured properly whose xml will be sent
|
||||||
|
* to the server.
|
||||||
|
* @return a new {@link Privacy} with the data received from the server.
|
||||||
|
* @exception XMPPException if the request or the answer failed, it raises an exception.
|
||||||
|
*/
|
||||||
|
private Packet setRequest(Privacy requestPrivacy) throws XMPPException {
|
||||||
|
|
||||||
|
// The request is a get iq type
|
||||||
|
requestPrivacy.setType(Privacy.Type.SET);
|
||||||
|
requestPrivacy.setFrom(this.getUser());
|
||||||
|
|
||||||
|
// Filter packets looking for an answer from the server.
|
||||||
|
PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
|
||||||
|
PacketCollector response = connection.createPacketCollector(responseFilter);
|
||||||
|
|
||||||
|
// Send create & join packet.
|
||||||
|
connection.sendPacket(requestPrivacy);
|
||||||
|
|
||||||
|
// Wait up to a certain number of seconds for a reply.
|
||||||
|
Packet privacyAnswer = response.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||||
|
|
||||||
|
// Stop queuing results
|
||||||
|
response.cancel();
|
||||||
|
|
||||||
|
// Interprete the result and answer the privacy only if it is valid
|
||||||
|
if (privacyAnswer == null) {
|
||||||
|
throw new XMPPException("No response from server.");
|
||||||
|
} else if (privacyAnswer.getError() != null) {
|
||||||
|
throw new XMPPException(privacyAnswer.getError());
|
||||||
|
}
|
||||||
|
return privacyAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer a privacy containing the list structre without {@link PrivacyItem}.
|
||||||
|
*
|
||||||
|
* @return a Privacy with the list names.
|
||||||
|
*/
|
||||||
|
private Privacy getPrivacyWithListNames() throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an empty privacy message
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
|
||||||
|
// Send the package to the server and get the answer
|
||||||
|
return getRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer the active privacy list.
|
||||||
|
*
|
||||||
|
* @return the {@see PrivacyList} of the active list.
|
||||||
|
*/
|
||||||
|
public PrivacyList getActiveList() throws XMPPException {
|
||||||
|
Privacy privacyAnswer = this.getPrivacyWithListNames();
|
||||||
|
String listName = privacyAnswer.getActiveName();
|
||||||
|
boolean isDefaultAndActive = privacyAnswer.getActiveName() != null
|
||||||
|
&& privacyAnswer.getDefaultName() != null
|
||||||
|
&& privacyAnswer.getActiveName().equals(
|
||||||
|
privacyAnswer.getDefaultName());
|
||||||
|
return new PrivacyList(true, isDefaultAndActive, listName, getPrivacyListItems(listName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer the default privacy list.
|
||||||
|
*
|
||||||
|
* @return the {@see PrivacyList} of the default list.
|
||||||
|
*/
|
||||||
|
public PrivacyList getDefaultList() throws XMPPException {
|
||||||
|
Privacy privacyAnswer = this.getPrivacyWithListNames();
|
||||||
|
String listName = privacyAnswer.getDefaultName();
|
||||||
|
boolean isDefaultAndActive = privacyAnswer.getActiveName() != null
|
||||||
|
&& privacyAnswer.getDefaultName() != null
|
||||||
|
&& privacyAnswer.getActiveName().equals(
|
||||||
|
privacyAnswer.getDefaultName());
|
||||||
|
return new PrivacyList(isDefaultAndActive, true, listName, getPrivacyListItems(listName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer the privacy list items under listName with the allowed and blocked permissions.
|
||||||
|
*
|
||||||
|
* @param listName the name of the list to get the allowed and blocked permissions.
|
||||||
|
* @return a list of {@link PrivacyItem} under the list listName.
|
||||||
|
*/
|
||||||
|
private List getPrivacyListItems(String listName) throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an privacy message with an empty list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setPrivacyList(listName, new ArrayList());
|
||||||
|
|
||||||
|
// Send the package to the server and get the answer
|
||||||
|
Privacy privacyAnswer = getRequest(request);
|
||||||
|
|
||||||
|
return privacyAnswer.getPrivacyList(listName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer the privacy list items under listName with the allowed and blocked permissions.
|
||||||
|
*
|
||||||
|
* @param listName the name of the list to get the allowed and blocked permissions.
|
||||||
|
* @return a {@link PrivacyList} under the list listName.
|
||||||
|
*/
|
||||||
|
public PrivacyList getPrivacyList(String listName) throws XMPPException {
|
||||||
|
|
||||||
|
PrivacyList list = new PrivacyList(false, false, listName, getPrivacyListItems(listName));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer every privacy list with the allowed and blocked permissions.
|
||||||
|
*
|
||||||
|
* @return a List of {@link PrivacyList}.
|
||||||
|
*/
|
||||||
|
public PrivacyList[] getPrivacyLists() throws XMPPException {
|
||||||
|
Privacy privacyAnswer = this.getPrivacyWithListNames();
|
||||||
|
Set names = privacyAnswer.getPrivacyListNames();
|
||||||
|
PrivacyList[] lists = new PrivacyList[names.size()];
|
||||||
|
String listName;
|
||||||
|
boolean isActiveList;
|
||||||
|
boolean isDefaultList;
|
||||||
|
int index=0;
|
||||||
|
for (Iterator iter = names.iterator(); iter.hasNext();) {
|
||||||
|
listName = (String) iter.next();
|
||||||
|
isActiveList = listName.equals(privacyAnswer.getActiveName());
|
||||||
|
isDefaultList = listName.equals(privacyAnswer.getDefaultName());
|
||||||
|
lists[index] = new PrivacyList(isActiveList, isDefaultList,
|
||||||
|
listName, getPrivacyListItems(listName));
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
return lists;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or change the active list to listName.
|
||||||
|
*
|
||||||
|
* @param listName the list name to set as the active one.
|
||||||
|
* @exception XMPPException if the request or the answer failed, it raises an exception.
|
||||||
|
*/
|
||||||
|
public void setActiveListName(String listName) throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an privacy message with an empty list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setActiveName(listName);
|
||||||
|
|
||||||
|
// Send the package to the server
|
||||||
|
setRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client declines the use of active lists.
|
||||||
|
*/
|
||||||
|
public void declineActiveList() throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an privacy message with an empty list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setDeclineActiveList(true);
|
||||||
|
|
||||||
|
// Send the package to the server
|
||||||
|
setRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or change the default list to listName.
|
||||||
|
*
|
||||||
|
* @param listName the list name to set as the default one.
|
||||||
|
* @exception XMPPException if the request or the answer failed, it raises an exception.
|
||||||
|
*/
|
||||||
|
public void setDefaultListName(String listName) throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an privacy message with an empty list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setDefaultName(listName);
|
||||||
|
|
||||||
|
// Send the package to the server
|
||||||
|
setRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client declines the use of default lists.
|
||||||
|
*/
|
||||||
|
public void declineDefaultList() throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an privacy message with an empty list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setDeclineDefaultList(true);
|
||||||
|
|
||||||
|
// Send the package to the server
|
||||||
|
setRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client has created a new list. It send the new one to the server.
|
||||||
|
*
|
||||||
|
* @param listName the list that has changed its content.
|
||||||
|
* @param privacyItems a List with every {@link PrivacyItem} in the list.
|
||||||
|
*/
|
||||||
|
public void createPrivacyList(String listName, List privacyItems) throws XMPPException {
|
||||||
|
|
||||||
|
this.updatePrivacyList(listName, privacyItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client has edited an existing list. It updates the server content with the resulting
|
||||||
|
* list of {@link PrivacyItem}. The {@link PrivacyItem} list MUST contain all elements in the
|
||||||
|
* list (not the "delta").
|
||||||
|
*
|
||||||
|
* @param listName the list that has changed its content.
|
||||||
|
* @param privacyItems a List with every {@link PrivacyItem} in the list.
|
||||||
|
*/
|
||||||
|
public void updatePrivacyList(String listName, List privacyItems) throws XMPPException {
|
||||||
|
|
||||||
|
// Build the privacy package to add or update the new list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setPrivacyList(listName, privacyItems);
|
||||||
|
|
||||||
|
// Send the package to the server
|
||||||
|
setRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a privacy list.
|
||||||
|
*
|
||||||
|
* @param listName the list that has changed its content.
|
||||||
|
*/
|
||||||
|
public void deletePrivacyList(String listName) throws XMPPException {
|
||||||
|
|
||||||
|
// The request of the list is an privacy message with an empty list
|
||||||
|
Privacy request = new Privacy();
|
||||||
|
request.setPrivacyList(listName, new ArrayList());
|
||||||
|
|
||||||
|
// Send the package to the server
|
||||||
|
setRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a packet listener that will be notified of any new update in the user
|
||||||
|
* privacy communication.
|
||||||
|
*
|
||||||
|
* @param listener a packet listener.
|
||||||
|
*/
|
||||||
|
public void addListener(PrivacyListListener listener) {
|
||||||
|
// Keep track of the listener so that we can manually deliver extra
|
||||||
|
// messages to it later if needed.
|
||||||
|
synchronized (listeners) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -277,16 +277,16 @@ public class XMPPConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (UnknownHostException uhe) {
|
catch (UnknownHostException uhe) {
|
||||||
throw new XMPPException(
|
String errorMessage = "Could not connect to " + host + ":" + port + ".";
|
||||||
"Could not connect to " + host + ":" + port + ".",
|
throw new XMPPException(errorMessage, new XMPPError(
|
||||||
new XMPPError(504),
|
XMPPError.Condition.remote_server_timeout, errorMessage),
|
||||||
uhe);
|
uhe);
|
||||||
}
|
}
|
||||||
catch (IOException ioe) {
|
catch (IOException ioe) {
|
||||||
throw new XMPPException(
|
String errorMessage = "XMPPError connecting to " + host + ":"
|
||||||
"XMPPError connecting to " + host + ":" + port + ".",
|
+ port + ".";
|
||||||
new XMPPError(502),
|
throw new XMPPException(errorMessage, new XMPPError(
|
||||||
ioe);
|
XMPPError.Condition.remote_server_error, errorMessage), ioe);
|
||||||
}
|
}
|
||||||
this.serviceName = config.getServiceName();
|
this.serviceName = config.getServiceName();
|
||||||
try {
|
try {
|
||||||
|
@ -967,7 +967,8 @@ public class XMPPConnection {
|
||||||
catch (IOException ioe) {
|
catch (IOException ioe) {
|
||||||
throw new XMPPException(
|
throw new XMPPException(
|
||||||
"XMPPError establishing connection with server.",
|
"XMPPError establishing connection with server.",
|
||||||
new XMPPError(502),
|
new XMPPError(XMPPError.Condition.remote_server_error,
|
||||||
|
"XMPPError establishing connection with server."),
|
||||||
ioe);
|
ioe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
315
source/org/jivesoftware/smack/packet/Privacy.java
Normal file
315
source/org/jivesoftware/smack/packet/Privacy.java
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Privacy IQ Packet, is used by the {@see PrivacyListManager} and {@see PrivacyProvider} to allow
|
||||||
|
* and block communications from other users. It contains the appropriate structure to suit
|
||||||
|
* user-defined privacy lists. Different configured Privacy packages are used in the Server –
|
||||||
|
* Manager communication in order to:
|
||||||
|
* <ul>
|
||||||
|
* <li>Retrieving one's privacy lists.
|
||||||
|
* <li>Adding, removing, and editing one's privacy lists.
|
||||||
|
* <li>Setting, changing, or declining active lists.
|
||||||
|
* <li>Setting, changing, or declining the default list (i.e., the list that is active by default).
|
||||||
|
* </ul>
|
||||||
|
* Privacy Items can handle different kind of blocking communications based on JID, group,
|
||||||
|
* subscription type or globally {@see PrivacyItem}
|
||||||
|
*
|
||||||
|
* @author Francisco Vives
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Privacy extends IQ {
|
||||||
|
/** declineActiveList is true when the user declines the use of the active list **/
|
||||||
|
private boolean declineActiveList=false;
|
||||||
|
/** activeName is the name associated with the active list set for the session **/
|
||||||
|
private String activeName;
|
||||||
|
/** declineDefaultList is true when the user declines the use of the default list **/
|
||||||
|
private boolean declineDefaultList=false;
|
||||||
|
/** defaultName is the name of the default list that applies to the user as a whole **/
|
||||||
|
private String defaultName;
|
||||||
|
/** itemLists holds the set of privacy items classified in lists. It is a map where the
|
||||||
|
* key is the name of the list and the value a collection with privacy items. **/
|
||||||
|
private Map itemLists = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or update a privacy list with {@link PrivacyItem}.
|
||||||
|
*
|
||||||
|
* @param listName the name of the new privacy list.
|
||||||
|
* @param listItem the {@link PrivacyItem} that rules the list.
|
||||||
|
* @return the privacy List.
|
||||||
|
*/
|
||||||
|
public List setPrivacyList(String listName, List listItem) {
|
||||||
|
// Add new list to the itemLists
|
||||||
|
this.getItemLists().put(listName, listItem);
|
||||||
|
return listItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the active list based on the default list.
|
||||||
|
*
|
||||||
|
* @return the active List.
|
||||||
|
*/
|
||||||
|
public List setActivePrivacyList() {
|
||||||
|
this.setActiveName(this.getDefaultName());
|
||||||
|
return (List) this.getItemLists().get(this.getActiveName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an existing privacy list. If the privacy list being deleted was the default list
|
||||||
|
* then the user will end up with no default list. Therefore, the user will have to set a new
|
||||||
|
* default list.
|
||||||
|
*
|
||||||
|
* @param listName the name of the list being deleted.
|
||||||
|
*/
|
||||||
|
public void deletePrivacyList(String listName) {
|
||||||
|
// Remove the list from the cache
|
||||||
|
this.getItemLists().remove(listName);
|
||||||
|
|
||||||
|
// Check if deleted list was the default list
|
||||||
|
if (this.getDefaultName() != null && listName.equals(this.getDefaultName())) {
|
||||||
|
this.setDefaultName(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the active privacy list or <tt>null</tt> if none was found.
|
||||||
|
*
|
||||||
|
* @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
|
||||||
|
*/
|
||||||
|
public List getActivePrivacyList() {
|
||||||
|
// Check if we have the default list
|
||||||
|
if (this.getActiveName() == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (List) this.getItemLists().get(this.getActiveName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default privacy list or <tt>null</tt> if none was found.
|
||||||
|
*
|
||||||
|
* @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
|
||||||
|
*/
|
||||||
|
public List getDefaultPrivacyList() {
|
||||||
|
// Check if we have the default list
|
||||||
|
if (this.getDefaultName() == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (List) this.getItemLists().get(this.getDefaultName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a specific privacy list.
|
||||||
|
*
|
||||||
|
* @param listName the name of the list to get.
|
||||||
|
* @return a List with {@link PrivacyItem}
|
||||||
|
*/
|
||||||
|
public List getPrivacyList(String listName) {
|
||||||
|
return (List) this.getItemLists().get(listName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the privacy item in the specified order.
|
||||||
|
*
|
||||||
|
* @param order the order of the element.
|
||||||
|
* @return a List with {@link PrivacyItem}
|
||||||
|
*/
|
||||||
|
public PrivacyItem getItem(String listName, int order) {
|
||||||
|
Iterator values = getPrivacyList(listName).iterator();
|
||||||
|
PrivacyItem itemFound = null;
|
||||||
|
while (itemFound == null && values.hasNext()) {
|
||||||
|
PrivacyItem element = (PrivacyItem) values.next();
|
||||||
|
if (element.getOrder() == order) {
|
||||||
|
itemFound = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a given privacy list as the new user default list.
|
||||||
|
*
|
||||||
|
* @param newDefault the new default privacy list.
|
||||||
|
* @return if the default list was changed.
|
||||||
|
*/
|
||||||
|
public boolean changeDefaultList(String newDefault) {
|
||||||
|
if (this.getItemLists().containsKey(newDefault)) {
|
||||||
|
this.setDefaultName(newDefault);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the list.
|
||||||
|
*
|
||||||
|
* @param listName name of the list to remove.
|
||||||
|
*/
|
||||||
|
public void deleteList(String listName) {
|
||||||
|
this.getItemLists().remove(listName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name associated with the active list set for the session. Communications
|
||||||
|
* will be verified against the active list.<p>
|
||||||
|
*
|
||||||
|
* @return the name of the active list.
|
||||||
|
*/
|
||||||
|
public String getActiveName() {
|
||||||
|
return activeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name associated with the active list set for the session. Communications
|
||||||
|
* will be verified against the active list.<p>
|
||||||
|
*
|
||||||
|
* @param activeName is the name of the active list.
|
||||||
|
*/
|
||||||
|
public void setActiveName(String activeName) {
|
||||||
|
this.activeName = activeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the default list that applies to the user as a whole. Default list is
|
||||||
|
* processed if there is no active list set for the target session/resource to which a stanza
|
||||||
|
* is addressed, or if there are no current sessions for the user.
|
||||||
|
*
|
||||||
|
* @return the name of the default list.
|
||||||
|
*/
|
||||||
|
public String getDefaultName() {
|
||||||
|
return defaultName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of the default list that applies to the user as a whole. Default list is
|
||||||
|
* processed if there is no active list set for the target session/resource to which a stanza
|
||||||
|
* is addressed, or if there are no current sessions for the user.
|
||||||
|
*
|
||||||
|
* If there is no default list set, then all Privacy Items are processed.
|
||||||
|
*
|
||||||
|
* @param defaultName is the name of the default list.
|
||||||
|
*/
|
||||||
|
public void setDefaultName(String defaultName) {
|
||||||
|
this.defaultName = defaultName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collection of privacy list that the user holds. A Privacy List contains a set of
|
||||||
|
* rules that define if communication with the list owner is allowed or denied.
|
||||||
|
* Users may have zero, one or more privacy items.
|
||||||
|
*
|
||||||
|
* @return a map where the key is the name of the list and the value the
|
||||||
|
* collection of privacy items.
|
||||||
|
*/
|
||||||
|
public Map getItemLists() {
|
||||||
|
return itemLists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allows or declines the use of an active list.
|
||||||
|
*
|
||||||
|
* @return the decline status of the list.
|
||||||
|
*/
|
||||||
|
public boolean isDeclineActiveList() {
|
||||||
|
return declineActiveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the receiver allows or declines the use of an active list.
|
||||||
|
*
|
||||||
|
* @param declineActiveList indicates if the receiver declines the use of an active list.
|
||||||
|
*/
|
||||||
|
public void setDeclineActiveList(boolean declineActiveList) {
|
||||||
|
this.declineActiveList = declineActiveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allows or declines the use of a default list.
|
||||||
|
*
|
||||||
|
* @return the decline status of the list.
|
||||||
|
*/
|
||||||
|
public boolean isDeclineDefaultList() {
|
||||||
|
return declineDefaultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the receiver allows or declines the use of a default list.
|
||||||
|
*
|
||||||
|
* @param declineActiveList indicates if the receiver declines the use of a default list.
|
||||||
|
*/
|
||||||
|
public void setDeclineDefaultList(boolean declineDefaultList) {
|
||||||
|
this.declineDefaultList = declineDefaultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the list names the user has defined to group restrictions.
|
||||||
|
*
|
||||||
|
* @return a Set with Strings containing every list names.
|
||||||
|
*/
|
||||||
|
public Set getPrivacyListNames() {
|
||||||
|
return this.itemLists.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChildElementXML() {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append("<query xmlns=\"jabber:iq:privacy\">");
|
||||||
|
|
||||||
|
// Add the active tag
|
||||||
|
if (this.isDeclineActiveList()) {
|
||||||
|
buf.append("<active/>");
|
||||||
|
} else {
|
||||||
|
if (this.getActiveName() != null) {
|
||||||
|
buf.append("<active name=\"").append(this.getActiveName()).append("\"/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add the default tag
|
||||||
|
if (this.isDeclineDefaultList()) {
|
||||||
|
buf.append("<default/>");
|
||||||
|
} else {
|
||||||
|
if (this.getDefaultName() != null) {
|
||||||
|
buf.append("<default name=\"").append(this.getDefaultName()).append("\"/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the list with their privacy items
|
||||||
|
int listNameSize = this.getItemLists().size();
|
||||||
|
Iterator listItemsPairs = this.getItemLists().entrySet().iterator();
|
||||||
|
for (int i = 0; i < listNameSize; i++) {
|
||||||
|
Map.Entry entry = (Map.Entry) listItemsPairs.next();
|
||||||
|
String listName = (String) entry.getKey();
|
||||||
|
List items = (List) entry.getValue();
|
||||||
|
// Begin the list tag
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
buf.append("<list name=\"").append(listName).append("\"/>");
|
||||||
|
} else {
|
||||||
|
buf.append("<list name=\"").append(listName).append("\">");
|
||||||
|
}
|
||||||
|
for (Iterator itemIterator = items.iterator(); itemIterator.hasNext();) {
|
||||||
|
PrivacyItem item = (PrivacyItem) itemIterator.next();
|
||||||
|
// Append the item xml representation
|
||||||
|
buf.append(item.toXML());
|
||||||
|
}
|
||||||
|
// Close the list tag
|
||||||
|
if (!items.isEmpty()) {
|
||||||
|
buf.append("</list>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add packet extensions, if any are defined.
|
||||||
|
buf.append(getExtensionsXML());
|
||||||
|
buf.append("</query>");
|
||||||
|
String generatedXML = buf.toString();
|
||||||
|
return generatedXML;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
454
source/org/jivesoftware/smack/packet/PrivacyItem.java
Normal file
454
source/org/jivesoftware/smack/packet/PrivacyItem.java
Normal file
|
@ -0,0 +1,454 @@
|
||||||
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A privacy item acts a rule that when matched defines if a packet should be blocked or not.
|
||||||
|
*
|
||||||
|
* Privacy Items can handle different kind of blocking communications based on JID, group,
|
||||||
|
* subscription type or globally by:<ul>
|
||||||
|
* <li>Allowing or blocking messages.
|
||||||
|
* <li>Allowing or blocking inbound presence notifications.
|
||||||
|
* <li>Allowing or blocking outbound presence notifications.
|
||||||
|
* <li>Allowing or blocking IQ stanzas.
|
||||||
|
* <li>Allowing or blocking all communications.
|
||||||
|
* </ul>
|
||||||
|
* @author Francisco Vives
|
||||||
|
*/
|
||||||
|
public class PrivacyItem {
|
||||||
|
/** allow is the action associated with the item, it can allow or deny the communication. */
|
||||||
|
private boolean allow;
|
||||||
|
/** order is a non-negative integer that is unique among all items in the list. */
|
||||||
|
private int order;
|
||||||
|
/** rule hold the kind of communication ([jid|group|subscription]) it will allow or block and
|
||||||
|
* identifier to apply the action.
|
||||||
|
* If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
|
||||||
|
* If the type is "group", then the 'value' attribute SHOULD contain the name of a group
|
||||||
|
* in the user's roster.
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
|
||||||
|
* "from", or "none". */
|
||||||
|
private PrivacyRule rule;
|
||||||
|
|
||||||
|
/** blocks incoming IQ stanzas. */
|
||||||
|
private boolean filterIQ = false;
|
||||||
|
/** filterMessage blocks incoming message stanzas. */
|
||||||
|
private boolean filterMessage = false;
|
||||||
|
/** blocks incoming presence notifications. */
|
||||||
|
private boolean filterPresence_in = false;
|
||||||
|
/** blocks outgoing presence notifications. */
|
||||||
|
private boolean filterPresence_out = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new privacy item.
|
||||||
|
*
|
||||||
|
* @param type the type.
|
||||||
|
*/
|
||||||
|
public PrivacyItem(String type, boolean allow, int order) {
|
||||||
|
this.setRule(PrivacyRule.fromString(type));
|
||||||
|
this.setAllow(allow);
|
||||||
|
this.setOrder(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the action associated with the item, it MUST be filled and will allow or deny
|
||||||
|
* the communication.
|
||||||
|
*
|
||||||
|
* @return the allow communication status.
|
||||||
|
*/
|
||||||
|
public boolean isAllow() {
|
||||||
|
return allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the action associated with the item, it can allow or deny the communication.
|
||||||
|
*
|
||||||
|
* @param allow indicates if the receiver allow or deny the communication.
|
||||||
|
*/
|
||||||
|
private void setAllow(boolean allow) {
|
||||||
|
this.allow = allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allow or deny incoming IQ stanzas or not.
|
||||||
|
*
|
||||||
|
* @return the iq filtering status.
|
||||||
|
*/
|
||||||
|
public boolean isFilterIQ() {
|
||||||
|
return filterIQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the receiver allows or denies incoming IQ stanzas or not.
|
||||||
|
*
|
||||||
|
* @param filterIQ indicates if the receiver allows or denies incoming IQ stanzas.
|
||||||
|
*/
|
||||||
|
public void setFilterIQ(boolean filterIQ) {
|
||||||
|
this.filterIQ = filterIQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allows or denies incoming messages or not.
|
||||||
|
*
|
||||||
|
* @return the message filtering status.
|
||||||
|
*/
|
||||||
|
public boolean isFilterMessage() {
|
||||||
|
return filterMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets wheather the receiver allows or denies incoming messages or not.
|
||||||
|
*
|
||||||
|
* @param filterMessage indicates if the receiver allows or denies incoming messages or not.
|
||||||
|
*/
|
||||||
|
public void setFilterMessage(boolean filterMessage) {
|
||||||
|
this.filterMessage = filterMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allows or denies incoming presence or not.
|
||||||
|
*
|
||||||
|
* @return the iq filtering incoming presence status.
|
||||||
|
*/
|
||||||
|
public boolean isFilterPresence_in() {
|
||||||
|
return filterPresence_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the receiver allows or denies incoming presence or not.
|
||||||
|
*
|
||||||
|
* @param filterPresence_in indicates if the receiver allows or denies filtering incoming presence.
|
||||||
|
*/
|
||||||
|
public void setFilterPresence_in(boolean filterPresence_in) {
|
||||||
|
this.filterPresence_in = filterPresence_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allows or denies incoming presence or not.
|
||||||
|
*
|
||||||
|
* @return the iq filtering incoming presence status.
|
||||||
|
*/
|
||||||
|
public boolean isFilterPresence_out() {
|
||||||
|
return filterPresence_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the receiver allows or denies outgoing presence or not.
|
||||||
|
*
|
||||||
|
* @param filterPresence_out indicates if the receiver allows or denies filtering outgoing presence
|
||||||
|
*/
|
||||||
|
public void setFilterPresence_out(boolean filterPresence_out) {
|
||||||
|
this.filterPresence_out = filterPresence_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the order where the receiver is processed. List items are processed in
|
||||||
|
* ascending order.
|
||||||
|
*
|
||||||
|
* The order MUST be filled and its value MUST be a non-negative integer
|
||||||
|
* that is unique among all items in the list.
|
||||||
|
*
|
||||||
|
* @return the order number.
|
||||||
|
*/
|
||||||
|
public int getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the order where the receiver is processed.
|
||||||
|
*
|
||||||
|
* The order MUST be filled and its value MUST be a non-negative integer
|
||||||
|
* that is unique among all items in the list.
|
||||||
|
*
|
||||||
|
* @param order indicates the order in the list.
|
||||||
|
*/
|
||||||
|
private void setOrder(int order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the element identifier to apply the action.
|
||||||
|
*
|
||||||
|
* If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
|
||||||
|
* If the type is "group", then the 'value' attribute SHOULD contain the name of a group
|
||||||
|
* in the user's roster.
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
|
||||||
|
* "from", or "none".
|
||||||
|
*
|
||||||
|
* @param value is the identifier to apply the action.
|
||||||
|
*/
|
||||||
|
public void setValue(String value) {
|
||||||
|
if (!(this.getRule() == null && value == null)) {
|
||||||
|
this.getRule().setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type hold the kind of communication it will allow or block.
|
||||||
|
* It MUST be filled with one of these values: jid, group or subscription.
|
||||||
|
*
|
||||||
|
* @return the type of communication it represent.
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
if (this.getRule() == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return this.getRule().getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the element identifier to apply the action.
|
||||||
|
*
|
||||||
|
* If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
|
||||||
|
* If the type is "group", then the 'value' attribute SHOULD contain the name of a group
|
||||||
|
* in the user's roster.
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
|
||||||
|
* "from", or "none".
|
||||||
|
*
|
||||||
|
* @return the identifier to apply the action.
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
if (this.getRule() == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return this.getRule().getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver allows or denies every kind of communication.
|
||||||
|
*
|
||||||
|
* When filterIQ, filterMessage, filterPresence_in and filterPresence_out are not set
|
||||||
|
* the receiver will block all communications.
|
||||||
|
*
|
||||||
|
* @return the all communications status.
|
||||||
|
*/
|
||||||
|
public boolean isFilterEverything() {
|
||||||
|
return !(this.isFilterIQ() || this.isFilterMessage() || this.isFilterPresence_in()
|
||||||
|
|| this.isFilterPresence_out());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private PrivacyRule getRule() {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRule(PrivacyRule rule) {
|
||||||
|
this.rule = rule;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Answer an xml representation of the receiver according to the RFC 3921.
|
||||||
|
*
|
||||||
|
* @return the text xml representation.
|
||||||
|
*/
|
||||||
|
public String toXML() {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append("<item");
|
||||||
|
if (this.isAllow()) {
|
||||||
|
buf.append(" action=\"allow\"");
|
||||||
|
} else {
|
||||||
|
buf.append(" action=\"deny\"");
|
||||||
|
}
|
||||||
|
buf.append(" order=\"").append(getOrder()).append("\"");
|
||||||
|
if (getType() != null) {
|
||||||
|
buf.append(" type=\"").append(getType()).append("\"");
|
||||||
|
}
|
||||||
|
if (getValue() != null) {
|
||||||
|
buf.append(" value=\"").append(getValue()).append("\"");
|
||||||
|
}
|
||||||
|
if (isFilterEverything()) {
|
||||||
|
buf.append("/>");
|
||||||
|
} else {
|
||||||
|
buf.append(">");
|
||||||
|
if (this.isFilterIQ()) {
|
||||||
|
buf.append("<iq/>");
|
||||||
|
}
|
||||||
|
if (this.isFilterMessage()) {
|
||||||
|
buf.append("<message/>");
|
||||||
|
}
|
||||||
|
if (this.isFilterPresence_in()) {
|
||||||
|
buf.append("<presence-in/>");
|
||||||
|
}
|
||||||
|
if (this.isFilterPresence_out()) {
|
||||||
|
buf.append("<presence-out/>");
|
||||||
|
}
|
||||||
|
buf.append("</item>");
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privacy Rule represents the kind of action to apply.
|
||||||
|
* It holds the kind of communication ([jid|group|subscription]) it will allow or block and
|
||||||
|
* identifier to apply the action.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static class PrivacyRule {
|
||||||
|
/**
|
||||||
|
* Type defines if the rule is based on JIDs, roster groups or presence subscription types.
|
||||||
|
* Available values are: [jid|group|subscription]
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* The value hold the element identifier to apply the action.
|
||||||
|
* If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
|
||||||
|
* If the type is "group", then the 'value' attribute SHOULD contain the name of a group
|
||||||
|
* in the user's roster.
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
|
||||||
|
* "from", or "none".
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JID being analyzed should have a resource match, domain match or bare JID match.
|
||||||
|
*/
|
||||||
|
public static final String GROUP = "group";
|
||||||
|
/**
|
||||||
|
* JID being analyzed should belong to a roster group of the list's owner.
|
||||||
|
*/
|
||||||
|
public static final String JID = "jid";
|
||||||
|
/**
|
||||||
|
* JID being analyzed should belong to a contact present in the owner's roster with
|
||||||
|
* the specified subscription status.
|
||||||
|
*/
|
||||||
|
public static final String SUBSCRIPTION = "subscription";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both",
|
||||||
|
* "to", "from", or "none"
|
||||||
|
*/
|
||||||
|
public static final String SUBSCRIPTION_BOTH = "subscription";
|
||||||
|
public static final String SUBSCRIPTION_TO = "to";
|
||||||
|
public static final String SUBSCRIPTION_FROM = "from";
|
||||||
|
public static final String SUBSCRIPTION_NONE = "none";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type constant associated with the String value.
|
||||||
|
*/
|
||||||
|
protected static PrivacyRule fromString(String value) {
|
||||||
|
String type = null;
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (SUBSCRIPTION.equalsIgnoreCase(value)) {
|
||||||
|
type = SUBSCRIPTION;
|
||||||
|
}
|
||||||
|
else if (GROUP.equalsIgnoreCase(value)) {
|
||||||
|
type = GROUP;
|
||||||
|
}
|
||||||
|
else if (JID.equalsIgnoreCase(value)) {
|
||||||
|
type = JID;
|
||||||
|
}
|
||||||
|
// Default to available.
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PrivacyRule rule = new PrivacyRule();
|
||||||
|
rule.setType(type);
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type hold the kind of communication it will allow or block.
|
||||||
|
* It MUST be filled with one of these values: jid, group or subscription.
|
||||||
|
*
|
||||||
|
* @return the type of communication it represent.
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the action associated with the item, it can allow or deny the communication.
|
||||||
|
*
|
||||||
|
* @param allow indicates if the receiver allows or denies the communication.
|
||||||
|
*/
|
||||||
|
private void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the element identifier to apply the action.
|
||||||
|
*
|
||||||
|
* If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
|
||||||
|
* If the type is "group", then the 'value' attribute SHOULD contain the name of a group
|
||||||
|
* in the user's roster.
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
|
||||||
|
* "from", or "none".
|
||||||
|
*
|
||||||
|
* @return the identifier to apply the action.
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the element identifier to apply the action.
|
||||||
|
*
|
||||||
|
* If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
|
||||||
|
* If the type is "group", then the 'value' attribute SHOULD contain the name of a group
|
||||||
|
* in the user's roster.
|
||||||
|
* If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
|
||||||
|
* "from", or "none".
|
||||||
|
*
|
||||||
|
* @param value is the identifier to apply the action.
|
||||||
|
*/
|
||||||
|
protected void setValue(String value) {
|
||||||
|
if (this.isSuscription()) {
|
||||||
|
setSuscriptionValue(value);
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the element identifier to apply the action.
|
||||||
|
*
|
||||||
|
* The 'value' attribute MUST be one of "both", "to", "from", or "none".
|
||||||
|
*
|
||||||
|
* @param value is the identifier to apply the action.
|
||||||
|
*/
|
||||||
|
private void setSuscriptionValue(String value) {
|
||||||
|
String setValue = null;
|
||||||
|
if (value == null) {
|
||||||
|
setValue = null;
|
||||||
|
}
|
||||||
|
if (SUBSCRIPTION_BOTH.equalsIgnoreCase(value)) {
|
||||||
|
setValue = SUBSCRIPTION_BOTH;
|
||||||
|
}
|
||||||
|
else if (SUBSCRIPTION_TO.equalsIgnoreCase(value)) {
|
||||||
|
setValue = SUBSCRIPTION_TO;
|
||||||
|
}
|
||||||
|
else if (SUBSCRIPTION_FROM.equalsIgnoreCase(value)) {
|
||||||
|
setValue = SUBSCRIPTION_FROM;
|
||||||
|
}
|
||||||
|
else if (SUBSCRIPTION_NONE.equalsIgnoreCase(value)) {
|
||||||
|
setValue = SUBSCRIPTION_NONE;
|
||||||
|
}
|
||||||
|
// Default to available.
|
||||||
|
else {
|
||||||
|
setValue = null;
|
||||||
|
}
|
||||||
|
this.value = setValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the receiver represents a subscription rule.
|
||||||
|
*
|
||||||
|
* @return if the receiver represents a subscription rule.
|
||||||
|
*/
|
||||||
|
public boolean isSuscription () {
|
||||||
|
return this.getValue() == SUBSCRIPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,29 +20,43 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack.packet;
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a XMPP error sub-packet. Typically, a server responds to a request that has
|
* Represents a XMPP error sub-packet. Typically, a server responds to a request that has
|
||||||
* problems by sending the packet back and including an error packet. Each error has a code
|
* problems by sending the packet back and including an error packet. Each error has a code, type,
|
||||||
* as well as as an optional text explanation. Typical error codes are as follows:<p>
|
* error condition as well as as an optional text explanation. Typical errors are:<p>
|
||||||
*
|
*
|
||||||
* <table border=1>
|
* <table border=1>
|
||||||
* <tr><td><b>Code</b></td><td><b>Description</b></td></tr>
|
* <hr><td><b>Code</b></td><td><b>XMPP Error</b></td><td><b>Type</b></td></hr>
|
||||||
* <tr><td> 302 </td><td> Redirect </td></tr>
|
* <tr><td>500</td><td>interna-server-error</td><td>WAIT</td></tr>
|
||||||
* <tr><td> 400 </td><td> Bad Request </td></tr>
|
* <tr><td>403</td><td>forbidden</td><td>AUTH</td></tr>
|
||||||
* <tr><td> 401 </td><td> Unauthorized </td></tr>
|
* <tr><td>400</td<td>bad-request</td><td>MODIFY</td>></tr>
|
||||||
* <tr><td> 402 </td><td> Payment Required </td></tr>
|
* <tr><td>404</td><td>item-not-found</td><td>CANCEL</td></tr>
|
||||||
* <tr><td> 403 </td><td> Forbidden </td></tr>
|
* <tr><td>409</td><td>conflict</td><td>CANCEL</td></tr>
|
||||||
* <tr><td> 404 </td><td> Not Found </td></tr>
|
* <tr><td>501</td><td>feature-not-implemented</td><td>CANCEL</td></tr>
|
||||||
* <tr><td> 405 </td><td> Not Allowed </td></tr>
|
* <tr><td>302</td><td>gone</td><td>MODIFY</td></tr>
|
||||||
* <tr><td> 406 </td><td> Not Acceptable </td></tr>
|
* <tr><td>400</td><td>jid-malformed</td><td>MODIFY</td></tr>
|
||||||
* <tr><td> 407 </td><td> Registration Required </td></tr>
|
* <tr><td>406</td><td>no-acceptable</td><td> MODIFY</td></tr>
|
||||||
* <tr><td> 408 </td><td> Request Timeout </td></tr>
|
* <tr><td>405</td><td>not-allowed</td><td>CANCEL</td></tr>
|
||||||
* <tr><td> 409 </td><td> Conflict </td></tr>
|
* <tr><td>401</td><td>not-authorized</td><td>AUTH</td></tr>
|
||||||
* <tr><td> 500 </td><td> Internal Server XMPPError </td></tr>
|
* <tr><td>402</td><td>payment-required</td><td>AUTH</td></tr>
|
||||||
* <tr><td> 501 </td><td> Not Implemented </td></tr>
|
* <tr><td>404</td><td>recipient-unavailable</td><td>WAIT</td></tr>
|
||||||
* <tr><td> 502 </td><td> Remote Server Error </td></tr>
|
* <tr><td>302</td><td>redirect</td><td>MODIFY</td></tr>
|
||||||
* <tr><td> 503 </td><td> Service Unavailable </td></tr>
|
* <tr><td>407</td><td>registration-required</td><td>AUTH</td></tr>
|
||||||
* <tr><td> 504 </td><td> Remote Server Timeout </td></tr>
|
* <tr><td>404</td><td>remote-server-not-found</td><td>CANCEL</td></tr>
|
||||||
|
* <tr><td>504</td><td>remote-server-timeout</td><td>WAIT</td></tr>
|
||||||
|
* <tr><td>502</td><td>remote-server-error</td><td>CANCEL</td></tr>
|
||||||
|
* <tr><td>500</td><td>resource-constraint</td><td>WAIT</td></tr>
|
||||||
|
* <tr><td>503</td><td>service-unavailable</td><td>CANCEL</td></tr>
|
||||||
|
* <tr><td>407</td><td>subscription-required</td><td>AUTH</td></tr>
|
||||||
|
* <tr><td>500</td><td>undefined-condition</td><td>WAIT</td></tr>
|
||||||
|
* <tr><td>400</td><td>unexpected-condition</td><td>WAIT</td></tr>
|
||||||
|
* <tr><td>408</td><td>request-timeout</td><td>CANCEL</td></tr>
|
||||||
* </table>
|
* </table>
|
||||||
*
|
*
|
||||||
* @author Matt Tucker
|
* @author Matt Tucker
|
||||||
|
@ -50,13 +64,47 @@ package org.jivesoftware.smack.packet;
|
||||||
public class XMPPError {
|
public class XMPPError {
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
|
private Type type;
|
||||||
|
private String condition;
|
||||||
private String message;
|
private String message;
|
||||||
|
private List applicationExtensions = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new error with the specified code and no message..
|
* Creates a new error with the specified condition infering the type and code.
|
||||||
|
* If the Condition is predefined, client code should be like:
|
||||||
|
* new XMPPError(XMPPError.Condition.remote_server_timeout);
|
||||||
|
* If the Condition is not predefined, invocations should be like
|
||||||
|
* new XMPPError(new XMPPError.Condition("my_own_error"));
|
||||||
*
|
*
|
||||||
* @param code the error code.
|
* @param code the error code.
|
||||||
*/
|
*/
|
||||||
|
public XMPPError(Condition condition) {
|
||||||
|
this.init(condition);
|
||||||
|
this.message = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new error with the specified condition and message infering the type and code.
|
||||||
|
* If the Condition is predefined, client code should be like:
|
||||||
|
* new XMPPError(XMPPError.Condition.remote_server_timeout, "Error Explanation");
|
||||||
|
* If the Condition is not predefined, invocations should be like
|
||||||
|
* new XMPPError(new XMPPError.Condition("my_own_error"), "Error Explanation");
|
||||||
|
*
|
||||||
|
* @param code the error code.
|
||||||
|
* @param message a message describing the error.
|
||||||
|
*/
|
||||||
|
public XMPPError(Condition condition, String messageText) {
|
||||||
|
this.init(condition);
|
||||||
|
this.message = messageText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new error with the specified code and no message.
|
||||||
|
*
|
||||||
|
* @param code the error code.
|
||||||
|
* @Deprecated new errors should be created using the constructor XMPPError(condition)
|
||||||
|
*/
|
||||||
public XMPPError(int code) {
|
public XMPPError(int code) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = null;
|
this.message = null;
|
||||||
|
@ -64,15 +112,71 @@ public class XMPPError {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new error with the specified code and message.
|
* Creates a new error with the specified code and message.
|
||||||
|
* deprecated
|
||||||
*
|
*
|
||||||
* @param code the error code.
|
* @param code the error code.
|
||||||
* @param message a message describing the error.
|
* @param message a message describing the error.
|
||||||
|
* @Deprecated new errors should be created using the constructor XMPPError(condition, message)
|
||||||
*/
|
*/
|
||||||
public XMPPError(int code, String message) {
|
public XMPPError(int code, String message) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new error with the specified code, type, condition and message.
|
||||||
|
* This constructor is used when the condition is not recognized automatically by XMPPError
|
||||||
|
* i.e. there is not a defined instance of ErrorCondition or it does not applies the default
|
||||||
|
* specification.
|
||||||
|
*
|
||||||
|
* @param code the error code.
|
||||||
|
* @param type the error type.
|
||||||
|
* @param condition the error condition.
|
||||||
|
* @param message a message describing the error.
|
||||||
|
*/
|
||||||
|
public XMPPError(int code, Type type, String condition, String message, List extension) {
|
||||||
|
this.code = code;
|
||||||
|
this.type = type;
|
||||||
|
this.condition = condition;
|
||||||
|
this.message = message;
|
||||||
|
this.applicationExtensions = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the error infering the type and code for the received condition.
|
||||||
|
*
|
||||||
|
* @param condition the error condition.
|
||||||
|
*/
|
||||||
|
private void init(Condition condition) {
|
||||||
|
// Look for the condition and its default code and type
|
||||||
|
ErrorSpecification defaultErrorSpecification = ErrorSpecification.specFor(condition);
|
||||||
|
this.condition = condition.value;
|
||||||
|
if (defaultErrorSpecification != null) {
|
||||||
|
// If there is a default error specification for the received condition,
|
||||||
|
// it get configured with the infered type and code.
|
||||||
|
this.type = defaultErrorSpecification.getType();
|
||||||
|
this.code = defaultErrorSpecification.getCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the error condition.
|
||||||
|
*
|
||||||
|
* @return the error condition.
|
||||||
|
*/
|
||||||
|
public String getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error type.
|
||||||
|
*
|
||||||
|
* @return the error type.
|
||||||
|
*/
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error code.
|
* Returns the error code.
|
||||||
*
|
*
|
||||||
|
@ -97,21 +201,299 @@ public class XMPPError {
|
||||||
* @return the error as XML.
|
* @return the error as XML.
|
||||||
*/
|
*/
|
||||||
public String toXML() {
|
public String toXML() {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuffer buf = new StringBuffer();
|
||||||
buf.append("<error code=\"").append(code).append("\">");
|
buf.append("<error code=\"").append(code).append("\"");
|
||||||
|
if (type != null) {
|
||||||
|
buf.append(" type=\"");
|
||||||
|
buf.append(type.value);
|
||||||
|
buf.append("\"");
|
||||||
|
}
|
||||||
|
buf.append(">");
|
||||||
|
if (condition != null) {
|
||||||
|
buf.append("<").append(condition);
|
||||||
|
buf.append(" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>");
|
||||||
|
}
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
|
buf.append("<text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">");
|
||||||
buf.append(message);
|
buf.append(message);
|
||||||
|
buf.append("</text>");
|
||||||
|
}
|
||||||
|
for (Iterator extensions = this.getExtensions(); extensions.hasNext();) {
|
||||||
|
PacketExtension element = (PacketExtension) extensions.next();
|
||||||
|
buf.append(element.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</error>");
|
buf.append("</error>");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder txt = new StringBuilder();
|
StringBuffer txt = new StringBuffer();
|
||||||
txt.append("(").append(code).append(")");
|
txt.append("(").append(code).append(")");
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
txt.append(" ").append(message);
|
txt.append(" ").append(message);
|
||||||
}
|
}
|
||||||
return txt.toString();
|
return txt.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an Iterator for the error extensions attached to the xmppError.
|
||||||
|
* An application MAY provide application-specific error information by including a
|
||||||
|
* properly-namespaced child in the error element.
|
||||||
|
*
|
||||||
|
* @return an Iterator for the error extensions.
|
||||||
|
*/
|
||||||
|
public synchronized Iterator getExtensions() {
|
||||||
|
if (applicationExtensions == null) {
|
||||||
|
return Collections.EMPTY_LIST.iterator();
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(new ArrayList(applicationExtensions)).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first patcket extension that matches the specified element name and
|
||||||
|
* namespace, or <tt>null</tt> if it doesn't exist.
|
||||||
|
*
|
||||||
|
* @param elementName the XML element name of the packet extension.
|
||||||
|
* @param namespace the XML element namespace of the packet extension.
|
||||||
|
* @return the extension, or <tt>null</tt> if it doesn't exist.
|
||||||
|
*/
|
||||||
|
public synchronized PacketExtension getExtension(String elementName, String namespace) {
|
||||||
|
if (applicationExtensions == null || elementName == null || namespace == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (Iterator i=applicationExtensions.iterator(); i.hasNext(); ) {
|
||||||
|
PacketExtension ext = (PacketExtension)i.next();
|
||||||
|
if (elementName.equals(ext.getElementName()) && namespace.equals(ext.getNamespace())) {
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a packet extension to the error.
|
||||||
|
*
|
||||||
|
* @param extension a packet extension.
|
||||||
|
*/
|
||||||
|
public synchronized void addExtension(PacketExtension extension) {
|
||||||
|
if (applicationExtensions == null) {
|
||||||
|
applicationExtensions = new ArrayList();
|
||||||
|
}
|
||||||
|
applicationExtensions.add(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the packet extension to the error.
|
||||||
|
*
|
||||||
|
* @param extension a packet extension.
|
||||||
|
*/
|
||||||
|
public synchronized void setExtension(List extension) {
|
||||||
|
applicationExtensions = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to represent the type of the Error. The types are:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>XMPPError.Type.WAIT - retry after waiting (the error is temporary)
|
||||||
|
* <li>XMPPError.Type.CANCEL - do not retry (the error is unrecoverable)
|
||||||
|
* <li>XMPPError.Type.MODIFY - retry after changing the data sent
|
||||||
|
* <li>XMPPError.Type.AUTH - retry after providing credentials
|
||||||
|
* <li>XMPPError.Type.CONTINUE - proceed (the condition was only a warning)
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static class Type {
|
||||||
|
|
||||||
|
public static final Type WAIT = new Type("wait");
|
||||||
|
public static final Type CANCEL = new Type("cancel");
|
||||||
|
public static final Type MODIFY = new Type("modify");
|
||||||
|
public static final Type AUTH = new Type("auth");
|
||||||
|
public static final Type CONTINUE = new Type("continue");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a String into the corresponding types. Valid String values
|
||||||
|
* that can be converted to types are: "wait", "cancel", "modify", "auth" or a user defined.
|
||||||
|
*
|
||||||
|
* @param type the String value to covert.
|
||||||
|
* @return the corresponding Type.
|
||||||
|
*/
|
||||||
|
public static Type fromString(String type) {
|
||||||
|
if (type == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
type = type.toLowerCase();
|
||||||
|
if (CANCEL.toString().equals(type)) {
|
||||||
|
return CANCEL;
|
||||||
|
}
|
||||||
|
else if (CONTINUE.toString().equals(type)) {
|
||||||
|
return CONTINUE;
|
||||||
|
}
|
||||||
|
else if (WAIT.toString().equals(type)) {
|
||||||
|
return WAIT;
|
||||||
|
}
|
||||||
|
else if (MODIFY.toString().equals(type)) {
|
||||||
|
return MODIFY;
|
||||||
|
}
|
||||||
|
else if (AUTH.toString().equals(type)) {
|
||||||
|
return AUTH;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
private Type(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to represent predefined error conditions.
|
||||||
|
*/
|
||||||
|
public static class Condition {
|
||||||
|
|
||||||
|
public static final Condition interna_server_error = new Condition("internal-server-error");
|
||||||
|
public static final Condition forbidden = new Condition("forbidden");
|
||||||
|
public static final Condition bad_request = new Condition("bad-request");
|
||||||
|
public static final Condition conflict = new Condition("conflict");
|
||||||
|
public static final Condition feature_not_implemented = new Condition("feature-not-implemented");
|
||||||
|
public static final Condition gone = new Condition("gone");
|
||||||
|
public static final Condition item_not_found = new Condition("item-not-found");
|
||||||
|
public static final Condition jid_malformed = new Condition("jid-malformed");
|
||||||
|
public static final Condition no_acceptable = new Condition("not-acceptable");
|
||||||
|
public static final Condition not_allowed = new Condition("not-allowed");
|
||||||
|
public static final Condition not_authorized = new Condition("not-authorized");
|
||||||
|
public static final Condition payment_required = new Condition("payment-required");
|
||||||
|
public static final Condition recipient_unavailable = new Condition("recipient-unavailable");
|
||||||
|
public static final Condition redirect = new Condition("redirect");
|
||||||
|
public static final Condition registration_required = new Condition("registration-required");
|
||||||
|
public static final Condition remote_server_error = new Condition("remote-server-error");
|
||||||
|
public static final Condition remote_server_not_found = new Condition("remote-server-not-found");
|
||||||
|
public static final Condition remote_server_timeout = new Condition("remote-server-timeout");
|
||||||
|
public static final Condition resource_constraint = new Condition("resource-constraint");
|
||||||
|
public static final Condition service_unavailable = new Condition("service-unavailable");
|
||||||
|
public static final Condition subscription_required = new Condition("subscription-required");
|
||||||
|
public static final Condition undefined_condition = new Condition("undefined-condition");
|
||||||
|
public static final Condition unexpected_condition = new Condition("unexpected-condition");
|
||||||
|
public static final Condition request_timeout = new Condition("request-timeout");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public Condition(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to represent the error specification used to infer common usage.
|
||||||
|
*/
|
||||||
|
private static class ErrorSpecification {
|
||||||
|
private int code;
|
||||||
|
private Type type;
|
||||||
|
private Condition condition;
|
||||||
|
private static HashMap instances = errorSpecifications();
|
||||||
|
|
||||||
|
private ErrorSpecification(Condition condition, Type type, int code) {
|
||||||
|
this.code = code;
|
||||||
|
this.type = type;
|
||||||
|
this.condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashMap errorSpecifications() {
|
||||||
|
HashMap instances = new HashMap(22);
|
||||||
|
instances.put(Condition.interna_server_error, new ErrorSpecification(
|
||||||
|
Condition.interna_server_error, Type.WAIT, 500));
|
||||||
|
instances.put(Condition.forbidden, new ErrorSpecification(Condition.forbidden,
|
||||||
|
Type.AUTH, 403));
|
||||||
|
instances.put(Condition.bad_request, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.bad_request, Type.MODIFY, 400));
|
||||||
|
instances.put(Condition.item_not_found, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.item_not_found, Type.CANCEL, 404));
|
||||||
|
instances.put(Condition.conflict, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.conflict, Type.CANCEL, 409));
|
||||||
|
instances.put(Condition.feature_not_implemented, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.feature_not_implemented, Type.CANCEL, 501));
|
||||||
|
instances.put(Condition.gone, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.gone, Type.MODIFY, 302));
|
||||||
|
instances.put(Condition.jid_malformed, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.jid_malformed, Type.MODIFY, 400));
|
||||||
|
instances.put(Condition.no_acceptable, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.no_acceptable, Type.MODIFY, 406));
|
||||||
|
instances.put(Condition.not_allowed, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.not_allowed, Type.CANCEL, 405));
|
||||||
|
instances.put(Condition.not_authorized, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.not_authorized, Type.AUTH, 401));
|
||||||
|
instances.put(Condition.payment_required, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.payment_required, Type.AUTH, 402));
|
||||||
|
instances.put(Condition.recipient_unavailable, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.recipient_unavailable, Type.WAIT, 404));
|
||||||
|
instances.put(Condition.redirect, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.redirect, Type.MODIFY, 302));
|
||||||
|
instances.put(Condition.registration_required, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.registration_required, Type.AUTH, 407));
|
||||||
|
instances.put(Condition.remote_server_not_found, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.remote_server_not_found, Type.CANCEL, 404));
|
||||||
|
instances.put(Condition.remote_server_timeout, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.remote_server_timeout, Type.WAIT, 504));
|
||||||
|
instances.put(Condition.remote_server_error, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.remote_server_error, Type.CANCEL, 502));
|
||||||
|
instances.put(Condition.resource_constraint, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.resource_constraint, Type.WAIT, 500));
|
||||||
|
instances.put(Condition.service_unavailable, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.service_unavailable, Type.CANCEL, 503));
|
||||||
|
instances.put(Condition.subscription_required, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.subscription_required, Type.AUTH, 407));
|
||||||
|
instances.put(Condition.undefined_condition, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.undefined_condition, Type.WAIT, 500));
|
||||||
|
instances.put(Condition.unexpected_condition, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.unexpected_condition, Type.WAIT, 400));
|
||||||
|
instances.put(Condition.request_timeout, new XMPPError.ErrorSpecification(
|
||||||
|
Condition.request_timeout, Type.CANCEL, 408));
|
||||||
|
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static ErrorSpecification specFor(Condition condition) {
|
||||||
|
return (ErrorSpecification) instances.get(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error condition.
|
||||||
|
*
|
||||||
|
* @return the error condition.
|
||||||
|
*/
|
||||||
|
protected Condition getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error type.
|
||||||
|
*
|
||||||
|
* @return the error type.
|
||||||
|
*/
|
||||||
|
protected Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the error code.
|
||||||
|
*
|
||||||
|
* @return the error code.
|
||||||
|
*/
|
||||||
|
protected int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
134
source/org/jivesoftware/smack/provider/PrivacyProvider.java
Normal file
134
source/org/jivesoftware/smack/provider/PrivacyProvider.java
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
package org.jivesoftware.smack.provider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.DefaultPacketExtension;
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.Privacy;
|
||||||
|
import org.jivesoftware.smack.packet.PrivacyItem;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PrivacyProvider parses {@link Privacy} packets. {@link Privacy}
|
||||||
|
* Parses the <tt>query</tt> sub-document and creates an instance of {@link Privacy}.
|
||||||
|
* For each <tt>item</tt> in the <tt>list</tt> element, it creates an instance
|
||||||
|
* of {@link PrivacyItem} and {@link PrivacyRule}.
|
||||||
|
*
|
||||||
|
* @author Francisco Vives
|
||||||
|
*/
|
||||||
|
public class PrivacyProvider implements IQProvider {
|
||||||
|
|
||||||
|
public PrivacyProvider() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ parseIQ(XmlPullParser parser) throws Exception {
|
||||||
|
Privacy privacy = new Privacy();
|
||||||
|
/* privacy.addExtension(PacketParserUtils.parsePacketExtension(parser
|
||||||
|
.getName(), parser.getNamespace(), parser)); */
|
||||||
|
privacy.addExtension(new DefaultPacketExtension(parser.getName(), parser.getNamespace()));
|
||||||
|
boolean done = false;
|
||||||
|
while (!done) {
|
||||||
|
int eventType = parser.next();
|
||||||
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
|
if (parser.getName().equals("active")) {
|
||||||
|
String activeName = parser.getAttributeValue("", "name");
|
||||||
|
if (activeName == null) {
|
||||||
|
privacy.setDeclineActiveList(true);
|
||||||
|
} else {
|
||||||
|
privacy.setActiveName(activeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parser.getName().equals("default")) {
|
||||||
|
String defaultName = parser.getAttributeValue("", "name");
|
||||||
|
if (defaultName == null) {
|
||||||
|
privacy.setDeclineDefaultList(true);
|
||||||
|
} else {
|
||||||
|
privacy.setDefaultName(defaultName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parser.getName().equals("list")) {
|
||||||
|
parseList(parser, privacy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventType == XmlPullParser.END_TAG) {
|
||||||
|
if (parser.getName().equals("query")) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return privacy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the list complex type
|
||||||
|
public void parseList(XmlPullParser parser, Privacy privacy) throws Exception {
|
||||||
|
boolean done = false;
|
||||||
|
String listName = parser.getAttributeValue("", "name");
|
||||||
|
ArrayList items = new ArrayList();
|
||||||
|
while (!done) {
|
||||||
|
int eventType = parser.next();
|
||||||
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
|
if (parser.getName().equals("item")) {
|
||||||
|
items.add(parseItem(parser));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventType == XmlPullParser.END_TAG) {
|
||||||
|
if (parser.getName().equals("list")) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
privacy.setPrivacyList(listName, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the list complex type
|
||||||
|
public PrivacyItem parseItem(XmlPullParser parser) throws Exception {
|
||||||
|
boolean done = false;
|
||||||
|
// Retrieves the required attributes
|
||||||
|
String actionValue = parser.getAttributeValue("", "action");
|
||||||
|
String orderValue = parser.getAttributeValue("", "order");
|
||||||
|
String type = parser.getAttributeValue("", "type");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According the action value it sets the allow status. The fall-through action is assumed
|
||||||
|
* to be "allow"
|
||||||
|
*/
|
||||||
|
boolean allow = true;
|
||||||
|
if ("allow".equalsIgnoreCase(actionValue)) {
|
||||||
|
allow = true;
|
||||||
|
} else if ("deny".equalsIgnoreCase(actionValue)) {
|
||||||
|
allow = false;
|
||||||
|
}
|
||||||
|
// Set the order number
|
||||||
|
int order = Integer.parseInt(orderValue);
|
||||||
|
|
||||||
|
// Create the privacy item
|
||||||
|
PrivacyItem item = new PrivacyItem(type, allow, order);
|
||||||
|
item.setValue(parser.getAttributeValue("", "value"));
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
int eventType = parser.next();
|
||||||
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
|
if (parser.getName().equals("iq")) {
|
||||||
|
item.setFilterIQ(true);
|
||||||
|
}
|
||||||
|
if (parser.getName().equals("message")) {
|
||||||
|
item.setFilterMessage(true);
|
||||||
|
}
|
||||||
|
if (parser.getName().equals("presence-in")) {
|
||||||
|
item.setFilterPresence_in(true);
|
||||||
|
}
|
||||||
|
if (parser.getName().equals("presence-out")) {
|
||||||
|
item.setFilterPresence_out(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventType == XmlPullParser.END_TAG) {
|
||||||
|
if (parser.getName().equals("item")) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,9 +21,7 @@
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
|
@ -31,7 +29,6 @@ import org.jivesoftware.smack.packet.*;
|
||||||
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.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class that helps to parse packets. Any parsing packets method that must be shared
|
* Utility class that helps to parse packets. Any parsing packets method that must be shared
|
||||||
|
@ -69,7 +66,7 @@ public class PacketParserUtils {
|
||||||
String subject = null;
|
String subject = null;
|
||||||
String body = null;
|
String body = null;
|
||||||
String thread = null;
|
String thread = null;
|
||||||
Map properties = null;
|
Map<String, Object> properties = null;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
int eventType = parser.next();
|
int eventType = parser.next();
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
|
@ -115,8 +112,7 @@ public class PacketParserUtils {
|
||||||
message.setThread(thread);
|
message.setThread(thread);
|
||||||
// Set packet properties.
|
// Set packet properties.
|
||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
for (Iterator i=properties.keySet().iterator(); i.hasNext(); ) {
|
for (String name : properties.keySet()) {
|
||||||
String name = (String)i.next();
|
|
||||||
message.setProperty(name, properties.get(name));
|
message.setProperty(name, properties.get(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,10 +182,9 @@ public class PacketParserUtils {
|
||||||
else if (elementName.equals("properties") &&
|
else if (elementName.equals("properties") &&
|
||||||
namespace.equals(PROPERTIES_NAMESPACE))
|
namespace.equals(PROPERTIES_NAMESPACE))
|
||||||
{
|
{
|
||||||
Map properties = parseProperties(parser);
|
Map<String,Object> properties = parseProperties(parser);
|
||||||
// Set packet properties.
|
// Set packet properties.
|
||||||
for (Iterator i=properties.keySet().iterator(); i.hasNext(); ) {
|
for (String name : properties.keySet()) {
|
||||||
String name = (String)i.next();
|
|
||||||
presence.setProperty(name, properties.get(name));
|
presence.setProperty(name, properties.get(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,8 +214,8 @@ public class PacketParserUtils {
|
||||||
* @return a map of the properties.
|
* @return a map of the properties.
|
||||||
* @throws Exception if an error occurs while parsing the properties.
|
* @throws Exception if an error occurs while parsing the properties.
|
||||||
*/
|
*/
|
||||||
public static Map parseProperties(XmlPullParser parser) throws Exception {
|
public static Map<String, Object> parseProperties(XmlPullParser parser) throws Exception {
|
||||||
Map properties = new HashMap();
|
Map<String, Object> properties = new HashMap<String, Object>();
|
||||||
while (true) {
|
while (true) {
|
||||||
int eventType = parser.next();
|
int eventType = parser.next();
|
||||||
if (eventType == XmlPullParser.START_TAG && parser.getName().equals("property")) {
|
if (eventType == XmlPullParser.START_TAG && parser.getName().equals("property")) {
|
||||||
|
@ -257,7 +252,7 @@ public class PacketParserUtils {
|
||||||
value = new Double(valueText);
|
value = new Double(valueText);
|
||||||
}
|
}
|
||||||
else if ("boolean".equals(type)) {
|
else if ("boolean".equals(type)) {
|
||||||
value = new Boolean(valueText);
|
value = Boolean.valueOf(valueText);
|
||||||
}
|
}
|
||||||
else if ("string".equals(type)) {
|
else if ("string".equals(type)) {
|
||||||
value = valueText;
|
value = valueText;
|
||||||
|
@ -297,25 +292,52 @@ public class PacketParserUtils {
|
||||||
* @throws Exception if an exception occurs while parsing the packet.
|
* @throws Exception if an exception occurs while parsing the packet.
|
||||||
*/
|
*/
|
||||||
public static XMPPError parseError(XmlPullParser parser) throws Exception {
|
public static XMPPError parseError(XmlPullParser parser) throws Exception {
|
||||||
|
final String errorNamespace = "urn:ietf:params:xml:ns:xmpp-stanzas";
|
||||||
String errorCode = "-1";
|
String errorCode = "-1";
|
||||||
|
String type = null;
|
||||||
String message = null;
|
String message = null;
|
||||||
|
String condition = null;
|
||||||
|
List<PacketExtension> extensions = new ArrayList<PacketExtension>();
|
||||||
|
|
||||||
|
// Parse the error header
|
||||||
for (int i=0; i<parser.getAttributeCount(); i++) {
|
for (int i=0; i<parser.getAttributeCount(); i++) {
|
||||||
if (parser.getAttributeName(i).equals("code")) {
|
if (parser.getAttributeName(i).equals("code")) {
|
||||||
errorCode = parser.getAttributeValue("", "code");
|
errorCode = parser.getAttributeValue("", "code");
|
||||||
}
|
}
|
||||||
|
if (parser.getAttributeName(i).equals("type")) {
|
||||||
|
type = parser.getAttributeValue("", "type");
|
||||||
}
|
}
|
||||||
// Get the error text in a safe way since we are not sure about the error message format
|
|
||||||
try {
|
|
||||||
message = parser.nextText();
|
|
||||||
}
|
|
||||||
catch (XmlPullParserException ex) {}
|
|
||||||
while (true) {
|
|
||||||
if (parser.getEventType() == XmlPullParser.END_TAG && parser.getName().equals("error")) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
boolean done = false;
|
||||||
|
// Parse the text and condition tags
|
||||||
|
while (!done) {
|
||||||
|
int eventType = parser.next();
|
||||||
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
|
if (parser.getName().equals("text")) {
|
||||||
|
parser.next();
|
||||||
|
message = parser.getText();
|
||||||
parser.next();
|
parser.next();
|
||||||
}
|
}
|
||||||
return new XMPPError(Integer.parseInt(errorCode), message);
|
else {
|
||||||
|
// Condition tag, it can be xmpp error or an application defined error.
|
||||||
|
String elementName = parser.getName();
|
||||||
|
String namespace = parser.getNamespace();
|
||||||
|
if (errorNamespace.equals(namespace)) {
|
||||||
|
condition = elementName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
extensions.add(parsePacketExtension(elementName, namespace, parser));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventType == XmlPullParser.END_TAG) {
|
||||||
|
if (parser.getName().equals("error")) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new XMPPError(Integer.parseInt(errorCode), XMPPError.Type
|
||||||
|
.fromString(type), condition, message, extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -387,7 +409,7 @@ public class PacketParserUtils {
|
||||||
// String to the correct object type.
|
// String to the correct object type.
|
||||||
Object value = decode(propertyType, stringValue);
|
Object value = decode(propertyType, stringValue);
|
||||||
// Set the value of the bean.
|
// Set the value of the bean.
|
||||||
descriptor.getWriteMethod().invoke(object, new Object[] { value });
|
descriptor.getWriteMethod().invoke(object, value);
|
||||||
}
|
}
|
||||||
else if (eventType == XmlPullParser.END_TAG) {
|
else if (eventType == XmlPullParser.END_TAG) {
|
||||||
if (parser.getName().equals(elementName)) {
|
if (parser.getName().equals(elementName)) {
|
||||||
|
@ -430,5 +452,4 @@ public class PacketParserUtils {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -184,7 +184,7 @@ public class ServiceDiscoveryManager {
|
||||||
// Return <item-not-found/> error since client doesn't contain
|
// Return <item-not-found/> error since client doesn't contain
|
||||||
// the specified node
|
// the specified node
|
||||||
response.setType(IQ.Type.ERROR);
|
response.setType(IQ.Type.ERROR);
|
||||||
response.setError(new XMPPError(404, "item-not-found"));
|
response.setError(new XMPPError(XMPPError.Condition.item_not_found));
|
||||||
}
|
}
|
||||||
connection.sendPacket(response);
|
connection.sendPacket(response);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ public class ServiceDiscoveryManager {
|
||||||
else {
|
else {
|
||||||
// Return <item-not-found/> error since specified node was not found
|
// Return <item-not-found/> error since specified node was not found
|
||||||
response.setType(IQ.Type.ERROR);
|
response.setType(IQ.Type.ERROR);
|
||||||
response.setError(new XMPPError(404, "item-not-found"));
|
response.setError(new XMPPError(XMPPError.Condition.item_not_found));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connection.sendPacket(response);
|
connection.sendPacket(response);
|
||||||
|
|
|
@ -172,7 +172,7 @@ public class FileTransferManager {
|
||||||
IQ rejection = FileTransferNegotiator.createIQ(
|
IQ rejection = FileTransferNegotiator.createIQ(
|
||||||
initiation.getPacketID(), initiation.getFrom(), initiation
|
initiation.getPacketID(), initiation.getFrom(), initiation
|
||||||
.getTo(), IQ.Type.ERROR);
|
.getTo(), IQ.Type.ERROR);
|
||||||
rejection.setError(new XMPPError(403));
|
rejection.setError(new XMPPError(XMPPError.Condition.forbidden));
|
||||||
connection.sendPacket(rejection);
|
connection.sendPacket(rejection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,12 +223,13 @@ public class FileTransferNegotiator {
|
||||||
.getFeatureNegotiationForm());
|
.getFeatureNegotiationForm());
|
||||||
|
|
||||||
if (streamMethodField == null) {
|
if (streamMethodField == null) {
|
||||||
XMPPError error = new XMPPError(400);
|
String errorMessage = "No stream methods contained in packet.";
|
||||||
|
XMPPError error = new XMPPError(XMPPError.Condition.bad_request, errorMessage);
|
||||||
IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(),
|
IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(),
|
||||||
IQ.Type.ERROR);
|
IQ.Type.ERROR);
|
||||||
iqPacket.setError(error);
|
iqPacket.setError(error);
|
||||||
connection.sendPacket(iqPacket);
|
connection.sendPacket(iqPacket);
|
||||||
throw new XMPPException("No stream methods contained in packet.", error);
|
throw new XMPPException(errorMessage, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// select the appropriate protocol
|
// select the appropriate protocol
|
||||||
|
@ -278,8 +279,9 @@ public class FileTransferNegotiator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isByteStream && !isIBB) {
|
if (!isByteStream && !isIBB) {
|
||||||
XMPPError error = new XMPPError(400);
|
XMPPError error = new XMPPError(XMPPError.Condition.bad_request,
|
||||||
throw new XMPPException("No acceptable transfer mechanism", error);
|
"No acceptable transfer mechanism");
|
||||||
|
throw new XMPPException(error.getMessage(), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isByteStream && isIBB && field.getType().equals(FormField.TYPE_LIST_MULTI)) {
|
if (isByteStream && isIBB && field.getType().equals(FormField.TYPE_LIST_MULTI)) {
|
||||||
|
@ -299,7 +301,7 @@ public class FileTransferNegotiator {
|
||||||
* @param si The Stream Initiation request to reject.
|
* @param si The Stream Initiation request to reject.
|
||||||
*/
|
*/
|
||||||
public void rejectStream(final StreamInitiation si) {
|
public void rejectStream(final StreamInitiation si) {
|
||||||
XMPPError error = new XMPPError(403, "Offer Declined");
|
XMPPError error = new XMPPError(XMPPError.Condition.forbidden, "Offer Declined");
|
||||||
IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(),
|
IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(),
|
||||||
IQ.Type.ERROR);
|
IQ.Type.ERROR);
|
||||||
iqPacket.setError(error);
|
iqPacket.setError(error);
|
||||||
|
@ -409,8 +411,9 @@ public class FileTransferNegotiator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isByteStream && !isIBB) {
|
if (!isByteStream && !isIBB) {
|
||||||
XMPPError error = new XMPPError(400);
|
XMPPError error = new XMPPError(XMPPError.Condition.bad_request,
|
||||||
throw new XMPPException("No acceptable transfer mechanism", error);
|
"No acceptable transfer mechanism");
|
||||||
|
throw new XMPPException(error.getMessage(), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isByteStream && isIBB) {
|
if (isByteStream && isIBB) {
|
||||||
|
|
|
@ -377,7 +377,7 @@ public class IBBTransferNegotiator extends StreamNegotiator {
|
||||||
private void sendCancelMessage(Message message) {
|
private void sendCancelMessage(Message message) {
|
||||||
IQ error = FileTransferNegotiator.createIQ(message.getPacketID(), message.getFrom(), message.getTo(),
|
IQ error = FileTransferNegotiator.createIQ(message.getPacketID(), message.getFrom(), message.getTo(),
|
||||||
IQ.Type.ERROR);
|
IQ.Type.ERROR);
|
||||||
error.setError(new XMPPError(504));
|
error.setError(new XMPPError(XMPPError.Condition.remote_server_timeout, "Cancel Message Transfer"));
|
||||||
connection.sendPacket(error);
|
connection.sendPacket(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,8 +220,9 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selectedHost == null || socket == null || !socket.isConnected()) {
|
if (selectedHost == null || socket == null || !socket.isConnected()) {
|
||||||
throw new XMPPException(
|
String errorMessage = "Could not establish socket with any provided host";
|
||||||
"Could not establish socket with any provided host", new XMPPError(406));
|
throw new XMPPException(errorMessage, new XMPPError(
|
||||||
|
XMPPError.Condition.no_acceptable, errorMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SelectedHostInfo(selectedHost, socket);
|
return new SelectedHostInfo(selectedHost, socket);
|
||||||
|
|
|
@ -522,7 +522,9 @@ public class VCard extends IQ {
|
||||||
result = (VCard) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
result = (VCard) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
throw new XMPPException(new XMPPError(408, "Timeout getting VCard information"));
|
String errorMessage = "Timeout getting VCard information";
|
||||||
|
throw new XMPPException(errorMessage, new XMPPError(
|
||||||
|
XMPPError.Condition.request_timeout, errorMessage));
|
||||||
}
|
}
|
||||||
if (result.getError() != null) {
|
if (result.getError() != null) {
|
||||||
throw new XMPPException(result.getError());
|
throw new XMPPException(result.getError());
|
||||||
|
|
Loading…
Reference in a new issue