+local type_map = {
+ keyval = "dat";
+ list = "list";
+}
+
+function users(host, store, typ)
+ typ = type_map[typ or "keyval"];
+ local store_dir = format("%s/%s/%s", data_path, encode(host), store);
+
+ local mode, err = lfs.attributes(store_dir, "mode");
+ if not mode then
+ return function() log("debug", err or (store_dir .. " does not exist")) end
+ end
+ local next, state = lfs.dir(store_dir);
+ return function(state)
+ for node in next, state do
+ local file, ext = node:match("^(.*)%.([dalist]+)$");
+ if file and ext == typ then
+ return decode(file);
+ end
+ end
+ end, state;
+end
+
+function stores(username, host, typ)
+ typ = type_map[typ or "keyval"];
+ local store_dir = format("%s/%s/", data_path, encode(host));
+
+ local mode, err = lfs.attributes(store_dir, "mode");
+ if not mode then
+ return function() log("debug", err or (store_dir .. " does not exist")) end
+ end
+ local next, state = lfs.dir(store_dir);
+ return function(state)
+ for node in next, state do
+ if not node:match"^%." then
+ if username == true then
+ if lfs.attributes(store_dir..node, "mode") == "directory" then
+ return decode(node);
+ end
+ elseif username then
+ local store = decode(node)
+ if lfs.attributes(getpath(username, host, store, typ), "mode") then
+ return store;
+ end
+ elseif lfs.attributes(node, "mode") == "file" then
+ local file, ext = node:match("^(.*)%.([dalist]+)$");
+ if ext == typ then
+ return decode(file)
+ end
+ end
+ end
+ end
+ end, state;
+end
+
+local function do_remove(path)
+ local ok, err = os_remove(path);
+ if not ok and lfs.attributes(path, "mode") then
+ return ok, err;
+ end
+ return true
+end
+
+function purge(username, host)
+ local host_dir = format("%s/%s/", data_path, encode(host));
+ local errs = {};
+ for file in lfs.dir(host_dir) do
+ if lfs.attributes(host_dir..file, "mode") == "directory" then
+ local store = decode(file);
+ local ok, err = do_remove(getpath(username, host, store));
+ if not ok then errs[#errs+1] = err; end
+
+ local ok, err = do_remove(getpath(username, host, store, "list"));
+ if not ok then errs[#errs+1] = err; end
+ end
+ end
+ return #errs == 0, t_concat(errs, ", ");
+end
+
+_M.path_decode = decode;
+_M.path_encode = encode;