@@ -1,4 +1,15 @@ +local sanitable = { + ['\xfe'] = '\xf0'; + ['\1'] = '\xf1'; + ['\2'] = '\xf2'; + ['\3'] = '\xf3'; + + ['\xf0'] = '\xfe'; + ['\xf1'] = '\1'; + ['\xf2'] = '\2'; + ['\xf3'] = '\3'; +} return { capitalize = function(str) return string.upper(string.sub(str, 1,1)) .. string.sub(str, 2) end; @@ -35,5 +46,31 @@ str = string.sub(str, 1, #str - 1) end return str end; + + meta_armor = function(str,mark_struct) + -- binary values stored in metadata need to be sanitized so + -- they don't contain values that will disrupt parsing of the + -- KV store, as minetest (stupidly) uses in-band signalling + local sanitized = string.gsub(str, '[\xfe\1\2\3]', function(char) + return '\xfe' .. sanitable[char] + end) + if sanitized ~= str and mark_struct then + -- use different type code to mark struct headers for + -- back-compat + return string.gsub(sanitized,'^\xfe\xf0\x99','\xfe\x98') + else return sanitized end + end; + meta_dearmor = function(str,cond) + local dearmor = function(s) + return string.gsub(s, '\xfe([\xf0\xf1\xf2\xf3])', function(char) + return sanitable[char] + end) + end + if cond then + if string.sub(str,1,2) == '\xfe\x98' then + return dearmor(string.gsub(str,'^\xfe\x98','\xfe\xf0\x99')) + else return str end + else return dearmor(str) end + end; }