File

util/http.lua @ 11516:83822be7704d

util.xmppstream: Send <?xml?> declaration in same call as stream open If network_settings.opportunistic_writes is enabled then this would previously have resulted in two socket writes, and possibly two packets being sent. This caused some issues in older versions of Gajim, which apparently expected the stream opening in the first packet, and thus it could not connect. With this change and opportunistic_writes enabled, the first packet should contain both the xml declaration and the stream open tag. Without opportunistic_writes, there should be no observable change. Tested with Gajim 1.1.2 (on same machine). Unsure if loopback behaves differently than the network here.
author Kim Alvefur <zash@zash.se>
date Wed, 14 Apr 2021 15:21:13 +0200
parent 9785:ff88b03c343f
child 13124:f15e23840780
line wrap: on
line source

-- Prosody IM
-- Copyright (C) 2013 Florian Zeitz
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--

local format, char = string.format, string.char;
local pairs, ipairs = pairs, ipairs;
local t_insert, t_concat = table.insert, table.concat;

local url_codes = {};
for i = 0, 255 do
	local c = char(i);
	local u = format("%%%02x", i);
	url_codes[c] = u;
	url_codes[u] = c;
	url_codes[u:upper()] = c;
end
local function urlencode(s)
	return s and (s:gsub("[^a-zA-Z0-9.~_-]", url_codes));
end
local function urldecode(s)
	return s and (s:gsub("%%%x%x", url_codes));
end

local function _formencodepart(s)
	return s and (urlencode(s):gsub("%%20", "+"));
end

local function formencode(form)
	local result = {};
	if form[1] then -- Array of ordered { name, value }
		for _, field in ipairs(form) do
			t_insert(result, _formencodepart(field.name).."=".._formencodepart(field.value));
		end
	else -- Unordered map of name -> value
		for name, value in pairs(form) do
			t_insert(result, _formencodepart(name).."=".._formencodepart(value));
		end
	end
	return t_concat(result, "&");
end

local function formdecode(s)
	if not s:match("=") then return urldecode(s); end
	local r = {};
	for k, v in s:gmatch("([^=&]*)=([^&]*)") do
		k, v = k:gsub("%+", "%%20"), v:gsub("%+", "%%20");
		k, v = urldecode(k), urldecode(v);
		t_insert(r, { name = k, value = v });
		r[k] = v;
	end
	return r;
end

local function contains_token(field, token)
	field = ","..field:gsub("[ \t]", ""):lower()..",";
	return field:find(","..token:lower()..",", 1, true) ~= nil;
end

local function normalize_path(path, is_dir)
	if is_dir then
		if path:sub(-1,-1) ~= "/" then path = path.."/"; end
	else
		if path:sub(-1,-1) == "/" then path = path:sub(1, -2); end
	end
	if path:sub(1,1) ~= "/" then path = "/"..path; end
	return path;
end

return {
	urlencode = urlencode, urldecode = urldecode;
	formencode = formencode, formdecode = formdecode;
	contains_token = contains_token;
	normalize_path = normalize_path;
};