Software /
code /
prosody
File
util/http.lua @ 13571:ca041359c045
net.server_epoll: Don't try to flush buffer on closed connections
Attempt to fix a bug where connections are somehow closed twice, leading
to bad things happening elsewhere.
With LuaSec, closed connections are generally already too closed to
write anything to anyway since it does not support unidirectional
shutdown.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 19 Nov 2024 00:41:02 +0100 |
parent | 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 --- Parse the RFC 7239 Forwarded header into array of key-value pairs. local function parse_forwarded(forwarded) if type(forwarded) ~= "string" then return nil; end local fwd = {}; -- array local cur = {}; -- map, to which we add the next key-value pair for key, quoted, value, delim in forwarded:gmatch("(%w+)%s*=%s*(\"?)([^,;\"]+)%2%s*(.?)") do -- FIXME quoted quotes like "foo\"bar" -- unlikely when only dealing with IP addresses if quoted == '"' then value = value:gsub("\\(.)", "%1"); end cur[key:lower()] = value; if delim == "" or delim == "," then t_insert(fwd, cur) if delim == "" then -- end of the string break; end cur = {}; elseif delim ~= ";" then -- misparsed return false; end end return fwd; end return { urlencode = urlencode, urldecode = urldecode; formencode = formencode, formdecode = formdecode; contains_token = contains_token; normalize_path = normalize_path; parse_forwarded = parse_forwarded; };