📄 mod_pubsub.erl
字号:
Error; {atomic, {result, Res}} -> broadcast_retract_item(Host, Node, ItemID), {result, Res}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end.subscribe_node(Host, From, JID, Node) -> Sender = jlib:jid_tolower(jlib:jid_remove_resource(From)), SubscriberJID = case jlib:string_to_jid(JID) of error -> {"", "", ""}; J -> J end, Subscriber = jlib:jid_tolower(SubscriberJID), F = fun() -> case mnesia:read({pubsub_node, Node}) of [#pubsub_node{info = Info} = N] -> Affiliation = get_affiliation(Info, Subscriber), if Affiliation /= outcast -> NewInfo = add_subscriber(Info, Subscriber), mnesia:write( N#pubsub_node{info = NewInfo}), {result, []}; true -> {error, ?ERR_NOT_ALLOWED} end; [] -> {error, ?ERR_ITEM_NOT_FOUND} end end, if Sender == Subscriber -> case mnesia:transaction(F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, Res}} -> {result, Res}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end; true -> {error, ?ERR_NOT_ALLOWED} end.unsubscribe_node(Host, From, JID, Node) -> Sender = jlib:jid_tolower(jlib:jid_remove_resource(From)), SubscriberJID = case jlib:string_to_jid(JID) of error -> {"", "", ""}; J -> J end, Subscriber = jlib:jid_tolower(SubscriberJID), F = fun() -> case mnesia:read({pubsub_node, Node}) of [#pubsub_node{info = Info} = N] -> Subscription = get_subscription(Info, Subscriber), if Subscription /= none -> NewInfo = remove_subscriber(Info, Subscriber), mnesia:write( N#pubsub_node{info = NewInfo}), {result, []}; true -> {error, ?ERR_NOT_ALLOWED} end; [] -> {error, ?ERR_ITEM_NOT_FOUND} end end, if Sender == Subscriber -> case mnesia:transaction(F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, Res}} -> {result, Res}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end; true -> {error, ?ERR_NOT_ALLOWED} end.get_items(Host, JID, Node, SMaxItems) -> MaxItems = if SMaxItems == "" -> ?MAXITEMS; true -> case catch list_to_integer(SMaxItems) of {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; Val -> Val end end, case MaxItems of {error, _} = Error -> Error; _ -> case catch mnesia:dirty_read(pubsub_node, Node) of [#pubsub_node{info = Info}] -> Items = lists:sublist(Info#nodeinfo.items, MaxItems), ItemsEls = lists:map( fun(#item{id = ItemID, payload = Payload}) -> ItemAttrs = case ItemID of "" -> []; _ -> [{"id", ItemID}] end, {xmlelement, "item", ItemAttrs, Payload} end, Items), {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_EVENT}], [{xmlelement, "items", [{"node", node_to_string(Node)}], ItemsEls}]}]}; _ -> {error, ?ERR_ITEM_NOT_FOUND} end end.delete_node(Host, JID, Node) -> Owner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), F = fun() -> case mnesia:read({pubsub_node, Node}) of [#pubsub_node{info = Info}] -> case get_affiliation(Info, Owner) of owner -> % TODO: don't iterate over all table Removed = mnesia:foldl( fun(#pubsub_node{node = N, info = #nodeinfo{ entities = Entities }}, Acc) -> case lists:prefix(Node, N) of true -> [{N, Entities} | Acc]; _ -> Acc end end, [], pubsub_node), lists:foreach( fun({N, _}) -> mnesia:delete({pubsub_node, N}) end, Removed), {removed, Removed}; _ -> {error, ?ERR_NOT_ALLOWED} end; [] -> {error, ?ERR_ITEM_NOT_FOUND} end end, case mnesia:transaction(F) of {atomic, {error, _} = Error} -> Error; {atomic, {removed, Removed}} -> broadcast_removed_node(Host, Removed), Lang = "", broadcast_retract_item( Host, ["pubsub", "nodes"], node_to_string(Node)), {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end.purge_node(Host, JID, Node) -> Owner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), F = fun() -> case mnesia:read({pubsub_node, Node}) of [#pubsub_node{info = Info} = N] -> case get_affiliation(Info, Owner) of owner -> NewInfo = Info#nodeinfo{items = []}, mnesia:write( N#pubsub_node{info = NewInfo}), {result, Info#nodeinfo.items, []}; _ -> {error, ?ERR_NOT_ALLOWED} end; [] -> {error, ?ERR_ITEM_NOT_FOUND} end end, case mnesia:transaction(F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, Items, Res}} -> lists:foreach( fun(#item{id = ItemID}) -> broadcast_retract_item(Host, Node, ItemID) end, Items), {result, Res}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end.get_entities(OJID, Node) -> Owner = jlib:jid_tolower(jlib:jid_remove_resource(OJID)), case catch mnesia:dirty_read(pubsub_node, Node) of [#pubsub_node{info = Info}] -> case get_affiliation(Info, Owner) of owner -> Entities = Info#nodeinfo.entities, EntitiesEls = ?DICT:fold( fun(JID, #entity{affiliation = Affiliation, subscription = Subscription}, Acc) -> [{xmlelement, "entity", [{"jid", jlib:jid_to_string(JID)}, {"affiliation", affiliation_to_string(Affiliation)}, {"subscription", subscription_to_string(Subscription)}], []} | Acc] end, [], Entities), {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_EVENT}], [{xmlelement, "entities", [{"node", node_to_string(Node)}], EntitiesEls}]}]}; _ -> {error, ?ERR_NOT_ALLOWED} end; _ -> {error, ?ERR_ITEM_NOT_FOUND} end.set_entities(OJID, Node, EntitiesEls) -> Owner = jlib:jid_tolower(jlib:jid_remove_resource(OJID)), Entities = lists:foldl( fun(El, Acc) -> case Acc of error -> error; _ -> case El of {xmlelement, "entity", Attrs, _} -> JID = jlib:string_to_jid( xml:get_attr_s("jid", Attrs)), Affiliation = case xml:get_attr_s("affiliation", Attrs) of "owner" -> owner; "publisher" -> publisher; "outcast" -> outcast; "none" -> none; _ -> false end, Subscription = case xml:get_attr_s("subscription", Attrs) of "subscribed" -> subscribed; "pending" -> pending; "unconfigured" -> unconfigured; "none" -> none; _ -> false end, if (JID == error) or (Affiliation == false) or (Subscription == false) -> error; true -> [{jlib:jid_tolower(JID), #entity{ affiliation = Affiliation, subscription = Subscription}} | Acc] end end end end, [], EntitiesEls), case Entities of error -> {error, ?ERR_BAD_REQUEST}; _ -> F = fun() -> case mnesia:read({pubsub_node, Node}) of [#pubsub_node{info = Info} = N] -> case get_affiliation(Info, Owner) of owner -> NewInfo = set_info_entities(Info, Entities), mnesia:write( N#pubsub_node{info = NewInfo}), {result, []}; _ -> {error, ?ERR_NOT_ALLOWED} end; [] -> {error, ?ERR_ITEM_NOT_FOUND} end end, case mnesia:transaction(F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, _}} -> {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end end.%get_node_config(OJID, Node) ->% Owner = jlib:jid_tolower(jlib:jid_remove_resource(OJID)),% case catch mnesia:dirty_read(pubsub_node, Node) of% [#pubsub_node{info = Info}] ->% case get_affiliation(Info, Owner) of% owner ->% Entities = Info#nodeinfo.entities,% EntitiesEls =% ?DICT:fold(% fun(JID,% #entity{affiliation = Affiliation,% subscription = Subscription},% Acc) ->% [{xmlelement, "entity",% [{"jid", jlib:jid_to_string(JID)},% {"affiliation",% affiliation_to_string(Affiliation)},% {"subscription",% subscription_to_string(Subscription)}],% []} | Acc]% end, [], Entities),% {result, [{xmlelement, "pubsub",% [{"xmlns", ?NS_PUBSUB_EVENT}],% [{xmlelement, "entities",% [{"node", node_to_string(Node)}],% EntitiesEls}]}]};% _ ->% {error, ?ERR_NOT_ALLOWED}% end;% _ ->% {error, ?ERR_ITEM_NOT_FOUND}% end.get_affiliation(#nodeinfo{entities = Entities}, JID) -> LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), case ?DICT:find(LJID, Entities) of {ok, #entity{affiliation = Affiliation}} -> Affiliation; _ -> none end.get_subscription(#nodeinfo{entities = Entities}, JID) -> LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), case ?DICT:find(LJID, Entities) of {ok, #entity{subscription = Subscription}} -> Subscription; _ -> none end.affiliation_to_string(Affiliation) -> case Affiliation of owner -> "owner"; publisher -> "publisher"; outcast -> "outcast"; _ -> "none" end.subscription_to_string(Subscription) -> case Subscription of subscribed -> "subscribed"; pending -> "pending"; unconfigured -> "unconfigured"; _ -> "none" end.check_create_permission(Host, Node, Owner) -> if Owner#jid.lserver == Host -> true; true -> #jid{luser = User, lserver = Server} = Owner, case Node of ["home", Server, User | _] -> true; _ -> false end end.insert_item(Info, ItemID, Publisher, Payload) -> Items = Info#nodeinfo.items, Items1 = lists:filter(fun(I) -> I#item.id /= ItemID end, Items), Items2 = [#item{id = ItemID, publisher = Publisher, payload = Payload} | Items1], Items3 = lists:sublist(Items2, ?MAXITEMS), Info#nodeinfo{items = Items3}.remove_item(Info, ItemID) -> Items = Info#nodeinfo.items, Items1 = lists:filter(fun(I) -> I#item.id /= ItemID end, Items), Info#nodeinfo{items = Items1}.check_item_publisher(Info, ItemID, Publisher) -> Items = Info#nodeinfo.items, case lists:keysearch(ItemID, #item.id, Items) of {value, #item{publisher = Publisher}} -> true; _ -> false end.add_subscriber(Info, Subscriber) -> Entities = Info#nodeinfo.entities, case ?DICT:find(Subscriber, Entities) of {ok, Entity} -> Info#nodeinfo{ entities = ?DICT:store(Subscriber, Entity#entity{subscription = subscribed}, Entities)}; _ -> Info#nodeinfo{ entities = ?DICT:store(Subscriber, #entity{subscription = subscribed}, Entities)} end.remove_subscriber(Info, Subscriber) -> Entities = Info#nodeinfo.entities, case ?DICT:find(Subscriber, Entities) of {ok, #entity{affiliation = none}} -> Info#nodeinfo{ entities = ?DICT:erase(Subscriber, Entities)}; {ok, Entity} -> Info#nodeinfo{ entities = ?DICT:store(Subscriber, Entity#entity{subscription = none}, Entities)}; _ -> Info end.set_info_entities(Info, Entities) -> NewEntities = lists:foldl( fun({JID, Ent}, Es) -> case Ent of #entity{affiliation = none, subscription = none} -> ?DICT:erase(JID, Es); _ -> ?DICT:store(JID, Ent, Es) end end, Info#nodeinfo.entities, Entities), Info#nodeinfo{entities = NewEntities}. broadcast_publish_item(Host, Node, ItemID, Payload) -> case catch mnesia:dirty_read(pubsub_node, Node) of [#pubsub_node{info = Info}] -> ?DICT:fold( fun(JID, #entity{subscription = Subscription}, _) -> if (Subscription /= none) and (Subscription /= pending) -> ItemAttrs = case ItemID of "" -> []; _ -> [{"id", ItemID}] end, Stanza = {xmlelement, "message", [], [{xmlelement, "x", [{"xmlns", ?NS_PUBSUB_EVENT}], [{xmlelement, "items", [{"node", node_to_string(Node)}], [{xmlelement, "item", ItemAttrs, Payload}]}]}]}, ejabberd_router:route( ?MYJID, jlib:make_jid(JID), Stanza); true -> ok end end, ok, Info#nodeinfo.entities); _ -> false end.broadcast_retract_item(Host, Node, ItemID) -> case catch mnesia:dirty_read(pubsub_node, Node) of [#pubsub_node{info = Info}] -> ?DICT:fold( fun(JID, #entity{subscription = Subscription}, _) -> if (Subscription /= none) and (Subscription /= pending) -> ItemAttrs = case ItemID of "" -> []; _ -> [{"id", ItemID}] end, Stanza = {xmlelement, "message", [], [{xmlelement, "x", [{"xmlns", ?NS_PUBSUB_EVENT}], [{xmlelement, "items", [{"node", node_to_string(Node)}], [{xmlelement, "retract", ItemAttrs, []}]}]}]}, ejabberd_router:route( ?MYJID, jlib:make_jid(JID), Stanza); true -> ok end end, ok, Info#nodeinfo.entities); _ -> false end.broadcast_removed_node(Host, Removed) -> lists:foreach( fun({Node, Entities}) -> ?DICT:fold( fun(JID, #entity{subscription = Subscription}, _) -> if (Subscription /= none) and (Subscription /= pending) -> Stanza = {xmlelement, "message", [], [{xmlelement, "x", [{"xmlns", ?NS_PUBSUB_EVENT}], [{xmlelement, "delete", [{"node", node_to_string(Node)}], []}]}]}, ejabberd_router:route( ?MYJID, jlib:make_jid(JID), Stanza); true -> ok end end, ok, Entities) end, Removed).system_continue(Parent, _, State) -> loop(State, Parent).system_terminate(Reason, Parent, _, State) -> exit(Reason).system_code_change(State, _Mod, Ver, _Extra) -> {ok, State}.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -