----------------------------------------------------------------------------- -- Xavante webDAV file repository -- Author: Javier Guerra -- Copyright (c) 2005 Javier Guerra ----------------------------------------------------------------------------- require "lfs" require "xavante.mime" require "socket.url" module (arg and arg[1]) local source_mt = { __index = {} } local source = source_mt.__index local resource_mt = { __index = {} } local resource = resource_mt.__index function source:getRoot () return self.rootDir end function source:getResource (rootUrl, path) local diskpath = self.rootDir .. path local attr = lfs.attributes (diskpath) if not attr then return end local _,_,pfx = string.find (rootUrl, "^(.*/)[^/]-$") if attr.mode == "directory" and string.sub (path, -1) ~= "/" then path = path .."/" end return setmetatable ({ source = self, path = path, diskpath = diskpath, attr = attr, pfx = pfx }, resource_mt) end function source:createResource (rootUrl, path) local diskpath = self.rootDir .. path local attr = lfs.attributes (diskpath) if not attr then io.open (diskpath, "w"):close () attr = lfs.attributes (diskpath) end local _,_,pfx = string.find (rootUrl, "^(.*/)[^/]-$") return setmetatable ({ source = self, path = path, diskpath = diskpath, attr = attr, pfx = pfx }, resource_mt) end function source:createCollection (rootUrl, path) local diskpath = self.rootDir .. path return lfs.mkdir (diskpath) end local _liveprops = {} _liveprops["DAV:creationdate"] = function (self) return os.date ("!%a, %d %b %Y %H:%M:%S GMT", self.attr.change) end _liveprops["DAV:displayname"] = function (self) local name = "" for part in string.gfind (self.path, "[^/]+") do name = part end return name end _liveprops["DAV:source"] = function (self) return self:getHRef () end _liveprops["DAV:supportedlock"] = function (self) return [[ ]] end _liveprops["DAV:getlastmodified"] = function (self) return os.date ("!%a, %d %b %Y %H:%M:%S GMT", self.attr.modification) end _liveprops["DAV:resourcetype"] = function (self) if self.attr.mode == "directory" then return "" else return "" end end _liveprops["DAV:getcontenttype"] = function (self) return self:getContentType () end _liveprops["DAV:getcontentlength"] = function (self) return self:getContentSize () end function resource:getContentType () if self.attr.mode == "directory" then return "httpd/unix-directory" end local _,_,exten = string.find (self.path, "%.([^.]*)$") exten = exten or "" return xavante.mimetypes [exten] or "" end function resource:getContentSize () if self.attr.mode == "file" then return self.attr.size else return 0 end end function resource:getContentData () local function gen () local f = io.open (self.diskpath, "rb") if not f then return end local block repeat block = f:read (8192) if block then coroutine.yield (block) end until not block f:close () end return coroutine.wrap (gen) end function resource:addContentData (b) local f = assert (io.open (self.diskpath, "a+b")) f:seek ("end") f:write (b) f:close () end function resource:delete () local ok, err = os.remove (self.diskpath) if not ok then err = string.format ([[HTTP/1.1 424 %s]], err) end return ok, err end function resource:getItems (depth) local gen local path = self.path local diskpath = self.diskpath local rootdir = self.source.rootDir if depth == "0" then gen = function () coroutine.yield (self) end elseif depth == "1" then gen = function () if self.attr.mode == "directory" then if string.sub (diskpath, -1) ~= "/" then diskpath = diskpath .."/" end if string.sub (path, -1) ~= "/" then path = path .."/" end for entry in lfs.dir (diskpath) do if string.sub (entry, 1,1) ~= "." then coroutine.yield (self.source:getResource (self.pfx, path..entry)) end end end coroutine.yield (self) end else local function recur (p) local attr = assert (lfs.attributes (rootdir .. p)) if attr.mode == "directory" then for entry in lfs.dir (rootdir .. p) do if string.sub (entry, 1,1) ~= "." then recur (p.."/"..entry) end end coroutine.yield (self.source:getResource (self.pfx, p)) end end gen = function () recur (path) end end if gen then return coroutine.wrap (gen) end end function resource:getPath () return self.path end function resource:getHRef () local _,_,sfx = string.find (self.path, "^/*(.*)$") return self.pfx..sfx end function resource:getPropNames () return pairs (_liveprops) end function resource:getProp (propname) local liveprop = _liveprops [propname] if liveprop then return liveprop (self) end end function resource:setProp (propname, value) return false end function makeSource (params) params = params or {} params.rootDir = params.rootDir or "./" return setmetatable (params, source_mt) end