package org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.get; import java.util.concurrent.BlockingQueue; import org.buddycloud.channelserver.Configuration; import org.buddycloud.channelserver.channel.ChannelManager; import org.buddycloud.channelserver.db.exception.NodeStoreException; import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.JabberPubsub; import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.PubSubElementProcessorAbstract; import org.buddycloud.channelserver.pubsub.model.NodeMembership; import org.buddycloud.channelserver.pubsub.subscription.Subscriptions; import org.buddycloud.channelserver.utils.XMLConstants; import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud; import org.dom4j.Element; import org.dom4j.Namespace; import org.dom4j.QName; import org.xmpp.packet.IQ; import org.xmpp.packet.JID; import org.xmpp.packet.Packet; import org.xmpp.resultsetmanagement.ResultSet; public class SubscriptionsGet extends PubSubElementProcessorAbstract { private IQ result; private String node; private JID actorJid; private IQ requestIq; private boolean ephemeral = false; public SubscriptionsGet(BlockingQueue<Packet> outQueue, ChannelManager channelManager) { setOutQueue(outQueue); setChannelManager(channelManager); } @Override public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exception { result = IQ.createResultIQ(reqIQ); actorJid = actorJID; requestIq = reqIQ; Element pubsub = result.setChildElement(XMLConstants.PUBSUB_ELEM, JabberPubsub.NAMESPACE_URI); Element subscriptions = pubsub.addElement(XMLConstants.SUBSCRIPTIONS_ELEM); node = reqIQ.getChildElement().element(XMLConstants.SUBSCRIPTIONS_ELEM).attributeValue(XMLConstants.NODE_ATTR); if (null == actorJid) { actorJid = reqIQ.getFrom(); } boolean isProcessedLocally = true; if (node == null) { isProcessedLocally = getUserMemberships(subscriptions); } else { if (!Configuration.getInstance().isLocalNode(node)) { result.getElement().addAttribute(XMLConstants.REMOTE_SERVER_DISCOVER_ATTR, Boolean.FALSE.toString()); } isProcessedLocally = getNodeMemberships(subscriptions); } if (!isProcessedLocally) { return; } outQueue.put(result); } /** * Don't include any subscriptions other than Subscriptions.subscriptions, unless the user is * one of owner, moderator or the user. * * @param subscriptions * @return * @throws NodeStoreException * @throws InterruptedException */ private boolean getNodeMemberships(Element subscriptions) throws NodeStoreException, InterruptedException { ResultSet<NodeMembership> cur = channelManager.getNodeMemberships(node); if (Configuration.getInstance().isLocalNode(node)) { subscriptions.addAttribute(XMLConstants.NODE_ATTR, node); for (NodeMembership ns : cur) { if (!isUserPriviledged(ns.getUser()) && !ns.getSubscription().equals(Subscriptions.subscribed)) { continue; } Element subscription = subscriptions.addElement(XMLConstants.SUBSCRIPTION_ELEM); subscription.addAttribute(XMLConstants.NODE_ATTR, ns.getNodeId()) .addAttribute(XMLConstants.SUBSCRIPTION_ELEM, ns.getSubscription().toString()) .addAttribute(XMLConstants.JID_ATTR, ns.getUser().toBareJID()); // Only add the invited by attribute if the user has the necessary priviledges if (null != ns.getInvitedBy() && isUserPriviledged(ns.getUser())) { subscription.addAttribute(XMLConstants.INVITED_BY_ATTR, ns.getInvitedBy().toBareJID()); } } } else { // TODO(garethf) this looks like makeRemoteRequest if (!channelManager.isCachedNode(node) || (null != requestIq.getElement().element(XMLConstants.PUBSUB_ELEM).element(XMLConstants.SET_ELEM)) && !cur.isEmpty()) { makeRemoteRequest(new JID(node.split("/")[2]).getDomain()); } return false; } return true; } /** * Don't include any subscriptions other than Subscriptions.subscriptions, unless the user is * one of owner, moderator or the user. * * @param ns * * @return * @throws NodeStoreException */ private boolean isUserPriviledged(JID jid) throws NodeStoreException { boolean isUser = actorJid.toBareJID().equals(jid.toBareJID()); return (isUser || isOwnerModerator()) ? true : false; } private boolean getUserMemberships(Element subscriptions) throws NodeStoreException, InterruptedException { // let's get all subscriptions. ResultSet<NodeMembership> cur; String ephemeralValue = requestIq.getChildElement().element(XMLConstants.SUBSCRIPTIONS_ELEM) .attributeValue(new QName(XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS))); if ((null != ephemeralValue) && ephemeralValue.equals("true")) { ephemeral = true; } cur = channelManager.getUserMemberships(actorJid, ephemeral); if ((null != requestIq.getElement().element(XMLConstants.PUBSUB_ELEM).element("set")) && (!cur.isEmpty()) && (!Configuration.getInstance().isLocalJID(actorJid))) { makeRemoteRequest(actorJid.getDomain()); return false; } for (NodeMembership ns : cur) { Element subscription = subscriptions.addElement(XMLConstants.SUBSCRIPTION_ELEM); subscription.addAttribute(XMLConstants.NODE_ATTR, ns.getNodeId()) .addAttribute(XMLConstants.SUBSCRIPTION_ELEM, ns.getSubscription().toString()) .addAttribute(XMLConstants.JID_ATTR, ns.getUser().toBareJID()); if (null != ns.getInvitedBy() && isOwnerModerator()) { subscription.addAttribute(XMLConstants.INVITED_BY_ATTR, ns.getInvitedBy().toBareJID()); } } return true; } private boolean isOwnerModerator() throws NodeStoreException { return channelManager.getNodeMembership(node, actorJid).getAffiliation().canAuthorize(); } private void makeRemoteRequest(String to) throws InterruptedException { IQ forwarder = requestIq.createCopy(); forwarder.setTo(to); if (null == forwarder.getElement().element(XMLConstants.PUBSUB_ELEM).element(XMLConstants.ACTOR_ELEM)) { Element actor = forwarder.getElement().element(XMLConstants.PUBSUB_ELEM).addElement(XMLConstants.ACTOR_ELEM, Buddycloud.NS); actor.addText(requestIq.getFrom().toBareJID()); } outQueue.put(forwarder); } @Override public boolean accept(Element elm) { return XMLConstants.SUBSCRIPTIONS_ELEM.equals(elm.getName()); } }