-- Prosody IM
--- Copyright (C) 2008-2009 Matthew Wild
--- Copyright (C) 2008-2009 Waqas Hussain
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
local t_insert = table.insert;
local append = require "util.serialization".append;
local path_separator = "/"; if os.getenv("WINDIR") then path_separator = "\\" end
+local lfs = require "lfs";
+local prosody = prosody;
local raw_mkdir;
if prosody.platform == "posix" then
raw_mkdir = require "util.pposix".mkdir; -- Doesn't trample on umask
else
- raw_mkdir = require "lfs".mkdir;
+ raw_mkdir = lfs.mkdir;
end
module "datamanager"
return path;
end
-local data_path = "data";
+local data_path = (prosody and prosody.paths and prosody.paths.data) or ".";
local callbacks = {};
------- API -------------
-local _set_data_path;
function set_data_path(path)
- if _set_data_path then return _set_data_path(path); end
log("debug", "Setting data path to: %s", path);
data_path = path;
end
return username, host, datastore, data;
end
-local _add_callback;
function add_callback(func)
- if _add_callback then return _add_callback(func); end
if not callbacks[func] then -- Would you really want to set the same callback more than once?
callbacks[func] = true;
callbacks[#callbacks+1] = func;
return true;
end
end
-local _remove_callback;
function remove_callback(func)
- if _remove_callback then return _remove_callback(func); end
if callbacks[func] then
for i, f in ipairs(callbacks) do
if f == func then
end
end
-local _getpath;
function getpath(username, host, datastore, ext, create)
- if _getpath then return _getpath(username, host, datastore, ext, create); end
ext = ext or "dat";
host = (host and encode(host)) or "_global";
username = username and encode(username);
end
end
-local _load;
function load(username, host, datastore)
- if _load then return _load(username, host, datastore); end
local data, ret = loadfile(getpath(username, host, datastore));
if not data then
- log("debug", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return nil;
+ local mode = lfs.attributes(getpath(username, host, datastore), "mode");
+ if not mode then
+ log("debug", "Assuming empty "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ return nil;
+ else -- file exists, but can't be read
+ -- TODO more detailed error checking and logging?
+ log("error", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ return nil, "Error reading storage";
+ end
end
setfenv(data, {});
local success, ret = pcall(data);
if not success then
log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return nil;
+ return nil, "Error reading storage";
end
return ret;
end
-local _store;
function store(username, host, datastore, data)
- if _store then return _store(username, host, datastore, data); end
if not data then
data = {};
end
local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+");
if not f then
log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return;
+ return nil, "Error saving to storage";
end
f:write("return ");
append(f, data);
return true;
end
-local _list_append;
function list_append(username, host, datastore, data)
- if _list_append then return _list_append(username, host, datastore, data); end
if not data then return; end
if callback(username, host, datastore) == false then return true; end
-- save the datastore
return true;
end
-local _list_store;
function list_store(username, host, datastore, data)
- if _list_store then return _list_store(username, host, datastore, data); end
if not data then
data = {};
end
return true;
end
-local _list_load;
function list_load(username, host, datastore)
- if _list_load then return _list_load(username, host, datastore); end
local data, ret = loadfile(getpath(username, host, datastore, "list"));
if not data then
- log("debug", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return nil;
+ local mode = lfs.attributes(getpath(username, host, datastore, "list"), "mode");
+ if not mode then
+ log("debug", "Assuming empty "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ return nil;
+ else -- file exists, but can't be read
+ -- TODO more detailed error checking and logging?
+ log("error", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ return nil, "Error reading storage";
+ end
end
local items = {};
setfenv(data, {item = function(i) t_insert(items, i); end});
local success, ret = pcall(data);
if not success then
log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return nil;
+ return nil, "Error reading storage";
end
return items;
end
-function set(t)
- _set_data_path = t.set_data_path;
- _add_callback = t.add_callback;
- _remove_callback = t.remove_callback;
- _getpath = t.getpath;
- _load = t.load;
- _store = t.store;
- _list_append = t.list_append;
- _list_store = t.list_store;
- _list_load = t.list_load;
-end
-function get()
- return {
- set_data_path = _set_data_path;
- add_callback = _add_callback;
- remove_callback = _remove_callback;
- getpath = _getpath;
- load = _load;
- store = _store;
- list_append = _list_append;
- list_store = _list_store;
- list_load = _list_load;
- };
-end
-
return _M;