diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2015-02-09 19:44:12 +0200 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2015-02-12 16:32:41 +0200 |
commit | 29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6 (patch) | |
tree | a8ad7d5343c41950ff9c8f96a55f41a80271f72a /aconf/persistence/backends/augeas.lua | |
parent | 07a0eb180872401b271de40190603df8f3ab3db2 (diff) | |
download | aconf-29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6.tar.bz2 aconf-29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6.tar.xz |
proper escaping for back-end addresses
Diffstat (limited to 'aconf/persistence/backends/augeas.lua')
-rw-r--r-- | aconf/persistence/backends/augeas.lua | 101 |
1 files changed, 48 insertions, 53 deletions
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 |