Software / code / prosody
Comparison
plugins/mod_pubsub/pubsub.lib.lua @ 5626:8416d4619d80
mod_pubsub: Split out handlers into a module library
| author | Florian Zeitz <florob@babelmonkeys.de> |
|---|---|
| date | Fri, 17 May 2013 18:33:32 +0200 |
| child | 5851:cdcfd93e2f43 |
comparison
equal
deleted
inserted
replaced
| 5625:e67891ad18d6 | 5626:8416d4619d80 |
|---|---|
| 1 local st = require "util.stanza"; | |
| 2 local uuid_generate = require "util.uuid".generate; | |
| 3 | |
| 4 local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; | |
| 5 local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors"; | |
| 6 | |
| 7 local _M = {}; | |
| 8 | |
| 9 local handlers = {}; | |
| 10 _M.handlers = handlers; | |
| 11 | |
| 12 local pubsub_errors = { | |
| 13 ["conflict"] = { "cancel", "conflict" }; | |
| 14 ["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" }; | |
| 15 ["jid-required"] = { "modify", "bad-request", nil, "jid-required" }; | |
| 16 ["nodeid-required"] = { "modify", "bad-request", nil, "nodeid-required" }; | |
| 17 ["item-not-found"] = { "cancel", "item-not-found" }; | |
| 18 ["not-subscribed"] = { "modify", "unexpected-request", nil, "not-subscribed" }; | |
| 19 ["forbidden"] = { "cancel", "forbidden" }; | |
| 20 }; | |
| 21 local function pubsub_error_reply(stanza, error) | |
| 22 local e = pubsub_errors[error]; | |
| 23 local reply = st.error_reply(stanza, unpack(e, 1, 3)); | |
| 24 if e[4] then | |
| 25 reply:tag(e[4], { xmlns = xmlns_pubsub_errors }):up(); | |
| 26 end | |
| 27 return reply; | |
| 28 end | |
| 29 _M.pubsub_error_reply = pubsub_error_reply; | |
| 30 | |
| 31 function handlers.get_items(origin, stanza, items, service) | |
| 32 local node = items.attr.node; | |
| 33 local item = items:get_child("item"); | |
| 34 local id = item and item.attr.id; | |
| 35 | |
| 36 if not node then | |
| 37 return origin.send(pubsub_error_reply(stanza, "nodeid-required")); | |
| 38 end | |
| 39 local ok, results = service:get_items(node, stanza.attr.from, id); | |
| 40 if not ok then | |
| 41 return origin.send(pubsub_error_reply(stanza, results)); | |
| 42 end | |
| 43 | |
| 44 local data = st.stanza("items", { node = node }); | |
| 45 for _, entry in pairs(results) do | |
| 46 data:add_child(entry); | |
| 47 end | |
| 48 local reply; | |
| 49 if data then | |
| 50 reply = st.reply(stanza) | |
| 51 :tag("pubsub", { xmlns = xmlns_pubsub }) | |
| 52 :add_child(data); | |
| 53 else | |
| 54 reply = pubsub_error_reply(stanza, "item-not-found"); | |
| 55 end | |
| 56 return origin.send(reply); | |
| 57 end | |
| 58 | |
| 59 function handlers.get_subscriptions(origin, stanza, subscriptions, service) | |
| 60 local node = subscriptions.attr.node; | |
| 61 local ok, ret = service:get_subscriptions(node, stanza.attr.from, stanza.attr.from); | |
| 62 if not ok then | |
| 63 return origin.send(pubsub_error_reply(stanza, ret)); | |
| 64 end | |
| 65 local reply = st.reply(stanza) | |
| 66 :tag("pubsub", { xmlns = xmlns_pubsub }) | |
| 67 :tag("subscriptions"); | |
| 68 for _, sub in ipairs(ret) do | |
| 69 reply:tag("subscription", { node = sub.node, jid = sub.jid, subscription = 'subscribed' }):up(); | |
| 70 end | |
| 71 return origin.send(reply); | |
| 72 end | |
| 73 | |
| 74 function handlers.set_create(origin, stanza, create, service) | |
| 75 local node = create.attr.node; | |
| 76 local ok, ret, reply; | |
| 77 if node then | |
| 78 ok, ret = service:create(node, stanza.attr.from); | |
| 79 if ok then | |
| 80 reply = st.reply(stanza); | |
| 81 else | |
| 82 reply = pubsub_error_reply(stanza, ret); | |
| 83 end | |
| 84 else | |
| 85 repeat | |
| 86 node = uuid_generate(); | |
| 87 ok, ret = service:create(node, stanza.attr.from); | |
| 88 until ok or ret ~= "conflict"; | |
| 89 if ok then | |
| 90 reply = st.reply(stanza) | |
| 91 :tag("pubsub", { xmlns = xmlns_pubsub }) | |
| 92 :tag("create", { node = node }); | |
| 93 else | |
| 94 reply = pubsub_error_reply(stanza, ret); | |
| 95 end | |
| 96 end | |
| 97 return origin.send(reply); | |
| 98 end | |
| 99 | |
| 100 function handlers.set_delete(origin, stanza, delete, service) | |
| 101 local node = delete.attr.node; | |
| 102 | |
| 103 local reply, notifier; | |
| 104 if not node then | |
| 105 return origin.send(pubsub_error_reply(stanza, "nodeid-required")); | |
| 106 end | |
| 107 local ok, ret = service:delete(node, stanza.attr.from); | |
| 108 if ok then | |
| 109 reply = st.reply(stanza); | |
| 110 else | |
| 111 reply = pubsub_error_reply(stanza, ret); | |
| 112 end | |
| 113 return origin.send(reply); | |
| 114 end | |
| 115 | |
| 116 function handlers.set_subscribe(origin, stanza, subscribe, service) | |
| 117 local node, jid = subscribe.attr.node, subscribe.attr.jid; | |
| 118 if not (node and jid) then | |
| 119 return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "invalid-jid")); | |
| 120 end | |
| 121 --[[ | |
| 122 local options_tag, options = stanza.tags[1]:get_child("options"), nil; | |
| 123 if options_tag then | |
| 124 options = options_form:data(options_tag.tags[1]); | |
| 125 end | |
| 126 --]] | |
| 127 local options_tag, options; -- FIXME | |
| 128 local ok, ret = service:add_subscription(node, stanza.attr.from, jid, options); | |
| 129 local reply; | |
| 130 if ok then | |
| 131 reply = st.reply(stanza) | |
| 132 :tag("pubsub", { xmlns = xmlns_pubsub }) | |
| 133 :tag("subscription", { | |
| 134 node = node, | |
| 135 jid = jid, | |
| 136 subscription = "subscribed" | |
| 137 }):up(); | |
| 138 if options_tag then | |
| 139 reply:add_child(options_tag); | |
| 140 end | |
| 141 else | |
| 142 reply = pubsub_error_reply(stanza, ret); | |
| 143 end | |
| 144 origin.send(reply); | |
| 145 end | |
| 146 | |
| 147 function handlers.set_unsubscribe(origin, stanza, unsubscribe, service) | |
| 148 local node, jid = unsubscribe.attr.node, unsubscribe.attr.jid; | |
| 149 if not (node and jid) then | |
| 150 return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "invalid-jid")); | |
| 151 end | |
| 152 local ok, ret = service:remove_subscription(node, stanza.attr.from, jid); | |
| 153 local reply; | |
| 154 if ok then | |
| 155 reply = st.reply(stanza); | |
| 156 else | |
| 157 reply = pubsub_error_reply(stanza, ret); | |
| 158 end | |
| 159 return origin.send(reply); | |
| 160 end | |
| 161 | |
| 162 function handlers.set_publish(origin, stanza, publish, service) | |
| 163 local node = publish.attr.node; | |
| 164 if not node then | |
| 165 return origin.send(pubsub_error_reply(stanza, "nodeid-required")); | |
| 166 end | |
| 167 local item = publish:get_child("item"); | |
| 168 local id = (item and item.attr.id); | |
| 169 if not id then | |
| 170 id = uuid_generate(); | |
| 171 if item then | |
| 172 item.attr.id = id; | |
| 173 end | |
| 174 end | |
| 175 local ok, ret = service:publish(node, stanza.attr.from, id, item); | |
| 176 local reply; | |
| 177 if ok then | |
| 178 reply = st.reply(stanza) | |
| 179 :tag("pubsub", { xmlns = xmlns_pubsub }) | |
| 180 :tag("publish", { node = node }) | |
| 181 :tag("item", { id = id }); | |
| 182 else | |
| 183 reply = pubsub_error_reply(stanza, ret); | |
| 184 end | |
| 185 return origin.send(reply); | |
| 186 end | |
| 187 | |
| 188 function handlers.set_retract(origin, stanza, retract, service) | |
| 189 local node, notify = retract.attr.node, retract.attr.notify; | |
| 190 notify = (notify == "1") or (notify == "true"); | |
| 191 local item = retract:get_child("item"); | |
| 192 local id = item and item.attr.id | |
| 193 if not (node and id) then | |
| 194 return origin.send(pubsub_error_reply(stanza, node and "item-not-found" or "nodeid-required")); | |
| 195 end | |
| 196 local reply, notifier; | |
| 197 if notify then | |
| 198 notifier = st.stanza("retract", { id = id }); | |
| 199 end | |
| 200 local ok, ret = service:retract(node, stanza.attr.from, id, notifier); | |
| 201 if ok then | |
| 202 reply = st.reply(stanza); | |
| 203 else | |
| 204 reply = pubsub_error_reply(stanza, ret); | |
| 205 end | |
| 206 return origin.send(reply); | |
| 207 end | |
| 208 | |
| 209 function handlers.set_purge(origin, stanza, purge, service) | |
| 210 local node, notify = purge.attr.node, purge.attr.notify; | |
| 211 notify = (notify == "1") or (notify == "true"); | |
| 212 local reply; | |
| 213 if not node then | |
| 214 return origin.send(pubsub_error_reply(stanza, "nodeid-required")); | |
| 215 end | |
| 216 local ok, ret = service:purge(node, stanza.attr.from, notify); | |
| 217 if ok then | |
| 218 reply = st.reply(stanza); | |
| 219 else | |
| 220 reply = pubsub_error_reply(stanza, ret); | |
| 221 end | |
| 222 return origin.send(reply); | |
| 223 end | |
| 224 | |
| 225 return _M; |