root/LW/LWDAVService.lua

Revision 951 (checked in by rsz, 3 years ago)

cleanup

Line 
1 --------------------------------------------------------------------------------
2 -- Title:               LWDAVService.lua
3 -- Description:         Like a square peg in a round hole
4 -- Author:              Raphaël Szwarc http://alt.textdrive.com/lua/
5 -- Creation Date:       February 1, 2005
6 -- Legal:               Copyright (C) 2005 Raphaël Szwarc
7 --------------------------------------------------------------------------------
8
9 -- Based on Pier Fumagalli's "A simple approach to WebDAV"
10 -- http://www.betaversion.org/~pier/wiki/display/pier/A+simple+approach+to+WebDAV
11
12 -- import dependencies
13 local LWObjectService = require( "LWObjectService" )
14 local LWDAVResponse = require( "LWDAVResponse" )
15 local LWDirectoryService = require( "LWDirectoryService" )
16 local LWFileService = require( "LWFileService" )
17 local LUList = require( "LUList" )
18 local LUMap = require( "LUMap" )
19 local LUString = require( "LUString" )
20 local LUURI = require( "LUURI" )
21 local LFSFile = require( "LFSFile" )
22 local LULog = require( "LULog" )
23
24 -- define the class
25 local super = LWObjectService
26 local self = super()
27
28 -- initialization method
29 function self:init( aPrefix, aPath, anAuthenticator )
30         self = super.init( self, aPrefix, nil, anAuthenticator )
31        
32         self._path = aPath
33        
34         return self
35 end
36
37 -- method to access this service directory
38 function self:directory()
39         if self._directory == nil then
40                 self._directory = LFSFile( self:path() )
41         end
42        
43         return self._directory
44 end
45
46 -- method to access this service path
47 function self:path()
48         return self._path
49 end
50
51 -- method to define an object for a given path
52 function self:objectWithPath( aPath, aContext )
53         if aPath ~= nil then
54                 local someComponents = LUList():addAll( LFSFile:pathComponents( self:path() ) )
55                       someComponents:addAll( LUString:components( aPath, "/" ) )
56                 local aName = someComponents:last()
57                 local aPath = LFSFile:separator() .. someComponents:removeLast():join( LFSFile:separator() )
58                 local aFile = LFSFile( aPath, aName )
59                
60                 return aFile
61         end
62        
63         return self:directory()
64 end
65
66 -- method to define a path for a given a object
67 function self:pathWithObject( anObject, aContext )
68         if anObject ~= nil then
69                 local aServicePath = self:path()
70                 local aPath = anObject:path()
71                
72                 aPath = aPath:sub( aServicePath:len() + 1 )
73
74                 aPath = self:prefix() .. aPath:sub( 2 )
75                
76                 if anObject:isDirectory() == true and aPath:find( "/$" ) == nil then
77                         aPath = aPath .. "/"
78                 end
79                
80                 aPath = aPath:gsub( "%" .. LFSFile:separator(), "%/" )
81                
82                 return aPath
83         end
84        
85         return self:prefix()
86 end
87
88 -- method to define a component for given a object
89 function self:componentWithObject( anObject, aContext )
90         local someBindings = LUMap()
91               someBindings:put( "object", anObject )
92         local aComponent = LWDAVResponse( aContext, nil, someBindings )
93        
94         return aComponent
95 end
96
97 -- method to handle a COPY method
98 function self:handleCopy( aContext, shouldDelete )
99         local aPath = self:pathWithContext( aContext )
100         local anObject = self:objectWithPath( aPath, aContext )
101
102         if anObject:exists() == true then
103                 local aDestination = aContext:request():headers():get( "destination" )
104                 local anIndex = aDestination:find( "://" ) + 3
105                       anIndex = aDestination:find( "/", anIndex )
106                       aDestination = aDestination:sub( anIndex )
107                       aDestination = aDestination:sub( self:prefix():len() + 1 )
108                       aDestination = LUURI:decode( aDestination )
109                 local aDestinationObject = self:objectWithPath( aDestination, aContext )
110                
111                 if aDestinationObject:exists() == true then
112                         local shouldOverwrite = aContext:request():headers( "overwrite" )
113                        
114                         if shouldOverwrite == "T" then
115                                 anObject:copy( aDestinationObject, shouldDelete )
116
117                                 aContext:response():writeStatus( 200 )
118                         else
119                                 aContext:response():writeStatus( 412 )
120                         end
121                 else
122                         anObject:copy( aDestinationObject, shouldDelete )
123                        
124                         aContext:response():writeStatus( 200 )
125                 end
126         else
127                 aContext:response():writeStatus( 404 )
128         end
129
130         return self
131 end
132
133 -- method to handle a DELETE method
134 function self:handleDelete( aContext )
135         local aPath = self:pathWithContext( aContext )
136         local anObject = self:objectWithPath( aPath, aContext )
137        
138         if anObject:exists() == true then
139                 anObject:delete()
140        
141                 aContext:response():writeStatus( 200 )
142         else
143                 aContext:response():writeStatus( 404 )
144         end
145        
146         return self
147 end
148
149 -- method to handle a GET method
150 function self:handleGet( aContext, hasContent )
151         local aPath = self:pathWithContext( aContext )
152         local anObject = self:objectWithPath( aPath, aContext )
153        
154         LULog:debug( anObject )
155        
156         if anObject:exists() == true then
157                 local aPrefix = aContext:request():uri():path()
158                 local aPath = anObject:path()
159                 local anAuthenticator = self:authenticator()
160                 local aService = nil;
161                
162                 if anObject:isFile() == true then
163                         aPrefix = LUString:components( aPrefix, "/" )
164                         aPrefix:removeLast()
165                         aPrefix = "/" .. aPrefix:join( "/" ) .. "/"
166                         aPath = anObject:directory()
167                
168                         aService = LWFileService( aPrefix, aPath, anAuthenticator )
169                 else
170                         aService = LWDirectoryService( aPrefix, aPath, anAuthenticator )
171                 end
172
173                 aService:handleGet( aContext, hasContent )
174         else
175                 aContext:response():writeStatus( 404, hasContent )
176         end
177        
178         return self
179 end
180
181 -- method to handle a MKCOL method
182 function self:handleMkCol( aContext )
183         if aContext:request():content() == nil then
184                 local aPath = self:pathWithContext( aContext )
185                 local anObject = self:objectWithPath( aPath, aContext )
186                
187                 anObject:mkdir()
188                
189                 aContext:response():writeStatus( 201 )
190         else
191                 aContext:response():writeStatus( 415 )
192         end
193
194         return self
195 end
196
197 -- method to handle a MOVE method
198 function self:handleMove( aContext )
199         self:handleCopy( aContext, true )
200 end
201
202 -- method to handle a PROPFIND method
203 function self:handlePropFind( aContext )
204         local aDepth = aContext:request():headers():get( "depth" )
205        
206         aContext:request():content()
207        
208         if aDepth ~= nil then
209                 aDepth = tonumber( aDepth )
210        
211                 if aDepth ~= nil and aDepth >= 0 and aDepth <= 1 then
212                         local aPath = self:pathWithContext( aContext )
213                         local anObject = self:objectWithPath( aPath, aContext )
214
215                         if anObject:exists() == true then
216                                 local aComponent = self:componentWithObject( anObject, aContext )
217                                       aComponent:bindings():put( "depth", aDepth )
218                                 local aContent = aComponent:toString()
219                                
220                                 aContext:response():writeContent( aContent )
221                         else
222                                 aContext:response():writeStatus( 404 )
223                         end
224                 else
225                         aContext:response():writeStatus( 403 )
226                 end
227         else
228                 aContext:response():writeStatus( 403 )
229         end
230        
231         return self
232 end
233
234 -- method to handle a PROPPATCH method
235 function self:handlePropPatch( aContext )
236         aContext:response():writeStatus( 403 )
237        
238         return self
239 end
240
241 -- method to handle a PUT method
242 function self:handlePut( aContext )
243         local aPath = self:pathWithContext( aContext )
244         local anObject = self:objectWithPath( aPath, aContext )
245         local didExist = anObject:exists()
246        
247         anObject:setContent( aContext:request():content() )
248        
249         if didExist == true then
250                 aContext:response():writeStatus( 200 )
251         else
252                 aContext:response():writeStatus( 201 )
253         end
254        
255         return self
256 end
257
258 return self
Note: See TracBrowser for help on using the browser.