Search in sources :

Example 1 with AccessModel

use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.

the class IQPEPHandler method getUserItems.

/**
     * Implements UserItemsProvider, adding PEP related items to a disco#items
     * result.
     */
@Override
public Iterator<Element> getUserItems(String name, JID senderJID) {
    ArrayList<Element> items = new ArrayList<>();
    String recipientJID = XMPPServer.getInstance().createJID(name, null, true).toBareJID();
    PEPService pepService = pepServiceManager.getPEPService(recipientJID);
    if (pepService != null) {
        CollectionNode rootNode = pepService.getRootCollectionNode();
        Element defaultItem = DocumentHelper.createElement("item");
        defaultItem.addAttribute("jid", recipientJID);
        for (Node node : pepService.getNodes()) {
            // Do not include the root node as an item element.
            if (node == rootNode) {
                continue;
            }
            AccessModel accessModel = node.getAccessModel();
            if (accessModel.canAccessItems(node, senderJID, new JID(recipientJID))) {
                Element item = defaultItem.createCopy();
                item.addAttribute("node", node.getNodeID());
                items.add(item);
            }
        }
    }
    return items.iterator();
}
Also used : JID(org.xmpp.packet.JID) AccessModel(org.jivesoftware.openfire.pubsub.models.AccessModel) Element(org.dom4j.Element) CollectionNode(org.jivesoftware.openfire.pubsub.CollectionNode) Node(org.jivesoftware.openfire.pubsub.Node) LeafNode(org.jivesoftware.openfire.pubsub.LeafNode) ArrayList(java.util.ArrayList) CollectionNode(org.jivesoftware.openfire.pubsub.CollectionNode)

Example 2 with AccessModel

use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.

the class PubSubEngine method getPublishedItems.

private void getPublishedItems(PubSubService service, IQ iq, Element itemsElement) {
    String nodeID = itemsElement.attributeValue("node");
    String subID = itemsElement.attributeValue("subid");
    Node node;
    if (nodeID == null) {
        // User must specify a leaf node ID so return a nodeid-required error
        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) {
            // Node does not exist. Return item-not-found error
            sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
            return;
        }
    }
    if (node.isCollectionNode()) {
        // Node is a collection node. Return feature-not-implemented error
        Element pubsubError = DocumentHelper.createElement(QName.get("unsupported", "http://jabber.org/protocol/pubsub#errors"));
        pubsubError.addAttribute("feature", "retrieve-items");
        sendErrorPacket(iq, PacketError.Condition.feature_not_implemented, pubsubError);
        return;
    }
    // Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
    JID subscriberJID = iq.getFrom();
    // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
    JID owner = subscriberJID.asBareJID();
    // Check if the node's access model allows the subscription to proceed
    AccessModel accessModel = node.getAccessModel();
    if (!accessModel.canAccessItems(node, owner, subscriberJID)) {
        sendErrorPacket(iq, accessModel.getSubsriptionError(), accessModel.getSubsriptionErrorDetail());
        return;
    }
    // Check that the requester is not an outcast
    NodeAffiliate affiliate = node.getAffiliate(owner);
    if (affiliate != null && affiliate.getAffiliation() == NodeAffiliate.Affiliation.outcast) {
        sendErrorPacket(iq, PacketError.Condition.forbidden, null);
        return;
    }
    // Get the user's subscription
    NodeSubscription subscription = null;
    if (node.isMultipleSubscriptionsEnabled() && (node.getSubscriptions(owner).size() > 1)) {
        if (subID == null) {
            // No subid was specified and the node supports multiple subscriptions and the user
            // has multiple subscriptions
            Element pubsubError = DocumentHelper.createElement(QName.get("subid-required", "http://jabber.org/protocol/pubsub#errors"));
            sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
            return;
        } else {
            // Check if the specified subID belongs to an existing node subscription
            subscription = node.getSubscription(subID);
            if (subscription == null) {
                Element pubsubError = DocumentHelper.createElement(QName.get("invalid-subid", "http://jabber.org/protocol/pubsub#errors"));
                sendErrorPacket(iq, PacketError.Condition.not_acceptable, pubsubError);
                return;
            }
        }
    }
    if (subscription != null && !subscription.isActive()) {
        Element pubsubError = DocumentHelper.createElement(QName.get("not-subscribed", "http://jabber.org/protocol/pubsub#errors"));
        sendErrorPacket(iq, PacketError.Condition.not_authorized, pubsubError);
        return;
    }
    LeafNode leafNode = (LeafNode) node;
    // Get list of items to send to the user
    boolean forceToIncludePayload = false;
    List<PublishedItem> items;
    String max_items = itemsElement.attributeValue("max_items");
    int recentItems = 0;
    if (max_items != null) {
        try {
            // Parse the recent number of items requested
            recentItems = Integer.parseInt(max_items);
        } catch (NumberFormatException e) {
            // There was an error parsing the number so assume that all items were requested
            Log.warn("Assuming that all items were requested", e);
            max_items = null;
        }
    }
    if (max_items != null) {
        // Get the N most recent published items
        items = new ArrayList<>(leafNode.getPublishedItems(recentItems));
    } else {
        List requestedItems = itemsElement.elements("item");
        if (requestedItems.isEmpty()) {
            // Get all the active items that were published to the node
            items = new ArrayList<>(leafNode.getPublishedItems());
        } else {
            items = new ArrayList<>();
            // Indicate that payload should be included (if exists) no matter
            // the node configuration
            forceToIncludePayload = true;
            // Get the items as requested by the user
            for (Iterator it = requestedItems.iterator(); it.hasNext(); ) {
                Element element = (Element) it.next();
                String itemID = element.attributeValue("id");
                PublishedItem item = leafNode.getPublishedItem(itemID);
                if (item != null) {
                    items.add(item);
                }
            }
        }
    }
    if (subscription != null && subscription.getKeyword() != null) {
        // Filter items that do not match the subscription keyword
        for (Iterator<PublishedItem> it = items.iterator(); it.hasNext(); ) {
            PublishedItem item = it.next();
            if (!subscription.isKeywordMatched(item)) {
                // Remove item that does not match keyword
                it.remove();
            }
        }
    }
    // Send items to the user
    leafNode.sendPublishedItems(iq, items, forceToIncludePayload);
}
Also used : JID(org.xmpp.packet.JID) AccessModel(org.jivesoftware.openfire.pubsub.models.AccessModel) Element(org.dom4j.Element) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with AccessModel

use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.

the class PEPService method sendNotification.

@Override
public void sendNotification(Node node, Message message, JID recipientJID) {
    message.setTo(recipientJID);
    message.setFrom(getAddress());
    message.setID(StringUtils.randomString(8));
    // If the recipient subscribed with a bare JID and this PEPService can retrieve
    // presence information for the recipient, collect all of their full JIDs and
    // send the notification to each below.
    Set<JID> recipientFullJIDs = new HashSet<>();
    if (XMPPServer.getInstance().isLocal(recipientJID)) {
        if (recipientJID.getResource() == null) {
            for (ClientSession clientSession : SessionManager.getInstance().getSessions(recipientJID.getNode())) {
                recipientFullJIDs.add(clientSession.getAddress());
            }
        }
    } else {
        // Since recipientJID is not local, try to get presence info from cached known remote
        // presences.
        // TODO: OF-605 the old code depends on a cache that would contain presence state on all (?!) JIDS on all (?!)
        // remote domains. As we cannot depend on this information to be correct (even if we could ensure that this
        // potentially unlimited amount of data would indeed be manageable in the first place), this code was removed.
        recipientFullJIDs.add(recipientJID);
    }
    if (recipientFullJIDs.isEmpty()) {
        router.route(message);
        return;
    }
    for (JID recipientFullJID : recipientFullJIDs) {
        // to the service owner.
        try {
            JID publisher = null;
            // Get the ID of the node that had an item published to or retracted from.
            Element itemsElement = message.getElement().element("event").element("items");
            String nodeID = itemsElement.attributeValue("node");
            // Get the ID of the item that was published or retracted.
            String itemID = null;
            Element itemElement = itemsElement.element("item");
            if (itemElement == null) {
                Element retractElement = itemsElement.element("retract");
                if (retractElement != null) {
                    itemID = retractElement.attributeValue("id");
                }
            } else {
                itemID = itemElement.attributeValue("id");
            }
            // Check if the recipientFullJID is interested in notifications for this node.
            // If the recipient has not yet requested any notification filtering, continue and send
            // the notification.
            EntityCapabilities entityCaps = entityCapsManager.getEntityCapabilities(recipientFullJID);
            if (entityCaps != null) {
                if (!entityCaps.containsFeature(nodeID + "+notify")) {
                    return;
                }
            }
            // This full JID will be used as the "replyto" address in the addressing extension.
            if (node.isCollectionNode()) {
                for (Node leafNode : node.getNodes()) {
                    if (leafNode.getNodeID().equals(nodeID)) {
                        publisher = leafNode.getPublishedItem(itemID).getPublisher();
                        // Ensure the recipientJID has access to receive notifications for items published to the leaf node.
                        AccessModel accessModel = leafNode.getAccessModel();
                        if (!accessModel.canAccessItems(leafNode, recipientFullJID, publisher)) {
                            return;
                        }
                        break;
                    }
                }
            } else {
                publisher = node.getPublishedItem(itemID).getPublisher();
            }
            // Ensure the recipient is subscribed to the service owner's (publisher's) presence.
            if (canProbePresence(publisher, recipientFullJID)) {
                Element addresses = DocumentHelper.createElement(QName.get("addresses", "http://jabber.org/protocol/address"));
                Element address = addresses.addElement("address");
                address.addAttribute("type", "replyto");
                address.addAttribute("jid", publisher.toString());
                Message extendedMessage = message.createCopy();
                extendedMessage.addExtension(new PacketExtension(addresses));
                extendedMessage.setTo(recipientFullJID);
                router.route(extendedMessage);
            }
        } catch (IndexOutOfBoundsException e) {
        // Do not add addressing extension to message.
        } catch (UserNotFoundException e) {
            // Do not add addressing extension to message.
            router.route(message);
        } catch (NullPointerException e) {
            try {
                if (canProbePresence(getAddress(), recipientFullJID)) {
                    message.setTo(recipientFullJID);
                }
            } catch (UserNotFoundException e1) {
            // Do nothing
            }
            router.route(message);
        }
    }
}
Also used : PacketExtension(org.xmpp.packet.PacketExtension) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) JID(org.xmpp.packet.JID) Message(org.xmpp.packet.Message) AccessModel(org.jivesoftware.openfire.pubsub.models.AccessModel) Element(org.dom4j.Element) CollectionNode(org.jivesoftware.openfire.pubsub.CollectionNode) Node(org.jivesoftware.openfire.pubsub.Node) EntityCapabilities(org.jivesoftware.openfire.entitycaps.EntityCapabilities) ClientSession(org.jivesoftware.openfire.session.ClientSession) HashSet(java.util.HashSet)

Example 4 with AccessModel

use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.

the class PubSubEngine method subscribeNode.

private void subscribeNode(PubSubService service, IQ iq, Element childElement, Element subscribeElement) {
    String nodeID = subscribeElement.attributeValue("node");
    Node node;
    if (nodeID == null) {
        if (service.isCollectionNodesSupported()) {
            // Entity subscribes to root collection node
            node = service.getRootCollectionNode();
        } else {
            // Service does not have a root collection node so return a nodeid-required error
            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) {
            // Node does not exist. Return item-not-found error
            sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
            return;
        }
    }
    // Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
    JID from = iq.getFrom();
    JID subscriberJID = new JID(subscribeElement.attributeValue("jid"));
    if (!from.toBareJID().equals(subscriberJID.toBareJID()) && !service.isServiceAdmin(from)) {
        // JIDs do not match and requestor is not a service admin so return an error
        Element pubsubError = DocumentHelper.createElement(QName.get("invalid-jid", "http://jabber.org/protocol/pubsub#errors"));
        sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
        return;
    }
    // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
    JID owner = subscriberJID.asBareJID();
    // Check if the node's access model allows the subscription to proceed
    AccessModel accessModel = node.getAccessModel();
    if (!accessModel.canSubscribe(node, owner, subscriberJID)) {
        sendErrorPacket(iq, accessModel.getSubsriptionError(), accessModel.getSubsriptionErrorDetail());
        return;
    }
    // Check if the subscriber is an anonymous user
    if (!UserManager.getInstance().isRegisteredUser(subscriberJID)) {
        // Anonymous users cannot subscribe to the node. Return forbidden error
        sendErrorPacket(iq, PacketError.Condition.forbidden, null);
        return;
    }
    // Check if the subscription owner is a user with outcast affiliation
    NodeAffiliate nodeAffiliate = node.getAffiliate(owner);
    if (nodeAffiliate != null && nodeAffiliate.getAffiliation() == NodeAffiliate.Affiliation.outcast) {
        // Subscriber is an outcast. Return forbidden error
        sendErrorPacket(iq, PacketError.Condition.forbidden, null);
        return;
    }
    // Check that subscriptions to the node are enabled
    if (!node.isSubscriptionEnabled() && !service.isServiceAdmin(from)) {
        // Sender is not a sysadmin and subscription is disabled so return an error
        sendErrorPacket(iq, PacketError.Condition.not_allowed, null);
        return;
    }
    // Get any configuration form included in the options element (if any)
    DataForm optionsForm = null;
    Element options = childElement.element("options");
    if (options != null) {
        Element formElement = options.element(QName.get("x", "jabber:x:data"));
        if (formElement != null) {
            optionsForm = new DataForm(formElement);
        }
    }
    // creating another subscription or not
    if (!node.isCollectionNode() && !node.isMultipleSubscriptionsEnabled()) {
        NodeSubscription existingSubscription = node.getSubscription(subscriberJID);
        if (existingSubscription != null) {
            // User is trying to create another subscription so
            // return current subscription state
            existingSubscription.sendSubscriptionState(iq);
            return;
        }
    }
    // Check if subscribing twice to a collection node using same subscription type
    if (node.isCollectionNode()) {
        // By default assume that new subscription is of type node
        boolean isNodeType = true;
        if (optionsForm != null) {
            FormField field = optionsForm.getField("pubsub#subscription_type");
            if (field != null) {
                if ("items".equals(field.getValues().get(0))) {
                    isNodeType = false;
                }
            }
        }
        if (nodeAffiliate != null) {
            for (NodeSubscription subscription : nodeAffiliate.getSubscriptions()) {
                if (isNodeType) {
                    // User is requesting a subscription of type "nodes"
                    if (NodeSubscription.Type.nodes == subscription.getType()) {
                        // Cannot have 2 subscriptions of the same type. Return conflict error
                        sendErrorPacket(iq, PacketError.Condition.conflict, null);
                        return;
                    }
                } else if (!node.isMultipleSubscriptionsEnabled()) {
                    // multiple subscriptions is not allowed
                    if (NodeSubscription.Type.items == subscription.getType()) {
                        // User is trying to create another subscription so
                        // return current subscription state
                        subscription.sendSubscriptionState(iq);
                        return;
                    }
                }
            }
        }
    }
    // Create a subscription and an affiliation if the subscriber doesn't have one
    node.createSubscription(iq, owner, subscriberJID, accessModel.isAuthorizationRequired(), optionsForm);
}
Also used : JID(org.xmpp.packet.JID) AccessModel(org.jivesoftware.openfire.pubsub.models.AccessModel) Element(org.dom4j.Element) DataForm(org.xmpp.forms.DataForm) FormField(org.xmpp.forms.FormField)

Aggregations

Element (org.dom4j.Element)4 AccessModel (org.jivesoftware.openfire.pubsub.models.AccessModel)4 JID (org.xmpp.packet.JID)4 ArrayList (java.util.ArrayList)2 CollectionNode (org.jivesoftware.openfire.pubsub.CollectionNode)2 Node (org.jivesoftware.openfire.pubsub.Node)2 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 List (java.util.List)1 EntityCapabilities (org.jivesoftware.openfire.entitycaps.EntityCapabilities)1 LeafNode (org.jivesoftware.openfire.pubsub.LeafNode)1 ClientSession (org.jivesoftware.openfire.session.ClientSession)1 UserNotFoundException (org.jivesoftware.openfire.user.UserNotFoundException)1 DataForm (org.xmpp.forms.DataForm)1 FormField (org.xmpp.forms.FormField)1 Message (org.xmpp.packet.Message)1 PacketExtension (org.xmpp.packet.PacketExtension)1