📄 pubsubengine.java
字号:
fullPresences = new ConcurrentHashMap<String, String>(); barePresences.put(subscriber.toBareJID(), fullPresences); } } } Presence.Show show = presence.getShow(); fullPresences.put(subscriber.toString(), show == null ? "online" : show.name()); } else if (presence.getType() == Presence.Type.unavailable) { JID subscriber = presence.getFrom(); Map<String, String> fullPresences = barePresences.get(subscriber.toBareJID()); if (fullPresences != null) { fullPresences.remove(subscriber.toString()); if (fullPresences.isEmpty()) { barePresences.remove(subscriber.toBareJID()); } } } } /** * Handles Message packets sent to the pubsub service. Messages may be of type error * when an event notification was sent to a susbcriber whose address is no longer available.<p> * * Answers to authorization requests sent to node owners to approve pending subscriptions * will also be processed by this method. * * @param message the Message packet sent to the pubsub service. */ public void process(Message message) { if (message.getType() == Message.Type.error) { // Process Messages of type error to identify possible subscribers that no longer exist if (message.getError().getType() == PacketError.Type.cancel) { // TODO Assuming that owner is the bare JID (as defined in the JEP). This can be replaced with an explicit owner specified in the packet JID owner = new JID(message.getFrom().toBareJID()); // Terminate the subscription of the entity to all nodes hosted at the service cancelAllSubscriptions(owner); } else if (message.getError().getType() == PacketError.Type.auth) { // TODO Queue the message to be sent again later (will retry a few times and // will be discarded when the retry limit is reached) } } else if (message.getType() == Message.Type.normal) { // Check that this is an answer to an authorization request DataForm authForm = (DataForm) message.getExtension("x", "jabber:x:data"); if (authForm != null && authForm.getType() == DataForm.Type.submit) { String formType = authForm.getField("FORM_TYPE").getValues().get(0); // Check that completed data form belongs to an authorization request if ("http://jabber.org/protocol/pubsub#subscribe_authorization".equals(formType)) { // Process the answer to the authorization request processAuthorizationAnswer(authForm, message); } } } } private void publishItemsToNode(IQ iq, Element publishElement) { String nodeID = publishElement.attributeValue("node"); Node node; if (nodeID == null) { // No node was specified. Return bad_request 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; } } JID from = iq.getFrom(); // TODO Assuming that owner is the bare JID (as defined in the JEP). This can be replaced with an explicit owner specified in the packet JID owner = new JID(from.toBareJID()); if (!node.getPublisherModel().canPublish(node, owner) && !service.isServiceAdmin(owner)) { // Entity does not have sufficient privileges to publish to node sendErrorPacket(iq, PacketError.Condition.forbidden, 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", "publish"); sendErrorPacket(iq, PacketError.Condition.feature_not_implemented, pubsubError); return; } LeafNode leafNode = (LeafNode) node; Iterator itemElements = publishElement.elementIterator("item"); // Check that an item was included if node persist items or includes payload if (!itemElements.hasNext() && leafNode.isItemRequired()) { Element pubsubError = DocumentHelper.createElement(QName.get( "item-required", "http://jabber.org/protocol/pubsub#errors")); sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError); return; } // Check that no item was included if node doesn't persist items and doesn't // includes payload if (itemElements.hasNext() && !leafNode.isItemRequired()) { Element pubsubError = DocumentHelper.createElement(QName.get( "item-forbidden", "http://jabber.org/protocol/pubsub#errors")); sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError); return; } List<Element> items = new ArrayList<Element>(); List entries; Element payload; while (itemElements.hasNext()) { Element item = (Element) itemElements.next(); entries = item.elements(); payload = entries.isEmpty() ? null : (Element) entries.get(0); // Check that a payload was included if node is configured to include payload // in notifications if (payload == null && leafNode.isPayloadDelivered()) { Element pubsubError = DocumentHelper.createElement(QName.get( "payload-required", "http://jabber.org/protocol/pubsub#errors")); sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError); return; } // Check that the payload (if any) contains only one child element if (entries.size() > 1) { Element pubsubError = DocumentHelper.createElement(QName.get( "invalid-payload", "http://jabber.org/protocol/pubsub#errors")); sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError); return; } items.add(item); } // Return success operation router.route(IQ.createResultIQ(iq)); // Publish item and send event notifications to subscribers leafNode.publishItems(from, items); } private void deleteItems(IQ iq, Element retractElement) { String nodeID = retractElement.attributeValue("node"); Node node; if (nodeID == null) { // No node was specified. Return bad_request 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; } } // Get the items to delete Iterator itemElements = retractElement.elementIterator("item"); if (!itemElements.hasNext()) { Element pubsubError = DocumentHelper.createElement(QName.get( "item-required", "http://jabber.org/protocol/pubsub#errors")); sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError); return; } if (node.isCollectionNode()) { // Cannot delete items from a collection node. Return an error. Element pubsubError = DocumentHelper.createElement(QName.get( "unsupported", "http://jabber.org/protocol/pubsub#errors")); pubsubError.addAttribute("feature", "persistent-items"); sendErrorPacket(iq, PacketError.Condition.feature_not_implemented, pubsubError); return; } LeafNode leafNode = (LeafNode) node; if (!leafNode.isItemRequired()) { // Cannot delete items from a leaf node that doesn't handle itemIDs. Return an error. Element pubsubError = DocumentHelper.createElement(QName.get( "unsupported", "http://jabber.org/protocol/pubsub#errors")); pubsubError.addAttribute("feature", "persistent-items"); sendErrorPacket(iq, PacketError.Condition.feature_not_implemented, pubsubError); return; } List<PublishedItem> items = new ArrayList<PublishedItem>(); while (itemElements.hasNext()) { Element itemElement = (Element) itemElements.next(); String itemID = itemElement.attributeValue("id"); if (itemID != null) { PublishedItem item = node.getPublishedItem(itemID); if (item == null) { // ItemID does not exist. Return item-not-found error sendErrorPacket(iq, PacketError.Condition.item_not_found, null); return; } else { if (item.canDelete(iq.getFrom())) { items.add(item); } else { // Publisher does not have sufficient privileges to delete this item sendErrorPacket(iq, PacketError.Condition.forbidden, null); return; } } } else { // No item ID was specified so return a bad_request error Element pubsubError = DocumentHelper.createElement(QName.get( "item-required", "http://jabber.org/protocol/pubsub#errors")); sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError); return; } } // Send reply with success router.route(IQ.createResultIQ(iq)); // Delete items and send subscribers a notification leafNode.deleteItems(items); } private void subscribeNode(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 = new JID(subscriberJID.toBareJID()); // 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -