From 29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6 Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Mon, 9 Feb 2015 19:44:12 +0200 Subject: proper escaping for back-end addresses --- aconf/persistence/backends/augeas.lua | 101 ++++++++++++++++------------------ aconf/persistence/backends/files.lua | 7 ++- aconf/persistence/backends/json.lua | 8 +-- aconf/persistence/defer.lua | 6 +- aconf/persistence/init.lua | 8 +-- 5 files changed, 63 insertions(+), 67 deletions(-) (limited to 'aconf/persistence') diff --git a/aconf/persistence/backends/augeas.lua b/aconf/persistence/backends/augeas.lua index ab73c08..aaf3ac0 100644 --- a/aconf/persistence/backends/augeas.lua +++ b/aconf/persistence/backends/augeas.lua @@ -1,11 +1,16 @@ --[[ -Copyright (c) 2012-2014 Kaarle Ritvanen +Copyright (c) 2012-2015 Kaarle Ritvanen See LICENSE file for license details --]] local topology = require('aconf.model.root').topology -local class = require('aconf.object').class -local pth = require('aconf.path') + +local object = require('aconf.object') +local class = object.class +local isinstance = object.isinstance + +local address = require('aconf.path.address') +local special = require('aconf.path.address.special') local tostr = require('aconf.persistence.util').tostring local util = require('aconf.util') @@ -13,9 +18,6 @@ local contains = util.contains local copy = util.copy -local stringy = require('stringy') - - local function array_join(tbl, value) local res = copy(tbl) table.insert(res, value) @@ -30,7 +32,7 @@ end local function basename(path) - local res, pred = path:match('^.*/([#%w._-]+)([^/]*)$') + local res, pred = path:match('^.*/([@#$%w._-]+)([^/]*)$') assert(res) assert(res ~= '#') assert(pred == '' or pred:match('^%[.+%]$')) @@ -39,19 +41,12 @@ end local function append_pred(path, pred) return path..'['..pred..']' end - -local function key_mode(mode) return mode and stringy.startswith(mode, '@') end - -local function tbl_mode(mode) return mode == '#' or key_mode(mode) end - -local function key(mode) - assert(key_mode(mode)) - return mode == '@' and '.' or mode:sub(2, -1) +local function append_key_pred(path, key, value) + return append_pred(path, key.." = '"..value.."'") end -local function append_key_pred(path, mode, value) - return append_pred(path, key(mode).." = '"..value.."'") -end +local function key(mode) return mode.key or '.' end + local function conv_path(path) @@ -63,21 +58,21 @@ local function conv_path(path) local keys = {} repeat - assert(mode ~= '&') local comp = path[1] if mode then - if mode == '#' then + if isinstance(mode, special.EnumKeys) then assert(type(comp) == 'number') res = append_pred(res, comp) - else + elseif isinstance(mode, special.ValueEquals) then assert(type(comp) == 'string' and comp:match('^[%w %_%-%.%#]+$')) - res = append_key_pred(res, mode, comp) - table.insert(keys, key(mode)) - end + local k = key(mode) + res = append_key_pred(res, k, comp) + table.insert(keys, k) + else assert(false) end mode = nil - elseif contains({'#', '&'}, comp) or key_mode(comp) then mode = comp + elseif isinstance(comp, special.SpecialMode) then mode = comp else res = res..'/'..comp @@ -87,7 +82,7 @@ local function conv_path(path) table.remove(path, 1) until #path == 0 - return res, mode, mode == '&' and {} or keys + return res, mode, isinstance(mode, special.Value) and {} or keys end @@ -110,16 +105,17 @@ function backend:get(path, top) local tpe = top and top.type local tbl = tpe == 'table' local leaf = not tbl and not mode - if mode == '&' then + if isinstance(mode, special.Value) then assert(not tbl) leaf = true end local matches = self.aug:match(apath..(not leaf and not mode and '/*' or '')) + local is_selector = isinstance(mode, special.Selector) - if #matches == 0 and not tbl_mode(mode) then return end + if #matches == 0 and not is_selector then return end - if tbl_mode(mode) and #path > 1 and not self:get( + if is_selector and #path > 1 and not self:get( array_without_last(array_without_last(path)), true ) then return @@ -128,7 +124,7 @@ function backend:get(path, top) if not tpe and not mode then if #matches > 1 then leaf = false - mode = '#' + mode = address.special.enum_keys else local children = self.aug:match(apath..'/*') if #children > 0 then @@ -153,10 +149,10 @@ function backend:get(path, top) name = basename(child) name = tonumber(name) or name if contains(keys, name) then name = nil end - elseif mode == '#' then name = i - else - name = self.aug:get(child..(mode == '@' and '' or '/'..key(mode))) - end + elseif isinstance(mode, special.EnumKeys) then name = i + elseif isinstance(mode, special.ValueEquals) then + name = self.aug:get(child..(mode.key and '/'..mode.key or '')) + else assert(false) end if name and self:get(array_join(path, name), true) then names[name] = true @@ -181,17 +177,17 @@ function backend:set(mods) local parent = array_without_last(path) local ppath, pmode = conv_path(parent) - if tbl_mode(pmode) then - gc[pth.join(table.unpack(array_without_last(parent)))] = false - end + if isinstance(pmode, special.Selector) then + gc[address.join(table.unpack(array_without_last(parent)))] = false - if pmode == '#' then - local count = #self.aug:match(ppath) - while count < name do - insert(parent, true) - count = count + 1 + if isinstance(pmode, special.EnumKeys) then + local count = #self.aug:match(ppath) + while count < name do + insert(parent, true) + count = count + 1 + end + return apath, keys end - return apath, keys end local matches = self.aug:match(apath) @@ -199,17 +195,16 @@ function backend:set(mods) if count > 0 and not new then return apath, keys end - if key_mode(pmode) then - apath = pmode == '@' and append_key_pred( - ppath, '@', '' - ) or append_pred(ppath, 'count('..key(pmode)..') = 0') + if isinstance(pmode, special.ValueEquals) then + apath = pmode.key and append_pred( + ppath, 'count('..pmode.key..') = 0' + ) or append_key_pred(ppath, '.', '') matches = self.aug:match(apath) assert(#matches < 2) apath = matches[1] or insert(parent, true) - local key = key(pmode) - self.aug:set(apath..'/'..key, name) + self.aug:set(apath..'/'..key(pmode), name) return apath, keys end @@ -244,15 +239,15 @@ function backend:set(mods) local apath, keys = insert(path) local is_table = type(value) == 'table' - if not (is_table or util.contains(keys, '.')) then + if not (is_table or contains(keys, '.')) then self.aug:set(apath, value ~= nil and tostr(value) or nil) end - util.setdefault(gc, pth.join(table.unpack(path)), true) + util.setdefault(gc, address.join(table.unpack(path)), true) end for path, _ in pairs(gc) do - local p = pth.split(path) + local p = address.split(path) while #p > 0 do local value = self:get(p) @@ -264,7 +259,7 @@ function backend:set(mods) break end - if gc[pth.join(table.unpack(p))] ~= false then + if gc[address.join(table.unpack(p))] ~= false then self.aug:rm(conv_path(p)) end p[#p] = nil diff --git a/aconf/persistence/backends/files.lua b/aconf/persistence/backends/files.lua index 1c78c80..427d8bb 100644 --- a/aconf/persistence/backends/files.lua +++ b/aconf/persistence/backends/files.lua @@ -1,10 +1,11 @@ --[[ -Copyright (c) 2012-2014 Kaarle Ritvanen +Copyright (c) 2012-2015 Kaarle Ritvanen See LICENSE file for license details --]] local topology = require('aconf.model.root').topology local pth = require('aconf.path') +local address = require('aconf.path.address') local util = require('aconf.persistence.util') local copy = require('aconf.util').copy @@ -29,7 +30,7 @@ local backend = require('aconf.object').class() function backend:init() self.cache = {} end function backend:get(path, top) - local name = pth.join('/', table.unpack(path)) + local name = address.join('/', table.unpack(path)) if not self.cache[name] then local t = posix.stat(name, 'type') @@ -69,7 +70,7 @@ end function backend:set(mods) for _, mod in pairs(mods) do local path, value = table.unpack(mod) - local name = pth.join('/', table.unpack(path)) + local name = address.join('/', table.unpack(path)) if value == nil then print('DEL', name) diff --git a/aconf/persistence/backends/json.lua b/aconf/persistence/backends/json.lua index bdf2715..5a13955 100644 --- a/aconf/persistence/backends/json.lua +++ b/aconf/persistence/backends/json.lua @@ -1,9 +1,9 @@ --[[ -Copyright (c) 2012-2014 Kaarle Ritvanen +Copyright (c) 2012-2015 Kaarle Ritvanen See LICENSE file for license details --]] -local pth = require('aconf.path') +local address = require('aconf.path.address') local Cache = require('aconf.persistence.backends.volatile') local util = require('aconf.persistence.util') local copy = require('aconf.util').copy @@ -26,7 +26,7 @@ function backend:split_path(path) local res while #fpath > 0 do - local fp = pth.join('/', table.unpack(fpath)) + local fp = address.join('/', table.unpack(fpath)) if self.cache[fp] then return fp, jpath end table.insert(jpath, 1, fpath[#fpath]) table.remove(fpath) @@ -35,7 +35,7 @@ function backend:split_path(path) fpath = '/' while true do - fpath = pth.join(fpath, jpath[1]) + fpath = address.join(fpath, jpath[1]) table.remove(jpath, 1) local t = posix.stat(fpath, 'type') diff --git a/aconf/persistence/defer.lua b/aconf/persistence/defer.lua index cfa8e8b..d7f33d8 100644 --- a/aconf/persistence/defer.lua +++ b/aconf/persistence/defer.lua @@ -1,12 +1,12 @@ --[[ -Copyright (c) 2012-2014 Kaarle Ritvanen +Copyright (c) 2012-2015 Kaarle Ritvanen See LICENSE file for license details --]] local object = require('aconf.object') local super = object.super -local pth = require('aconf.path') +local address = require('aconf.path.address') local DeferringCommitter = object.class( @@ -31,7 +31,7 @@ function DeferringCommitter:_set_multiple(mods) local path, value = table.unpack(mod) while path > '/' do if self.defer_paths[path] then return end - path = pth.parent(path) + path = address.parent(path) end end diff --git a/aconf/persistence/init.lua b/aconf/persistence/init.lua index d95da2d..8056c16 100644 --- a/aconf/persistence/init.lua +++ b/aconf/persistence/init.lua @@ -1,12 +1,12 @@ --[[ -Copyright (c) 2012-2014 Kaarle Ritvanen +Copyright (c) 2012-2015 Kaarle Ritvanen See LICENSE file for license details --]] local loadmods = require('aconf.loader') local topology = require('aconf.model.root').topology local object = require('aconf.object') -local pth = require('aconf.path') +local address = require('aconf.path.address') local util = require('aconf.util') local contains = util.contains @@ -34,7 +34,7 @@ function DataStore:trigger(phase, path, func) end function DataStore:split_path(path) - local comps = pth.split(path) + local comps = address.split(path) local backend = self.backends[comps[1]] assert(backend) table.remove(comps, 1) @@ -93,7 +93,7 @@ function DataStore:_set_multiple(mods) local tp = path while not trigger[tp] do trigger[tp] = true - tp = pth.parent(tp) + tp = address.parent(tp) end local backend, comps = self:split_path(path) -- cgit v1.2.3