-------------------------------------------------------------------------------- -- Title: WikiContentFileService.lua -- Description: Like a square peg in a round hole -- Author: Raphaël Szwarc http://alt.textdrive.com/lua/ -- Creation Date: January 30, 2007 -- Legal: Copyright (C) 2007 Raphaël Szwarc -- Under the terms of the MIT License -- http://www.opensource.org/licenses/mit-license.html -------------------------------------------------------------------------------- -- import dependencies local HTTP = require( 'HTTP' ) local os = require( 'os' ) local getmetatable = getmetatable local require = require local setmetatable = setmetatable local tostring = tostring -------------------------------------------------------------------------------- -- WikiContentFileService -------------------------------------------------------------------------------- module( 'WikiContentFileService' ) _VERSION = '1.0' local self = setmetatable( _M, {} ) local meta = getmetatable( self ) -------------------------------------------------------------------------------- -- Utilities -------------------------------------------------------------------------------- local function ValidContent( aContent, aName ) if aContent and aContent.exists and ( '%s.txt' ):format( aContent.data.title ):lower() == aName:lower() then return true end end local function FindFile( aContent, aName ) aName = aName:lower() for aFile in aContent.file do if aFile.name == aName then return aFile end end end local function ValidFile( aContent, aName ) local aName = aName:lower(); local aReference = ( '%s/file/%s' ):format( aContent.name, aName ) local aFile = FindFile( aContent, aName ) if not aFile then return false end if not aContent.text:find( aReference, 1, true ) then local aTime = os.time() local anInterval = aTime - aFile.modification if anInterval < 3600 then return true else aFile.delete = true return false end end return true end local function DAVContentResource( aContent ) local aName = ( '%s.txt' ):format( aContent.data.title ) local aCreation = aContent.creation local aModification = aContent.modification local aSize = aContent.text:len() local aResource = { mode = 'file', creation = aCreation, modification = aModification, name = aName, size = aSize } return aResource end local function DAVFileResource( aContent, aName ) local aFile = FindFile( aContent, aName ) local aResource = { mode = aFile.mode, modification = aFile.modification, name = aFile.name, size = aFile.size } return aResource end local function DAVListIterator( aContent ) local anIterator = aContent.file return function() local aFile = anIterator() if aFile then local aResource = { mode = aFile.mode, modification = aFile.modification, name = aFile.name, size = aFile.size } return aResource end end end local function DAVListResource( aContent ) local anIterator = DAVListIterator( aContent ) local aModification = aContent.modification local aResource = { iterator = anIterator, mode = 'directory', modification = aModification, size = 0 } return aResource end local function DAVResource( aContent, aName ) if not aName then return DAVListResource( aContent ) elseif ValidContent( aContent, aName ) then return DAVContentResource( aContent ) elseif ValidFile( aContent, aName ) then return DAVFileResource( aContent, aName ) end end -------------------------------------------------------------------------------- -- Service methods -------------------------------------------------------------------------------- function self:get() local aContent = self.content local aName = self.name if aContent and aContent.exists and aName then local aName = aName:lower() if ValidContent( aContent, aName ) then HTTP.response.header[ 'content-type' ] = 'text/plain; charset=utf-8' return aContent.text elseif ValidFile( aContent, aName ) then local File = require( 'File' ) local HTTPFile = require( 'HTTPFile' ) local aDirectory = File( aContent.directory.path, 'file', '' ) local aHandler = HTTPFile( aDirectory.path ) return aHandler( aName ) end end end -------------------------------------------------------------------------------- -- DAV service methods -------------------------------------------------------------------------------- function self:options() HTTP.response.header[ 'allow' ] = 'DELETE, GET, HEAD, LOCK, MOVE, OPTIONS, PROPFIND, PUT, UNLOCK' HTTP.response.header[ 'content-type' ] = 'text/plain' return HTTP.response.header[ 'allow' ] end function self:propfind() local aContent = self.content if aContent and aContent.exists then local WikiDAV = require( 'WikiDAV' ) local aResource = DAVResource( aContent, self.name ) if aResource then return WikiDAV( aResource ):propfind() end end end -------------------------------------------------------------------------------- -- Metamethods -------------------------------------------------------------------------------- function meta:__call( aContent, aName ) local aService = { content = aContent, name = aName } setmetatable( aService, self ) return aService end function meta:__concat( aValue ) return tostring( self ) .. tostring( aValue ) end function meta:__tostring() return ( '%s/%s' ):format( self._NAME, self._VERSION ) end function self:__index( aKey ) local aValue = getmetatable( self )[ aKey ] if not aValue and aKey:find( '^get.+' ) then local aName = aKey:match( '^get(.+)$' ) self.name = aName return function( self, anExtension ) self.name = ( '%s.%s' ):format( aName, anExtension or '' ) return self end elseif not aValue and aKey:find( '^propfind.+' ) then local aName = aKey:match( '^propfind(.+)$' ) self.name = aName return function( self, anExtension ) self.name = ( '%s.%s' ):format( aName, anExtension or '' ) return self end end self[ aKey ] = aValue return aValue end function self:__concat( aValue ) return tostring( self ) .. tostring( aValue ) end function self:__tostring() return tostring( self.name ) end