Software /
code /
prosody
File
util/xml.lua @ 11056:0b0a42542456
util.jid: Fix special escaping of '\' per XEP-0106
From XEP-0106 §2. Requirements:
> in certain circumstances, the escaping character itself ("\") might
> also be escaped
Later in §4.2 Address Transformation Algorithm it is stated that the
backslash would only be escaped if it forms an escape sequence. Thus
'\foo' is unaltered but '\20' must be escaped into '\5c20'.
Thanks to lovetox and jonas’ for brining up.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 28 Aug 2020 18:44:02 +0200 |
parent | 8555:4f0f5b49bb03 |
child | 11127:1d9cd1abc660 |
child | 12181:783056b4e448 |
line wrap: on
line source
local st = require "util.stanza"; local lxp = require "lxp"; local t_insert = table.insert; local t_remove = table.remove; local _ENV = nil; -- luacheck: std none local parse_xml = (function() local ns_prefixes = { ["http://www.w3.org/XML/1998/namespace"] = "xml"; }; local ns_separator = "\1"; local ns_pattern = "^([^"..ns_separator.."]*)"..ns_separator.."?(.*)$"; return function(xml) --luacheck: ignore 212/self local handler = {}; local stanza = st.stanza("root"); local namespaces = {}; local prefixes = {}; function handler:StartNamespaceDecl(prefix, url) if prefix ~= nil then t_insert(namespaces, url); t_insert(prefixes, prefix); end end function handler:EndNamespaceDecl(prefix) if prefix ~= nil then -- we depend on each StartNamespaceDecl having a paired EndNamespaceDecl t_remove(namespaces); t_remove(prefixes); end end function handler:StartElement(tagname, attr) local curr_ns,name = tagname:match(ns_pattern); if name == "" then curr_ns, name = "", curr_ns; end if curr_ns ~= "" then attr.xmlns = curr_ns; end for i=1,#attr do local k = attr[i]; attr[i] = nil; local ns, nm = k:match(ns_pattern); if nm ~= "" then ns = ns_prefixes[ns]; if ns then attr[ns..":"..nm] = attr[k]; attr[k] = nil; end end end local n = {} for i=1,#namespaces do n[prefixes[i]] = namespaces[i]; end stanza:tag(name, attr, n); end function handler:CharacterData(data) stanza:text(data); end function handler:EndElement() stanza:up(); end local parser = lxp.new(handler, "\1"); local ok, err, line, col = parser:parse(xml); if ok then ok, err, line, col = parser:parse(); end --parser:close(); if ok then return stanza.tags[1]; else return ok, err.." (line "..line..", col "..col..")"; end end; end)(); return { parse = parse_xml; };