view mod_compression_unsafe/mod_compression_unsafe.lua @ 6214:cc5c0f1dc89b

mod_muc_anonymize_moderation_actions: Fix mentioning Virtualhost for MUC, Compatibility section and License. diff --git a/mod_muc_anonymize_moderation_actions/README.md b/mod_muc_anonymize_moderation_actions/README.md --- a/mod_muc_anonymize_moderation_actions/README.md +++ b/mod_muc_anonymize_moderation_actions/README.md @@ -1,8 +1,10 @@ -<!-- -SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> -SPDX-License-Identifier: AGPL-3.0-only ---> -# mod_muc_anonymize_moderation_actions +--- +labels: +- 'Stage-Alpha' +summary: Anonymize moderator actions for participants +--- + +## Introduction This modules allows to anonymize affiliation and role changes in MUC rooms. @@ -11,13 +13,10 @@ When the feature is enabled, when a mode This is particularly usefull to prevent some revenge when a moderator bans someone. -This module is under AGPL-3.0 license. - -It was tested on Prosody 0.12.x. ## Configuration -Just enable the module on your MUC VirtualHost. +Just enable the module on your MUC Component. The feature will be accessible throught the room configuration form. You can tweak the position of the settings in the MUC configuration form using `anonymize_moderation_actions_form_position`. @@ -26,7 +25,20 @@ This value will be passed as priority fo By default, the field will be between muc#roomconfig_changesubject and muc#roomconfig_moderatedroom (default value is `78`). ``` lua -VirtualHost "muc.example.com" +Component "muc.example.com" "muc" modules_enabled = { "muc_anonymize_moderation_actions" } anonymize_moderation_actions_form_position = 96 ``` + +## Compatibility + + ------ ---------------------- + trunk Works as of 25-05-12 + 0.13 Works + 0.12 Works + ------ ---------------------- + +### License + +SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/> +SPDX-License-Identifier: AGPL-3.0-only
author Menel <menel@snikket.de>
date Mon, 12 May 2025 10:42:26 +0200
parents 226693a22fc9
children
line wrap: on
line source

-- Prosody IM
-- Copyright (C) 2009-2012 Tobias Markmann
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--

local st = require "util.stanza";
local zlib = require "zlib";
local pcall = pcall;
local tostring = tostring;

local xmlns_compression_feature = "http://jabber.org/features/compress"
local xmlns_compression_protocol = "http://jabber.org/protocol/compress"
local xmlns_stream = "http://etherx.jabber.org/streams";
local compression_stream_feature = st.stanza("compression", {xmlns=xmlns_compression_feature}):tag("method"):text("zlib"):up();
local add_filter = require "util.filters".add_filter;

local compression_level = module:get_option_number("compression_level", 7);

if not compression_level or compression_level < 1 or compression_level > 9 then
	module:log("warn", "Invalid compression level in config: %s", tostring(compression_level));
	module:log("warn", "Module loading aborted. Compression won't be available.");
	return;
end

module:hook("stream-features", function(event)
	local origin, features = event.origin, event.features;
	if not origin.compressed and (origin.type == "c2s" or origin.type == "c2s_unbound") then
		features:add_child(compression_stream_feature);
	end
end);

module:hook("s2s-stream-features", function(event)
	local origin, features = event.origin, event.features;
	if not origin.compressed and origin.type == "s2sin" then
		features:add_child(compression_stream_feature);
	end
end);

-- Hook to activate compression if remote server supports it.
module:hook_stanza(xmlns_stream, "features",
		function (session, stanza)
			if not session.compressed and session.type == "s2sout" then
				-- does remote server support compression?
				local comp_st = stanza:get_child("compression", xmlns_compression_feature);
				if comp_st then
					-- do we support the mechanism
					for a in comp_st:childtags("method") do
						local algorithm = a:get_text();
						if algorithm == "zlib" then
							session.sends2s(st.stanza("compress", {xmlns=xmlns_compression_protocol}):tag("method"):text("zlib"))
							session.log("debug", "Enabled compression using zlib.")
							return true;
						end
					end
					session.log("debug", "Remote server supports no compression algorithm we support.")
				end
			end
		end
, 250);


-- returns either nil or a fully functional ready to use inflate stream
local function get_deflate_stream(session)
	local status, deflate_stream = pcall(zlib.deflate, compression_level);
	if status == false then
		local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed");
		(session.sends2s or session.send)(error_st);
		session.log("error", "Failed to create zlib.deflate filter.");
		module:log("error", "%s", tostring(deflate_stream));
		return
	end
	return deflate_stream
end

-- returns either nil or a fully functional ready to use inflate stream
local function get_inflate_stream(session)
	local status, inflate_stream = pcall(zlib.inflate);
	if status == false then
		local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed");
		(session.sends2s or session.send)(error_st);
		session.log("error", "Failed to create zlib.inflate filter.");
		module:log("error", "%s", tostring(inflate_stream));
		return
	end
	return inflate_stream
end

-- setup compression for a stream
local function setup_compression(session, deflate_stream)
	add_filter(session, "bytes/out", function(t)
		local status, compressed, eof = pcall(deflate_stream, tostring(t), 'sync');
		if status == false then
			module:log("warn", "%s", tostring(compressed));
			session:close({
				condition = "undefined-condition";
				text = compressed;
				extra = st.stanza("failure", {xmlns="http://jabber.org/protocol/compress"}):tag("processing-failed");
			});
			return;
		end
		return compressed;
	end);
end

-- setup decompression for a stream
local function setup_decompression(session, inflate_stream)
	add_filter(session, "bytes/in", function(data)
		local status, decompressed, eof = pcall(inflate_stream, data);
		if status == false then
			module:log("warn", "%s", tostring(decompressed));
			session:close({
				condition = "undefined-condition";
				text = decompressed;
				extra = st.stanza("failure", {xmlns="http://jabber.org/protocol/compress"}):tag("processing-failed");
			});
			return;
		end
		return decompressed;
	end);
end

module:hook("stanza/http://jabber.org/protocol/compress:compressed", function(event)
	local session = event.origin;
	
	if session.type == "s2sout" then
		session.log("debug", "Activating compression...")
		-- create deflate and inflate streams
		local deflate_stream = get_deflate_stream(session);
		if not deflate_stream then return true; end
		
		local inflate_stream = get_inflate_stream(session);
		if not inflate_stream then return true; end
		
		-- setup compression for session.w
		setup_compression(session, deflate_stream);
			
		-- setup decompression for session.data
		setup_decompression(session, inflate_stream);
		session:reset_stream();
		session:open_stream(session.from_host, session.to_host);
		session.compressed = true;
		return true;
	end
end);

module:hook("stanza/http://jabber.org/protocol/compress:failure", function(event)
	local err = event.stanza:get_child();
	(event.origin.log or module._log)("warn", "Compression setup failed (%s)", err and err.name or "unknown reason");
	return true;
end);

module:hook("stanza/http://jabber.org/protocol/compress:compress", function(event)
	local session, stanza = event.origin, event.stanza;

	if session.type == "c2s" or session.type == "s2sin" then
		-- fail if we are already compressed
		if session.compressed then
			local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed");
			(session.sends2s or session.send)(error_st);
			session.log("debug", "Client tried to establish another compression layer.");
			return true;
		end
		
		-- checking if the compression method is supported
		local method = stanza:get_child_text("method");
		if method == "zlib" then
			session.log("debug", "zlib compression enabled.");
			
			-- create deflate and inflate streams
			local deflate_stream = get_deflate_stream(session);
			if not deflate_stream then return true; end
			
			local inflate_stream = get_inflate_stream(session);
			if not inflate_stream then return true; end
			
			(session.sends2s or session.send)(st.stanza("compressed", {xmlns=xmlns_compression_protocol}));
			session:reset_stream();
			
			-- setup compression for session.w
			setup_compression(session, deflate_stream);
				
			-- setup decompression for session.data
			setup_decompression(session, inflate_stream);
			
			session.compressed = true;
		elseif method then
			session.log("debug", "%s compression selected, but we don't support it.", tostring(method));
			local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("unsupported-method");
			(session.sends2s or session.send)(error_st);
		else
			(session.sends2s or session.send)(st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"));
		end
		return true;
	end
end);