Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

mod_muc_domain_mapper.lua 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. -- Maps MUC JIDs like room1@muc.foo.example.com to JIDs like [foo]room1@muc.example.com
  2. -- Must be loaded on the client host in Prosody
  3. -- It is recommended to set muc_mapper_domain_base to the main domain being served (example.com)
  4. local jid = require "util.jid";
  5. local filters = require "util.filters";
  6. local muc_domain_prefix = module:get_option_string("muc_mapper_domain_prefix", "conference");
  7. local muc_domain_base = module:get_option_string("muc_mapper_domain_base");
  8. if not muc_domain_base then
  9. module:log("warn", "No 'muc_mapper_domain_base' option set, disabling muc_mapper plugin inactive");
  10. return
  11. end
  12. -- The "real" MUC domain that we are proxying to
  13. local muc_domain = module:get_option_string("muc_mapper_domain", muc_domain_prefix.."."..muc_domain_base);
  14. local escaped_muc_domain_base = muc_domain_base:gsub("%p", "%%%1");
  15. local escaped_muc_domain_prefix = muc_domain_prefix:gsub("%p", "%%%1");
  16. -- The pattern used to extract the target subdomain (e.g. extract 'foo' from 'foo.muc.example.com')
  17. local target_subdomain_pattern = "^"..escaped_muc_domain_prefix..".([^%.]+)%."..escaped_muc_domain_base;
  18. -- table to store all incoming iqs without roomname in it, like discoinfo to the muc compoent
  19. local roomless_iqs = {};
  20. if not muc_domain then
  21. module:log("warn", "No 'muc_mapper_domain' option set, disabling muc_mapper plugin inactive");
  22. return
  23. end
  24. -- Utility function to check and convert a room JID from virtual room1@muc.foo.example.com to real [foo]room1@muc.example.com
  25. local function match_rewrite_to_jid(room_jid, stanza)
  26. local node, host, resource = jid.split(room_jid);
  27. local target_subdomain = host and host:match(target_subdomain_pattern);
  28. if not target_subdomain then
  29. module:log("debug", "No need to rewrite out 'to' %s", room_jid);
  30. return room_jid;
  31. end
  32. -- Ok, rewrite room_jid address to new format
  33. local new_node, new_host, new_resource;
  34. if node then
  35. new_node, new_host, new_resource = "["..target_subdomain.."]"..node, muc_domain, resource;
  36. else
  37. module:log("debug", "No room name provided so rewriting only host 'to' %s", room_jid);
  38. new_host, new_resource = muc_domain, resource;
  39. if (stanza.attr and stanza.attr.id) then
  40. roomless_iqs[stanza.attr.id] = stanza.attr.to;
  41. end
  42. end
  43. room_jid = jid.join(new_node, new_host, new_resource);
  44. module:log("debug", "Rewrote to %s", room_jid);
  45. return room_jid
  46. end
  47. -- Utility function to check and convert a room JID from real [foo]room1@muc.example.com to virtual room1@muc.foo.example.com
  48. local function match_rewrite_from_jid(room_jid, stanza)
  49. local node, host, resource = jid.split(room_jid);
  50. if host ~= muc_domain or not node then
  51. module:log("debug", "No need to rewrite %s (not from the MUC host) %s, %s", room_jid, stanza.attr.id, roomless_iqs[stanza.attr.id]);
  52. if (stanza.attr and stanza.attr.id and roomless_iqs[stanza.attr.id]) then
  53. local result = roomless_iqs[stanza.attr.id];
  54. roomless_iqs[stanza.attr.id] = nil;
  55. return result;
  56. end
  57. return room_jid;
  58. end
  59. local target_subdomain, target_node = node:match("^%[([^%]]+)%](.+)$");
  60. if not (target_node and target_subdomain) then
  61. module:log("debug", "Not rewriting... unexpected node format: %s", node);
  62. return room_jid;
  63. end
  64. -- Ok, rewrite room_jid address to pretty format
  65. local new_node, new_host, new_resource = target_node, muc_domain_prefix..".".. target_subdomain.."."..muc_domain_base, resource;
  66. room_jid = jid.join(new_node, new_host, new_resource);
  67. module:log("debug", "Rewrote to %s", room_jid);
  68. return room_jid
  69. end
  70. -- We must filter stanzas in order to hook in to all incoming and outgoing messaging which skips the stanza routers
  71. function filter_stanza(stanza)
  72. if stanza.name == "message" or stanza.name == "iq" or stanza.name == "presence" then
  73. module:log("debug", "Filtering stanza type %s to %s from %s",stanza.name,stanza.attr.to,stanza.attr.from);
  74. if stanza.name == "iq" then
  75. local conf = stanza:get_child('conference')
  76. if conf then
  77. module:log("debug", "Filtering stanza conference %s to %s from %s",conf.attr.room,stanza.attr.to,stanza.attr.from);
  78. conf.attr.room = match_rewrite_to_jid(conf.attr.room, stanza)
  79. end
  80. end
  81. if stanza.attr.to then
  82. stanza.attr.to = match_rewrite_to_jid(stanza.attr.to, stanza)
  83. end
  84. if stanza.attr.from then
  85. stanza.attr.from = match_rewrite_from_jid(stanza.attr.from, stanza)
  86. end
  87. end
  88. return stanza;
  89. end
  90. function filter_session(session)
  91. module:log("warn", "Session filters applied");
  92. -- filters.add_filter(session, "stanzas/in", filter_stanza_in);
  93. filters.add_filter(session, "stanzas/out", filter_stanza);
  94. end
  95. function module.load()
  96. if module.reloading then
  97. module:log("debug", "Reloading MUC mapper!");
  98. else
  99. module:log("debug", "First load of MUC mapper!");
  100. end
  101. filters.add_filter_hook(filter_session);
  102. end
  103. function module.unload()
  104. filters.remove_filter_hook(filter_session);
  105. end
  106. local function outgoing_stanza_rewriter(event)
  107. local stanza = event.stanza;
  108. if stanza.attr.to then
  109. stanza.attr.to = match_rewrite_to_jid(stanza.attr.to, stanza)
  110. end
  111. end
  112. local function incoming_stanza_rewriter(event)
  113. local stanza = event.stanza;
  114. if stanza.attr.from then
  115. stanza.attr.from = match_rewrite_from_jid(stanza.attr.from, stanza)
  116. end
  117. end
  118. -- The stanza rewriters helper functions are attached for all stanza router hooks
  119. local function hook_all_stanzas(handler, host_module, event_prefix)
  120. for _, stanza_type in ipairs({ "message", "presence", "iq" }) do
  121. for _, jid_type in ipairs({ "host", "bare", "full" }) do
  122. host_module:hook((event_prefix or "")..stanza_type.."/"..jid_type, handler);
  123. end
  124. end
  125. end
  126. function add_host(host)
  127. module:log("info", "Loading mod_muc_domain_mapper for host %s!", host);
  128. local host_module = module:context(host);
  129. hook_all_stanzas(incoming_stanza_rewriter, host_module);
  130. hook_all_stanzas(outgoing_stanza_rewriter, host_module, "pre-");
  131. end
  132. prosody.events.add_handler("host-activated", add_host);
  133. for host in pairs(prosody.hosts) do
  134. add_host(host);
  135. end