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 {
...
@@ -207,7 +207,6 @@ public class IQOwnerHandler {
throws
ForbiddenException
,
ConflictException
,
NotAcceptableException
throws
ForbiddenException
,
ConflictException
,
NotAcceptableException
{
{
List
<
String
>
values
;
List
<
String
>
values
;
String
booleanValue
;
FormField
field
;
FormField
field
;
// Get the new list of admins
// Get the new list of admins
...
@@ -262,9 +261,7 @@ public class IQOwnerHandler {
...
@@ -262,9 +261,7 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_changesubject"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_changesubject"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setCanOccupantsChangeSubject
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setCanOccupantsChangeSubject
((
"1"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_maxusers"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_maxusers"
);
...
@@ -281,16 +278,12 @@ public class IQOwnerHandler {
...
@@ -281,16 +278,12 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_publicroom"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_publicroom"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setPublicRoom
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setPublicRoom
((
"1"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_persistentroom"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_persistentroom"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
boolean
isPersistent
=
parseFirstValueAsBoolean
(
field
,
true
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
boolean
isPersistent
=
(
"1"
.
equals
(
booleanValue
));
// Delete the room from the DB if it's no longer persistent
// Delete the room from the DB if it's no longer persistent
if
(
room
.
isPersistent
()
&&
!
isPersistent
)
{
if
(
room
.
isPersistent
()
&&
!
isPersistent
)
{
MUCPersistenceManager
.
deleteFromDB
(
room
);
MUCPersistenceManager
.
deleteFromDB
(
room
);
...
@@ -300,23 +293,17 @@ public class IQOwnerHandler {
...
@@ -300,23 +293,17 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_moderatedroom"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_moderatedroom"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setModerated
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setModerated
((
"1"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_membersonly"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_membersonly"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
presences
.
addAll
(
room
.
setMembersOnly
(
parseFirstValueAsBoolean
(
field
,
true
)
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
presences
.
addAll
(
room
.
setMembersOnly
((
"1"
.
equals
(
booleanValue
))));
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_allowinvites"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_allowinvites"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setCanOccupantsInvite
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setCanOccupantsInvite
((
"1"
.
equals
(
booleanValue
)));
}
}
...
@@ -330,9 +317,7 @@ public class IQOwnerHandler {
...
@@ -330,9 +317,7 @@ public class IQOwnerHandler {
if
(
field
!=
null
)
if
(
field
!=
null
)
{
{
passwordProtectionChanged
=
true
;
passwordProtectionChanged
=
true
;
final
String
value
=
field
.
getFirstValue
();
updatedIsPasswordProtected
=
parseFirstValueAsBoolean
(
field
,
true
);
booleanValue
=
(
(
value
!=
null
?
value
:
"1"
)
);
updatedIsPasswordProtected
=
"1"
.
equals
(
booleanValue
);
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_roomsecret"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_roomsecret"
);
...
@@ -373,43 +358,32 @@ public class IQOwnerHandler {
...
@@ -373,43 +358,32 @@ public class IQOwnerHandler {
field
=
completedForm
.
getField
(
"muc#roomconfig_whois"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_whois"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setCanAnyoneDiscoverJID
((
"anyone"
.
equals
(
field
.
getFirstValue
())));
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setCanAnyoneDiscoverJID
((
"anyone"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_allowpm"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_allowpm"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setCanSendPrivateMessage
(
field
.
getFirstValue
());
room
.
setCanSendPrivateMessage
(
value
);
}
}
field
=
completedForm
.
getField
(
"muc#roomconfig_enablelogging"
);
field
=
completedForm
.
getField
(
"muc#roomconfig_enablelogging"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setLogEnabled
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setLogEnabled
((
"1"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"x-muc#roomconfig_reservednick"
);
field
=
completedForm
.
getField
(
"x-muc#roomconfig_reservednick"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setLoginRestrictedToNickname
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setLoginRestrictedToNickname
((
"1"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"x-muc#roomconfig_canchangenick"
);
field
=
completedForm
.
getField
(
"x-muc#roomconfig_canchangenick"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setChangeNickname
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setChangeNickname
((
"1"
.
equals
(
booleanValue
)));
}
}
field
=
completedForm
.
getField
(
"x-muc#roomconfig_registration"
);
field
=
completedForm
.
getField
(
"x-muc#roomconfig_registration"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
final
String
value
=
field
.
getFirstValue
();
room
.
setRegistrationEnabled
(
parseFirstValueAsBoolean
(
field
,
true
)
);
booleanValue
=
((
value
!=
null
?
value
:
"1"
));
room
.
setRegistrationEnabled
((
"1"
.
equals
(
booleanValue
)));
}
}
// Update the modification date to reflect the last time when the room's configuration
// Update the modification date to reflect the last time when the room's configuration
...
@@ -719,4 +693,33 @@ public class IQOwnerHandler {
...
@@ -719,4 +693,33 @@ public class IQOwnerHandler {
probeResult
=
element
;
probeResult
=
element
;
probeResult
.
add
(
configurationForm
.
getElement
());
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,
...
@@ -369,6 +369,18 @@ public class IQPEPHandler extends IQHandler implements ServerIdentitiesProvider,
// Create the node
// Create the node
final
JID
creator
=
new
JID
(
jidFrom
);
final
JID
creator
=
new
JID
(
jidFrom
);
final
LeafNode
newNode
=
new
LeafNode
(
pepService
,
pepService
.
getRootCollectionNode
(),
nodeID
,
creator
);
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
.
addOwner
(
creator
);
newNode
.
saveToDB
();
newNode
.
saveToDB
();
}
}
...
...
src/java/org/jivesoftware/openfire/pubsub/CollectionNode.java
View file @
d16c186d
...
@@ -194,7 +194,7 @@ public class CollectionNode extends Node {
...
@@ -194,7 +194,7 @@ public class CollectionNode extends Node {
formField
.
addValue
(
maxLeafNodes
);
formField
.
addValue
(
maxLeafNodes
);
formField
=
form
.
addField
();
formField
=
form
.
addField
();
formField
.
setVariable
(
"pubsub#chilren_max"
);
formField
.
setVariable
(
"pubsub#chil
d
ren_max"
);
if
(
isEditing
)
{
if
(
isEditing
)
{
formField
.
setType
(
FormField
.
Type
.
text_single
);
formField
.
setType
(
FormField
.
Type
.
text_single
);
formField
.
setLabel
(
LocaleUtils
.
getLocalizedString
(
"pubsub.form.conf.children_max"
));
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;
...
@@ -33,6 +33,8 @@ import org.xmpp.packet.IQ;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.Message
;
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
* A type of node that contains published items only. It is NOT a container for
* other nodes.
* other nodes.
...
@@ -84,27 +86,19 @@ public class LeafNode extends Node {
...
@@ -84,27 +86,19 @@ public class LeafNode extends Node {
@Override
@Override
protected
void
configure
(
FormField
field
)
throws
NotAcceptableException
{
protected
void
configure
(
FormField
field
)
throws
NotAcceptableException
{
List
<
String
>
values
;
String
booleanValue
;
if
(
"pubsub#persist_items"
.
equals
(
field
.
getVariable
()))
{
if
(
"pubsub#persist_items"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
persistPublishedItems
=
parseFirstValueAsBoolean
(
field
,
true
);
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
persistPublishedItems
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#max_payload_size"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#max_payload_size"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
maxPayloadSize
=
field
.
getFirstValue
()
!=
null
?
Integer
.
parseInt
(
field
.
getFirstValue
()
)
:
5120
;
maxPayloadSize
=
values
.
size
()
>
0
?
Integer
.
parseInt
(
values
.
get
(
0
))
:
5120
;
}
}
else
if
(
"pubsub#send_item_subscribe"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#send_item_subscribe"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
sendItemSubscribe
=
parseFirstValueAsBoolean
(
field
,
true
);
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
sendItemSubscribe
=
"1"
.
equals
(
booleanValue
);
}
}
}
}
@Override
@Override
void
postConfigure
(
DataForm
completedForm
)
{
void
postConfigure
(
DataForm
completedForm
)
{
List
<
String
>
values
;
if
(!
persistPublishedItems
)
{
if
(!
persistPublishedItems
)
{
// Always save the last published item when not configured to use persistent items
// Always save the last published item when not configured to use persistent items
maxPublishedItems
=
1
;
maxPublishedItems
=
1
;
...
@@ -112,8 +106,7 @@ public class LeafNode extends Node {
...
@@ -112,8 +106,7 @@ public class LeafNode extends Node {
else
{
else
{
FormField
field
=
completedForm
.
getField
(
"pubsub#max_items"
);
FormField
field
=
completedForm
.
getField
(
"pubsub#max_items"
);
if
(
field
!=
null
)
{
if
(
field
!=
null
)
{
values
=
field
.
getValues
();
maxPublishedItems
=
field
.
getFirstValue
()
!=
null
?
Integer
.
parseInt
(
field
.
getFirstValue
()
)
:
50
;
maxPublishedItems
=
values
.
size
()
>
0
?
Integer
.
parseInt
(
values
.
get
(
0
))
:
50
;
}
}
}
}
}
}
...
...
src/java/org/jivesoftware/openfire/pubsub/Node.java
View file @
d16c186d
...
@@ -44,6 +44,8 @@ import org.xmpp.packet.IQ;
...
@@ -44,6 +44,8 @@ import org.xmpp.packet.IQ;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.Message
;
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
* 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
* notifications and/or payloads can be received (in other pubsub systems, this may
...
@@ -498,7 +500,6 @@ public abstract class Node {
...
@@ -498,7 +500,6 @@ public abstract class Node {
}
}
else
if
(
DataForm
.
Type
.
submit
.
equals
(
completedForm
.
getType
()))
{
else
if
(
DataForm
.
Type
.
submit
.
equals
(
completedForm
.
getType
()))
{
List
<
String
>
values
;
List
<
String
>
values
;
String
booleanValue
;
// Get the new list of owners
// Get the new list of owners
FormField
ownerField
=
completedForm
.
getField
(
"pubsub#owner"
);
FormField
ownerField
=
completedForm
.
getField
(
"pubsub#owner"
);
...
@@ -525,40 +526,26 @@ public abstract class Node {
...
@@ -525,40 +526,26 @@ public abstract class Node {
// Do nothing
// Do nothing
}
}
else
if
(
"pubsub#deliver_payloads"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#deliver_payloads"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
deliverPayloads
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
deliverPayloads
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#notify_config"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#notify_config"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
notifyConfigChanges
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
notifyConfigChanges
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#notify_delete"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#notify_delete"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
notifyDelete
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
notifyDelete
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#notify_retract"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#notify_retract"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
notifyRetract
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
notifyRetract
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#presence_based_delivery"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#presence_based_delivery"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
presenceBasedDelivery
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
presenceBasedDelivery
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#subscribe"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#subscribe"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
subscriptionEnabled
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
subscriptionEnabled
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#subscription_required"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#subscription_required"
.
equals
(
field
.
getVariable
()))
{
// TODO Replace this variable for the one defined in the JEP (once one is defined)
// TODO Replace this variable for the one defined in the JEP (once one is defined)
values
=
field
.
getValues
();
subscriptionConfigurationRequired
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
subscriptionConfigurationRequired
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#type"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#type"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
values
=
field
.
getValues
();
...
...
src/java/org/jivesoftware/openfire/pubsub/NodeSubscription.java
View file @
d16c186d
...
@@ -36,6 +36,8 @@ import org.xmpp.packet.JID;
...
@@ -36,6 +36,8 @@ import org.xmpp.packet.JID;
import
org.xmpp.packet.Message
;
import
org.xmpp.packet.Message
;
import
org.xmpp.packet.Presence
;
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
* 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
* are published to the node. Published events may contain a {@link PublishedItem}. Only
...
@@ -409,7 +411,6 @@ public class NodeSubscription {
...
@@ -409,7 +411,6 @@ public class NodeSubscription {
void
configure
(
DataForm
options
)
{
void
configure
(
DataForm
options
)
{
List
<
String
>
values
;
List
<
String
>
values
;
String
booleanValue
;
boolean
wasUsingPresence
=
!
presenceStates
.
isEmpty
();
boolean
wasUsingPresence
=
!
presenceStates
.
isEmpty
();
...
@@ -435,14 +436,10 @@ public class NodeSubscription {
...
@@ -435,14 +436,10 @@ public class NodeSubscription {
for
(
FormField
field
:
options
.
getFields
())
{
for
(
FormField
field
:
options
.
getFields
())
{
boolean
fieldExists
=
true
;
boolean
fieldExists
=
true
;
if
(
"pubsub#deliver"
.
equals
(
field
.
getVariable
()))
{
if
(
"pubsub#deliver"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
deliverNotifications
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
deliverNotifications
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#digest"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#digest"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
usingDigest
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
usingDigest
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#digest_frequency"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#digest_frequency"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
values
=
field
.
getValues
();
...
@@ -457,9 +454,7 @@ public class NodeSubscription {
...
@@ -457,9 +454,7 @@ public class NodeSubscription {
}
}
}
}
else
if
(
"pubsub#include_body"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#include_body"
.
equals
(
field
.
getVariable
()))
{
values
=
field
.
getValues
();
includingBody
=
parseFirstValueAsBoolean
(
field
,
true
)
;
booleanValue
=
(
values
.
size
()
>
0
?
values
.
get
(
0
)
:
"1"
);
includingBody
=
"1"
.
equals
(
booleanValue
);
}
}
else
if
(
"pubsub#show-values"
.
equals
(
field
.
getVariable
()))
{
else
if
(
"pubsub#show-values"
.
equals
(
field
.
getVariable
()))
{
// Get the new list of presence states for which an entity wants to
// 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;
...
@@ -19,11 +19,7 @@ package org.jivesoftware.openfire.pubsub;
import
org.dom4j.DocumentHelper
;
import
org.dom4j.DocumentHelper
;
import
org.dom4j.Element
;
import
org.dom4j.Element
;
import
org.dom4j.QName
;
import
org.dom4j.QName
;
import
org.jivesoftware.openfire.PacketRouter
;
import
org.jivesoftware.openfire.*
;
import
org.jivesoftware.openfire.RoutingTable
;
import
org.jivesoftware.openfire.SessionManager
;
import
org.jivesoftware.openfire.XMPPServer
;
import
org.jivesoftware.openfire.XMPPServerListener
;
import
org.jivesoftware.openfire.component.InternalComponentManager
;
import
org.jivesoftware.openfire.component.InternalComponentManager
;
import
org.jivesoftware.openfire.pep.PEPService
;
import
org.jivesoftware.openfire.pep.PEPService
;
import
org.jivesoftware.openfire.pubsub.cluster.RefreshNodeTask
;
import
org.jivesoftware.openfire.pubsub.cluster.RefreshNodeTask
;
...
@@ -37,20 +33,9 @@ import org.slf4j.Logger;
...
@@ -37,20 +33,9 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
org.xmpp.forms.DataForm
;
import
org.xmpp.forms.DataForm
;
import
org.xmpp.forms.FormField
;
import
org.xmpp.forms.FormField
;
import
org.xmpp.packet.IQ
;
import
org.xmpp.packet.*
;
import
org.xmpp.packet.JID
;
import
org.xmpp.packet.Message
;
import
java.util.*
;
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
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
...
@@ -133,7 +118,7 @@ public class PubSubEngine {
...
@@ -133,7 +118,7 @@ public class PubSubEngine {
return
TaskEngine
.
getInstance
().
submit
(
new
Runnable
()
{
return
TaskEngine
.
getInstance
().
submit
(
new
Runnable
()
{
@Override
@Override
public
void
run
()
{
public
void
run
()
{
createNode
(
service
,
iq
,
childElement
,
finalAction
);
createNode
(
service
,
iq
,
childElement
,
finalAction
,
getPublishOptions
(
iq
)
);
}
}
});
});
}
}
...
@@ -338,34 +323,42 @@ public class PubSubEngine {
...
@@ -338,34 +323,42 @@ public class PubSubEngine {
if
(
nodeID
==
null
)
{
if
(
nodeID
==
null
)
{
// XEP-0060 Section 7.2.3.3 - No node was specified. Return bad_request error
// 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
// This suggests that Instant nodes should not be auto-created
Element
pubsubError
=
DocumentHelper
.
createElement
(
QName
.
get
(
Element
pubsubError
=
DocumentHelper
.
createElement
(
QName
.
get
(
"nodeid-required"
,
"http://jabber.org/protocol/pubsub#errors"
));
"nodeid-required"
,
"http://jabber.org/protocol/pubsub#errors"
));
sendErrorPacket
(
iq
,
PacketError
.
Condition
.
bad_request
,
pubsubError
);
sendErrorPacket
(
iq
,
PacketError
.
Condition
.
bad_request
,
pubsubError
);
return
;
return
;
}
}
else
{
// Look for the specified node
// Optional Publish Options.
node
=
service
.
getNode
(
nodeID
);
final
DataForm
publishOptions
=
getPublishOptions
(
iq
);
if
(
node
==
null
)
{
if
(
service
instanceof
PEPService
&&
service
.
isServiceAdmin
(
owner
)){
// Look for the specified node
// If it is a PEP service & publisher is service owner -
node
=
service
.
getNode
(
nodeID
);
// auto create nodes.
if
(
node
==
null
)
{
Element
childElement
=
iq
.
getChildElement
();
if
(
service
instanceof
PEPService
&&
service
.
isServiceAdmin
(
owner
)
&&
canAutoCreate
(
publishOptions
)
)
{
CreateNodeResponse
response
=
createNodeHelper
(
service
,
iq
,
childElement
,
publishElement
);
// 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
if
(
response
.
newNode
==
null
)
{
// in disco#info, node creation error should be sent to the client.
// New node creation failed. Since pep#auto-create is advertised
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
// in disco#info, node creation error should be sent to the client.
}
else
{
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
// 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
;
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 {
...
@@ -433,6 +426,120 @@ public class PubSubEngine {
leafNode
.
publishItems
(
from
,
items
);
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
)
{
private
void
deleteItems
(
PubSubService
service
,
IQ
iq
,
Element
retractElement
)
{
String
nodeID
=
retractElement
.
attributeValue
(
"node"
);
String
nodeID
=
retractElement
.
attributeValue
(
"node"
);
Node
node
;
Node
node
;
...
@@ -1129,9 +1236,9 @@ public class PubSubEngine {
...
@@ -1129,9 +1236,9 @@ public class PubSubEngine {
leafNode
.
sendPublishedItems
(
iq
,
items
,
forceToIncludePayload
);
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.
// 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
)
{
if
(
response
.
newNode
==
null
)
{
// New node creation failed
// New node creation failed
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
sendErrorPacket
(
iq
,
response
.
creationStatus
,
response
.
pubsubError
);
...
@@ -1174,13 +1281,9 @@ public class PubSubEngine {
...
@@ -1174,13 +1281,9 @@ public class PubSubEngine {
* <br/>NOTE 2: This method calls UserManager::isRegisteredUser(JID) which can block waiting for a response - so
* <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
* 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}
* @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
// Get sender of the IQ packet
JID
from
=
iq
.
getFrom
();
JID
from
=
iq
.
getFrom
();
// Verify that sender has permissions to create nodes
// Verify that sender has permissions to create nodes
...
@@ -1213,36 +1316,53 @@ public class PubSubEngine {
...
@@ -1213,36 +1316,53 @@ public class PubSubEngine {
Element
configureElement
=
childElement
.
element
(
"configure"
);
Element
configureElement
=
childElement
.
element
(
"configure"
);
if
(
configureElement
!=
null
)
{
if
(
configureElement
!=
null
)
{
// Get the data form that contains the parent nodeID
// Get the data form that contains the parent nodeID
completedForm
=
getSentConfigurationForm
(
configureElement
);
completedForm
=
getSentConfigurationForm
(
configureElement
);
if
(
completedForm
!=
null
)
{
}
// Calculate newNodeID when new node is affiliated with a Collection
FormField
field
=
completedForm
.
getField
(
"pubsub#collection"
);
if
(
publishOptions
!=
null
)
{
if
(
field
!=
null
)
{
// Apply publish options to override provided config.
List
<
String
>
values
=
field
.
getValues
();
if
(
completedForm
==
null
)
{
if
(!
values
.
isEmpty
())
{
completedForm
=
publishOptions
;
String
parentNodeID
=
values
.
get
(
0
);
}
else
{
Node
tempNode
=
service
.
getNode
(
parentNodeID
);
for
(
final
FormField
publishOption
:
publishOptions
.
getFields
()
)
{
if
(
tempNode
==
null
)
{
completedForm
.
removeField
(
publishOption
.
getVariable
()
);
// Requested parent node was not found so return an error
final
FormField
formField
=
completedForm
.
addField
(
publishOption
.
getVariable
(),
publishOption
.
getLabel
(),
publishOption
.
getType
()
);
return
new
CreateNodeResponse
(
PacketError
.
Condition
.
item_not_found
,
null
,
null
);
for
(
final
String
value
:
publishOption
.
getValues
()
)
{
}
formField
.
addValue
(
value
);
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
(
completedForm
!=
null
)
{
if
(!
values
.
isEmpty
())
{
// Calculate newNodeID when new node is affiliated with a Collection
collectionType
=
"collection"
.
equals
(
values
.
get
(
0
));
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 no parent was defined then use the root collection node
if
(
parentNode
==
null
&&
service
.
isCollectionNodesSupported
())
{
if
(
parentNode
==
null
&&
service
.
isCollectionNodesSupported
())
{
parentNode
=
service
.
getRootCollectionNode
();
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
...
@@ -679,6 +679,8 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
features
.
add
(
"http://jabber.org/protocol/pubsub#subscribe"
);
features
.
add
(
"http://jabber.org/protocol/pubsub#subscribe"
);
// Configuration of subscription options is supported
// Configuration of subscription options is supported
features
.
add
(
"http://jabber.org/protocol/pubsub#subscription-options"
);
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
)
{
else
if
(
name
==
null
)
{
// Answer the features of a given node
// 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