Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
Openfire
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Openfire
Commits
d16c186d
Unverified
Commit
d16c186d
authored
Mar 22, 2018
by
Dave Cridland
Committed by
GitHub
Mar 22, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1049 from guusdk/OF-1511_Pubsub-publishing-options
OF-1511 OF-1513 OF-1514: Pubsub / PEP changes
parents
2e62750f
b99be2d6
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
271 additions
and
159 deletions
+271
-159
IQOwnerHandler.java
...ava/org/jivesoftware/openfire/muc/spi/IQOwnerHandler.java
+42
-39
IQPEPHandler.java
src/java/org/jivesoftware/openfire/pep/IQPEPHandler.java
+12
-0
CollectionNode.java
...java/org/jivesoftware/openfire/pubsub/CollectionNode.java
+1
-1
LeafNode.java
src/java/org/jivesoftware/openfire/pubsub/LeafNode.java
+6
-13
Node.java
src/java/org/jivesoftware/openfire/pubsub/Node.java
+9
-22
NodeSubscription.java
...va/org/jivesoftware/openfire/pubsub/NodeSubscription.java
+5
-10
PubSubEngine.java
src/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java
+194
-74
PubSubModule.java
src/java/org/jivesoftware/openfire/pubsub/PubSubModule.java
+2
-0
No files found.
src/java/org/jivesoftware/openfire/muc/spi/IQOwnerHandler.java
View file @
d16c186d
...
...
@@ -207,7 +207,6 @@ public class IQOwnerHandler {
throws
ForbiddenException
,
ConflictException
,
NotAcceptableException
{
List
<
String
>
values
;
String
booleanValue
;
FormField
field
;
// Get the new list of admins
...
...
@@ -262,9 +261,7 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_changesubject"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setCanOccupantsChangeSubject
((
"1"
.
equals
(
booleanValue
)));
room
.
setCanOccupantsChangeSubject
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
field
=
completedForm
.
getField
(
"muc#roomconfig_maxusers"
);
...
...
@@ -281,16 +278,12 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_publicroom"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setPublicRoom
((
"1"
.
equals
(
booleanValue
)));
room
.
setPublicRoom
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
field
=
completedForm
.
getField
(
"muc#roomconfig_persistentroom"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
boolean
isPersistent
=
(
"1"
.
equals
(
booleanValue
));
boolean
isPersistent
=
parseFirstValueAsBoolean
(
field
,
true
);
// Delete the room from the DB if it's no longer persistent
if
(
room
.
isPersistent
()
&&
!
isPersistent
)
{
MUCPersistenceManager
.
deleteFromDB
(
room
);
...
...
@@ -300,23 +293,17 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_moderatedroom"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setModerated
((
"1"
.
equals
(
booleanValue
)));
room
.
setModerated
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
field
=
completedForm
.
getField
(
"muc#roomconfig_membersonly"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
presences
.
addAll
(
room
.
setMembersOnly
((
"1"
.
equals
(
booleanValue
))));
presences
.
addAll
(
room
.
setMembersOnly
(
parseFirstValueAsBoolean
(
field
,
true
)
)
);
}
field
=
completedForm
.
getField
(
"muc#roomconfig_allowinvites"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setCanOccupantsInvite
((
"1"
.
equals
(
booleanValue
)));
room
.
setCanOccupantsInvite
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
...
...
@@ -330,9 +317,7 @@ public class IQOwnerHandler {
if
(
field
!=
null
)
{
passwordProtectionChanged
=
true
;
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
(
(
value
!=
null
?
value
:
"1"
)
);
updatedIsPasswordProtected
=
"1"
.
equals
(
booleanValue
);
updatedIsPasswordProtected
=
parseFirstValueAsBoolean
(
field
,
true
);
}
field
=
completedForm
.
getField
(
"muc#roomconfig_roomsecret"
);
...
...
@@ -373,43 +358,32 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_whois"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setCanAnyoneDiscoverJID
((
"anyone"
.
equals
(
booleanValue
)));
room
.
setCanAnyoneDiscoverJID
((
"anyone"
.
equals
(
field
.
getFirstValue
())));
}
field
=
completedForm
.
getField
(
"muc#roomconfig_allowpm"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setCanSendPrivateMessage
(
value
);
room
.
setCanSendPrivateMessage
(
field
.
getFirstValue
());
}
field
=
completedForm
.
getField
(
"muc#roomconfig_enablelogging"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setLogEnabled
((
"1"
.
equals
(
booleanValue
)));
room
.
setLogEnabled
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
field
=
completedForm
.
getField
(
"x-muc#roomconfig_reservednick"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setLoginRestrictedToNickname
((
"1"
.
equals
(
booleanValue
)));
room
.
setLoginRestrictedToNickname
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
field
=
completedForm
.
getField
(
"x-muc#roomconfig_canchangenick"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setChangeNickname
((
"1"
.
equals
(
booleanValue
)));
room
.
setChangeNickname
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
field
=
completedForm
.
getField
(
"x-muc#roomconfig_registration"
);
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setRegistrationEnabled
((
"1"
.
equals
(
booleanValue
)));
room
.
setRegistrationEnabled
(
parseFirstValueAsBoolean
(
field
,
true
)
);
}
// Update the modification date to reflect the last time when the room's configuration
...
...
@@ -719,4 +693,33 @@ public class IQOwnerHandler {
probeResult
=
element
;
probeResult
.
add
(
configurationForm
.
getElement
());
}
/**
* Returns the first value of the formfield as a boolean.
*
* @param field A form field (cannot be null)
* @param defaultValue Returned if first value is null or empty.
* @return true if the provided input equals '1' or 'true', false if the input equals '0' or 'false'.
* @throws IllegalArgumentException when the input cannot be parsed as a boolean.
* @Deprecated Use {@link FormField#parseFirstValueAsBoolean(String)} provided by Tinder version 1.3.1 or newer.
*/
@Deprecated
public
static
boolean
parseFirstValueAsBoolean
(
FormField
field
,
boolean
defaultValue
)
{
final
String
value
=
field
.
getFirstValue
();
if
(
value
==
null
||
value
.
isEmpty
()
)
{
return
defaultValue
;
}
if
(
"0"
.
equals
(
value
)
||
"false"
.
equals
(
value
)
)
{
return
false
;
}
if
(
"1"
.
equals
(
value
)
||
"true"
.
equals
(
value
)
)
{
return
true
;
}
throw
new
IllegalArgumentException
(
"Unable to parse value '"
+
value
+
"' as Data Form Field boolean."
);
}
}
src/java/org/jivesoftware/openfire/pep/IQPEPHandler.java
View file @
d16c186d
...
...
@@ -369,6 +369,18 @@ public class IQPEPHandler extends IQHandler implements ServerIdentitiesProvider,
// Create the node
final
JID
creator
=
new
JID
(
jidFrom
);
final
LeafNode
newNode
=
new
LeafNode
(
pepService
,
pepService
.
getRootCollectionNode
(),
nodeID
,
creator
);
final
DataForm
publishOptions
=
PubSubEngine
.
getPublishOptions
(
packet
);
if
(
publishOptions
!=
null
)
{
try
{
newNode
.
configure
(
publishOptions
);
}
catch
(
NotAcceptableException
e
)
{
Log
.
warn
(
"Unable to apply publish-options when creating a new PEP node {} for {}"
,
nodeID
,
creator
,
e
);
}
}
newNode
.
addOwner
(
creator
);
newNode
.
saveToDB
();
}
...
...
src/java/org/jivesoftware/openfire/pubsub/CollectionNode.java
View file @
d16c186d
...
...
@@ -194,7 +194,7 @@ public class CollectionNode extends Node {
formField
.
addValue
(
maxLeafNodes
);
formField
=
form
.
addField
();
formField
.
setVariable
(
"pubsub#chilren_max"
);
formField
.
setVariable
(
"pubsub#chil
d
ren_max"
);
if
(
isEditing
)
{
formField
.
setType
(
FormField
.
Type
.
text_single
);
formField
.
setLabel
(
LocaleUtils
.
getLocalizedString
(
"pubsub.form.conf.children_max"
));
...
...
src/java/org/jivesoftware/openfire/pubsub/LeafNode.java
View file @
d16c186d
...
...
@@ -33,6 +33,8 @@ import org.xmpp.packet.IQ;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.Message
;
import
static
org
.
jivesoftware
.
openfire
.
muc
.
spi
.
IQOwnerHandler
.
parseFirstValueAsBoolean
;
/**
* A type of node that contains published items only. It is NOT a container for
* other nodes.
...
...
@@ -84,27 +86,19 @@ public class LeafNode extends Node {
@Override
protected
void
configure
(
FormField
field
)
throws
NotAcceptableException
{
List
<
String
>
values
;
String
booleanValue
;
if
(
"pubsub#persist_items"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
persistPublishedItems
=
"1"
.
equals
(
booleanValue
);
persistPublishedItems
=
parseFirstValueAsBoolean
(
field
,
true
);
}
else
if
(
"pubsub#max_payload_size"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
maxPayloadSize
=
values
.
size
()
>
0
?
Integer
.
parseInt
(
values
.
get
(
0
))
:
5120
;
maxPayloadSize
=
field
.
getFirstValue
()
!=
null
?
Integer
.
parseInt
(
field
.
getFirstValue
()
)
:
5120
;
}
else
if
(
"pubsub#send_item_subscribe"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
sendItemSubscribe
=
"1"
.
equals
(
booleanValue
);
sendItemSubscribe
=
parseFirstValueAsBoolean
(
field
,
true
);
}
}
@Override
void
postConfigure
(
DataForm
completedForm
)
{
List
<
String
>
values
;
if
(!
persistPublishedItems
)
{
// Always save the last published item when not configured to use persistent items
maxPublishedItems
=
1
;
...
...
@@ -112,8 +106,7 @@ public class LeafNode extends Node {
else
{
FormField
field
=
completedForm
.
getField
(
"pubsub#max_items"
);
if
(
field
!=
null
)
{
values
=
field
.
getValues
();
maxPublishedItems
=
values
.
size
()
>
0
?
Integer
.
parseInt
(
values
.
get
(
0
))
:
50
;
maxPublishedItems
=
field
.
getFirstValue
()
!=
null
?
Integer
.
parseInt
(
field
.
getFirstValue
()
)
:
50
;
}
}
}
...
...
src/java/org/jivesoftware/openfire/pubsub/Node.java
View file @
d16c186d
...
...
@@ -44,6 +44,8 @@ import org.xmpp.packet.IQ;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.Message
;
import
static
org
.
jivesoftware
.
openfire
.
muc
.
spi
.
IQOwnerHandler
.
parseFirstValueAsBoolean
;
/**
* A virtual location to which information can be published and from which event
* notifications and/or payloads can be received (in other pubsub systems, this may
...
...
@@ -498,7 +500,6 @@ public abstract class Node {
}
else
if
(
DataForm
.
Type
.
submit
.
equals
(
completedForm
.
getType
()))
{
List
<
String
>
values
;
String
booleanValue
;
// Get the new list of owners
FormField
ownerField
=
completedForm
.
getField
(
"pubsub#owner"
);
...
...
@@ -525,40 +526,26 @@ public abstract class Node {
// Do nothing
}
else
if
(
"pubsub#deliver_payloads"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
deliverPayloads
=
"1"
.
equals
(
booleanValue
);
deliverPayloads
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#notify_config"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
notifyConfigChanges
=
"1"
.
equals
(
booleanValue
);
notifyConfigChanges
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#notify_delete"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
notifyDelete
=
"1"
.
equals
(
booleanValue
);
notifyDelete
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#notify_retract"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
notifyRetract
=
"1"
.
equals
(
booleanValue
);
notifyRetract
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#presence_based_delivery"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
presenceBasedDelivery
=
"1"
.
equals
(
booleanValue
);
presenceBasedDelivery
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#subscribe"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
subscriptionEnabled
=
"1"
.
equals
(
booleanValue
);
subscriptionEnabled
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#subscription_required"
.
equals
(
field
.
getVariable
()))
{
// TODO Replace this variable for the one defined in the JEP (once one is defined)
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
subscriptionConfigurationRequired
=
"1"
.
equals
(
booleanValue
);
subscriptionConfigurationRequired
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#type"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
...
...
src/java/org/jivesoftware/openfire/pubsub/NodeSubscription.java
View file @
d16c186d
...
...
@@ -36,6 +36,8 @@ import org.xmpp.packet.JID;
import
org.xmpp.packet.Message
;
import
org.xmpp.packet.Presence
;
import
static
org
.
jivesoftware
.
openfire
.
muc
.
spi
.
IQOwnerHandler
.
parseFirstValueAsBoolean
;
/**
* A subscription to a node. Entities may subscribe to a node to be notified when new events
* are published to the node. Published events may contain a {@link PublishedItem}. Only
...
...
@@ -409,7 +411,6 @@ public class NodeSubscription {
void
configure
(
DataForm
options
)
{
List
<
String
>
values
;
String
booleanValue
;
boolean
wasUsingPresence
=
!
presenceStates
.
isEmpty
();
...
...
@@ -435,14 +436,10 @@ public class NodeSubscription {
for
(
FormField
field
:
options
.
getFields
())
{
boolean
fieldExists
=
true
;
if
(
"pubsub#deliver"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
deliverNotifications
=
"1"
.
equals
(
booleanValue
);
deliverNotifications
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#digest"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
usingDigest
=
"1"
.
equals
(
booleanValue
);
usingDigest
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#digest_frequency"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
...
...
@@ -457,9 +454,7 @@ public class NodeSubscription {
}
}
else
if
(
"pubsub#include_body"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
includingBody
=
"1"
.
equals
(
booleanValue
);
includingBody
=
parseFirstValueAsBoolean
(
field
,
true
)
;
}
else
if
(
"pubsub#show-values"
.
equals
(
field
.
getVariable
()))
{
// Get the new list of presence states for which an entity wants to
...
...
src/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java
View file @
d16c186d
...
...
@@ -19,11 +19,7 @@ package org.jivesoftware.openfire.pubsub;
import
org.dom4j.DocumentHelper
;
import
org.dom4j.Element
;
import
org.dom4j.QName
;
import
org.jivesoftware.openfire.PacketRouter
;
import
org.jivesoftware.openfire.RoutingTable
;
import
org.jivesoftware.openfire.SessionManager
;
import
org.jivesoftware.openfire.XMPPServer
;
import
org.jivesoftware.openfire.XMPPServerListener
;
import
org.jivesoftware.openfire.*
;
import
org.jivesoftware.openfire.component.InternalComponentManager
;
import
org.jivesoftware.openfire.pep.PEPService
;
import
org.jivesoftware.openfire.pubsub.cluster.RefreshNodeTask
;
...
...
@@ -37,20 +33,9 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
org.xmpp.forms.DataForm
;
import
org.xmpp.forms.FormField
;
import
org.xmpp.packet.IQ
;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.Message
;
import
org.xmpp.packet.PacketError
;
import
org.xmpp.packet.Presence
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.xmpp.packet.*
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.Future
;
...
...
@@ -133,7 +118,7 @@ public class PubSubEngine {
return
TaskEngine
.
getInstance
().
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
createNode
(
service
,
iq
,
childElement
,
finalAction
);
createNode
(
service
,
iq
,
childElement
,
finalAction
,
getPublishOptions
(
iq
)
);
}
});
}
...
...
@@ -338,34 +323,42 @@ public class PubSubEngine {
if
(
nodeID
==
null
)
{
// XEP-0060 Section 7.2.3.3 - No node was specified. Return bad_request error
// This suggests that Instant nodes should not be auto-created
Element
pubsubError
=
DocumentHelper
.
createElement
(
QName
.
get
(
"nodeid-required"
,
"http://jabber.org/protocol/pubsub#errors"
));
Element
pubsubError
=
DocumentHelper
.
createElement
(
QName
.
get
(
"nodeid-required"
,
"http://jabber.org/protocol/pubsub#errors"
));
sendErrorPacket
(
iq
,
PacketError
.
Condition
.
bad_request
,
pubsubError
);
return
;
}
else
{
// Look for the specified node
node
=
service
.
getNode
(
nodeID
);
if
(
node
==
null
)
{
if
(
service
instanceof
PEPService
&&
service
.
isServiceAdmin
(
owner
)){
// If it is a PEP service & publisher is service owner -
// auto create nodes.
Element
childElement
=
iq
.
getChildElement
();
CreateNodeResponse
response
=
createNodeHelper
(
service
,
iq
,
childElement
,
publishElement
);
if
(
response
.
newNode
==
null
)
{
// New node creation failed. Since pep#auto-create is advertised
// in disco#info, node creation error should be sent to the client.
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
}
else
{
// Node creation succeeded, set node to newNode.
node
=
response
.
newNode
;
}
}
else
{
// Node does not exist. Return item-not-found error
sendErrorPacket
(
iq
,
PacketError
.
Condition
.
item_not_found
,
null
);
// Optional Publish Options.
final
DataForm
publishOptions
=
getPublishOptions
(
iq
);
// Look for the specified node
node
=
service
.
getNode
(
nodeID
);
if
(
node
==
null
)
{
if
(
service
instanceof
PEPService
&&
service
.
isServiceAdmin
(
owner
)
&&
canAutoCreate
(
publishOptions
)
)
{
// If it is a PEP service & publisher is service owner - auto create nodes.
CreateNodeResponse
response
=
createNodeHelper
(
service
,
iq
,
iq
.
getChildElement
(),
publishElement
,
publishOptions
);
if
(
response
.
newNode
==
null
)
{
// New node creation failed. Since pep#auto-create is advertised
// in disco#info, node creation error should be sent to the client.
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
return
;
}
else
{
// Node creation succeeded, set node to newNode.
node
=
response
.
newNode
;
}
}
else
{
// Node does not exist. Return item-not-found error
sendErrorPacket
(
iq
,
PacketError
.
Condition
.
item_not_found
,
null
);
return
;
}
}
else
{
// Check if the preconditions defined in the publish options (if any) are met.
if
(
!
nodeMeetsPreconditions
(
node
,
publishOptions
)
)
{
Element
pubsubError
=
DocumentHelper
.
createElement
(
QName
.
get
(
"precondition-not-met"
,
"http://jabber.org/protocol/pubsub#errors"
));
sendErrorPacket
(
iq
,
PacketError
.
Condition
.
conflict
,
pubsubError
);
return
;
}
}
...
...
@@ -433,6 +426,120 @@ public class PubSubEngine {
leafNode
.
publishItems
(
from
,
items
);
}
/**
* Get the dataform that describes the publish options from the request, or null if no such form was included.
*
* @param iq The publish request (cannot be null).
* @return A publish options data form (possibly null).
*/
public
static
DataForm
getPublishOptions
(
IQ
iq
)
{
final
Element
publishOptionsElement
=
iq
.
getChildElement
().
element
(
"publish-options"
);
if
(
publishOptionsElement
==
null
)
{
return
null
;
}
final
Element
x
=
publishOptionsElement
.
element
(
QName
.
get
(
DataForm
.
ELEMENT_NAME
,
DataForm
.
NAMESPACE
)
);
if
(
x
==
null
)
{
return
null
;
}
final
DataForm
result
=
new
DataForm
(
x
);
if
(
result
.
getType
()
!=
DataForm
.
Type
.
submit
)
{
return
null
;
}
final
FormField
formType
=
result
.
getField
(
"FORM_TYPE"
);
if
(
formType
==
null
||
!
"http://jabber.org/protocol/pubsub#publish-options"
.
equals
(
formType
.
getFirstValue
()
)
)
{
return
null
;
}
return
result
;
}
/**
* Checks if a node is allowed to be auto-created, given the configuration of the service and the optional publish options.
*
* @param publishOptions publish options (can be null)
* @return true if auto-creation of nodes on publish to a non-existent node is allowed, otherwise false.
*/
private
boolean
canAutoCreate
(
DataForm
publishOptions
)
{
// Since pep#auto-create is advertised in disco#info in hard-code, this is always allowed, unless the publish options explicitly forbid this.
if
(
publishOptions
==
null
)
{
return
true
;
}
final
FormField
field
=
publishOptions
.
getField
(
"pubsub#auto-create"
);
if
(
field
==
null
)
{
return
true
;
}
final
String
firstValue
=
field
.
getFirstValue
();
return
"1"
.
equals
(
firstValue
)
||
"true"
.
equalsIgnoreCase
(
firstValue
);
}
/**
* Checks of the configuration of the node meets the preconditions, as supplied in the dataform.
*
* This method returns true only if the configuration of the node at least contains each of the fields
* defined in the preconditions (with matching values).
*
* @param node The node (cannot be null)
* @param preconditions The preconditions (can be null, in which case 'true' is returned).
* @return True if all preconditions are met, otherwise false.
*/
private
boolean
nodeMeetsPreconditions
(
Node
node
,
DataForm
preconditions
)
{
if
(
preconditions
==
null
)
{
return
true
;
}
final
DataForm
conditions
=
node
.
getConfigurationForm
();
for
(
final
FormField
precondition
:
preconditions
.
getFields
()
)
{
if
(
precondition
.
getVariable
().
equals
(
"FORM_TYPE"
)
)
{
continue
;
}
final
FormField
condition
=
conditions
.
getField
(
precondition
.
getVariable
()
);
if
(
condition
==
null
)
{
// Unknown condition. Reject.
return
false
;
}
if
(
condition
.
getValues
().
size
()
>
1
)
{
if
(
!
condition
.
getValues
().
containsAll
(
precondition
.
getValues
()
)
||
!
precondition
.
getValues
().
containsAll
(
condition
.
getValues
()
)
)
{
// The condition value list does contain different values than the precondtion value list.
return
false
;
}
}
else
{
final
String
a
=
condition
.
getFirstValue
();
final
String
b
=
precondition
.
getFirstValue
();
if
(
!
a
.
equals
(
b
)
&&
!(
a
.
equals
(
"true"
)
&&
b
.
equals
(
"1"
))
&&
!(
a
.
equals
(
"1"
)
&&
b
.
equals
(
"true"
))
&&
!(
a
.
equals
(
"false"
)
&&
b
.
equals
(
"0"
))
&&
!(
a
.
equals
(
"0"
)
&&
b
.
equals
(
"false"
))
)
{
return
false
;
}
}
}
return
true
;
}
private
void
deleteItems
(
PubSubService
service
,
IQ
iq
,
Element
retractElement
)
{
String
nodeID
=
retractElement
.
attributeValue
(
"node"
);
Node
node
;
...
...
@@ -1129,9 +1236,9 @@ public class PubSubEngine {
leafNode
.
sendPublishedItems
(
iq
,
items
,
forceToIncludePayload
);
}
private
void
createNode
(
PubSubService
service
,
IQ
iq
,
Element
childElement
,
Element
createElement
)
{
private
void
createNode
(
PubSubService
service
,
IQ
iq
,
Element
childElement
,
Element
createElement
,
DataForm
publishOptions
)
{
// Call createNodeHelper and get the node creation status.
CreateNodeResponse
response
=
createNodeHelper
(
service
,
iq
,
childElement
,
createElement
);
CreateNodeResponse
response
=
createNodeHelper
(
service
,
iq
,
childElement
,
createElement
,
publishOptions
);
if
(
response
.
newNode
==
null
)
{
// New node creation failed
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
...
...
@@ -1174,13 +1281,9 @@ public class PubSubEngine {
* <br/>NOTE 2: This method calls UserManager::isRegisteredUser(JID) which can block waiting for a response - so
* do not call this method in the same thread in which a response might arrive
*
* @param service
* @param iq
* @param childElement
* @param createElement
* @return {@link CreateNodeResponse}
*/
private
CreateNodeResponse
createNodeHelper
(
PubSubService
service
,
IQ
iq
,
Element
childElement
,
Element
createElement
)
{
private
CreateNodeResponse
createNodeHelper
(
PubSubService
service
,
IQ
iq
,
Element
childElement
,
Element
createElement
,
DataForm
publishOptions
)
{
// Get sender of the IQ packet
JID
from
=
iq
.
getFrom
();
// Verify that sender has permissions to create nodes
...
...
@@ -1213,36 +1316,53 @@ public class PubSubEngine {
Element
configureElement
=
childElement
.
element
(
"configure"
);
if
(
configureElement
!=
null
)
{
// Get the data form that contains the parent nodeID
completedForm
=
getSentConfigurationForm
(
configureElement
);
if
(
completedForm
!=
null
)
{
// Calculate newNodeID when new node is affiliated with a Collection
FormField
field
=
completedForm
.
getField
(
"pubsub#collection"
);
if
(
field
!=
null
)
{
List
<
String
>
values
=
field
.
getValues
();
if
(!
values
.
isEmpty
())
{
String
parentNodeID
=
values
.
get
(
0
);
Node
tempNode
=
service
.
getNode
(
parentNodeID
);
if
(
tempNode
==
null
)
{
// Requested parent node was not found so return an error
return
new
CreateNodeResponse
(
PacketError
.
Condition
.
item_not_found
,
null
,
null
);
}
else
if
(!
tempNode
.
isCollectionNode
())
{
// Requested parent node is not a collection node so return an error
return
new
CreateNodeResponse
(
PacketError
.
Condition
.
not_acceptable
,
null
,
null
);
}
parentNode
=
(
CollectionNode
)
tempNode
;
completedForm
=
getSentConfigurationForm
(
configureElement
);
}
if
(
publishOptions
!=
null
)
{
// Apply publish options to override provided config.
if
(
completedForm
==
null
)
{
completedForm
=
publishOptions
;
}
else
{
for
(
final
FormField
publishOption
:
publishOptions
.
getFields
()
)
{
completedForm
.
removeField
(
publishOption
.
getVariable
()
);
final
FormField
formField
=
completedForm
.
addField
(
publishOption
.
getVariable
(),
publishOption
.
getLabel
(),
publishOption
.
getType
()
);
for
(
final
String
value
:
publishOption
.
getValues
()
)
{
formField
.
addValue
(
value
);
}
}
field
=
completedForm
.
getField
(
"pubsub#node_type"
);
if
(
field
!=
null
)
{
// Check if user requested to create a new collection node
List
<
String
>
values
=
field
.
getValues
();
if
(!
values
.
isEmpty
())
{
collectionType
=
"collection"
.
equals
(
values
.
get
(
0
));
}
}
if
(
completedForm
!=
null
)
{
// Calculate newNodeID when new node is affiliated with a Collection
FormField
field
=
completedForm
.
getField
(
"pubsub#collection"
);
if
(
field
!=
null
)
{
List
<
String
>
values
=
field
.
getValues
();
if
(!
values
.
isEmpty
())
{
String
parentNodeID
=
values
.
get
(
0
);
Node
tempNode
=
service
.
getNode
(
parentNodeID
);
if
(
tempNode
==
null
)
{
// Requested parent node was not found so return an error
return
new
CreateNodeResponse
(
PacketError
.
Condition
.
item_not_found
,
null
,
null
);
}
else
if
(!
tempNode
.
isCollectionNode
())
{
// Requested parent node is not a collection node so return an error
return
new
CreateNodeResponse
(
PacketError
.
Condition
.
not_acceptable
,
null
,
null
);
}
parentNode
=
(
CollectionNode
)
tempNode
;
}
}
field
=
completedForm
.
getField
(
"pubsub#node_type"
);
if
(
field
!=
null
)
{
// Check if user requested to create a new collection node
List
<
String
>
values
=
field
.
getValues
();
if
(!
values
.
isEmpty
())
{
collectionType
=
"collection"
.
equals
(
values
.
get
(
0
));
}
}
}
// If no parent was defined then use the root collection node
if
(
parentNode
==
null
&&
service
.
isCollectionNodesSupported
())
{
parentNode
=
service
.
getRootCollectionNode
();
...
...
src/java/org/jivesoftware/openfire/pubsub/PubSubModule.java
View file @
d16c186d
...
...
@@ -679,6 +679,8 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
features
.
add
(
"http://jabber.org/protocol/pubsub#subscribe"
);
// Configuration of subscription options is supported
features
.
add
(
"http://jabber.org/protocol/pubsub#subscription-options"
);
// Publishing options are supported.
features
.
add
(
"http://jabber.org/protocol/pubsub#publish-options"
);
}
else
if
(
name
==
null
)
{
// Answer the features of a given node
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment