Software / code / prosody
File
util/hashring.lua @ 13854:0b01f40df0f9 13.0
mod_http_file_share: Add media-src 'self' to Content-Security-Policy header
This allows certain media files to be loaded when navigated to directly in a
web browser.
Note that in some browsers (Chrome), the media gets transformed
internally into a HTML page with some basic styles, but these are blocked due
to our default-src policy of 'none' Although this could be unblocked with
style-src unsafe-inline, it is not our plan to fix this, because this would
have negative security implications.
The reason for our CSP is to prevent the file share service from being used to
host malicious HTML/CSS/JS. Yes, CSS can be malicious.
Our file share service is for uploading and downloading files, it is not a
substitute for website/content hosting.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 18 Apr 2025 12:25:06 +0100 |
| parent | 12975:d10957394a3c |
line wrap: on
line source
local it = require "prosody.util.iterators"; local function generate_ring(nodes, num_replicas, hash) local new_ring = {}; for _, node_name in ipairs(nodes) do for replica = 1, num_replicas do local replica_hash = hash(node_name..":"..replica); new_ring[replica_hash] = node_name; table.insert(new_ring, replica_hash); end end table.sort(new_ring); return new_ring; end local hashring_methods = {}; local hashring_mt = { __index = function (self, k) -- Automatically build self.ring if it's missing if k == "ring" then local ring = generate_ring(self.nodes, self.num_replicas, self.hash); rawset(self, "ring", ring); return ring; end return rawget(hashring_methods, k); end }; local function new(num_replicas, hash_function) return setmetatable({ nodes = {}, num_replicas = num_replicas, hash = hash_function }, hashring_mt); end; function hashring_methods:add_node(name, value) self.ring = nil; self.nodes[name] = value == nil and true or value; table.insert(self.nodes, name); return true; end function hashring_methods:add_nodes(nodes) self.ring = nil; local iter = pairs; if nodes[1] then -- simple array? iter = it.values; end for node_name, node_value in iter(nodes) do if self.nodes[node_name] == nil then self.nodes[node_name] = node_value == nil and true or node_value; table.insert(self.nodes, node_name); end end return true; end function hashring_methods:remove_node(node_name) self.ring = nil; if self.nodes[node_name] ~= nil then for i, stored_node_name in ipairs(self.nodes) do if node_name == stored_node_name then self.nodes[node_name] = nil; table.remove(self.nodes, i); return true; end end end return false; end function hashring_methods:remove_nodes(nodes) self.ring = nil; for _, node_name in ipairs(nodes) do self:remove_node(node_name); end end function hashring_methods:clone() local clone_hashring = new(self.num_replicas, self.hash); for node_name, node_value in pairs(self.nodes) do clone_hashring.nodes[node_name] = node_value; end clone_hashring.ring = nil; return clone_hashring; end function hashring_methods:get_node(key) local node; local key_hash = self.hash(key); for _, replica_hash in ipairs(self.ring) do if key_hash < replica_hash then node = self.ring[replica_hash]; break; end end if not node then node = self.ring[self.ring[1]]; end return node, self.nodes[node]; end return { new = new; }