diff --git a/lib/dav/webdav/lock.v b/lib/dav/webdav/lock.v index 4872a8a4..1c719e0f 100644 --- a/lib/dav/webdav/lock.v +++ b/lib/dav/webdav/lock.v @@ -18,22 +18,22 @@ pub: // lock attempts to lock a resource for a specific owner // Returns a LockResult with the lock token and whether it's a new lock // Returns an error if the resource is already locked by a different owner -pub fn (mut lm LockManager) lock(resource string, owner string, depth int, timeout int) !Lock { - if resource in lm.locks { +pub fn (mut lm LockManager) lock(l Lock) !Lock { + if l.resource in lm.locks { // Check if the lock is still valid - existing_lock := lm.locks[resource] + existing_lock := lm.locks[l.resource] if time.now().unix() - existing_lock.created_at.unix() < existing_lock.timeout { // Resource is already locked - if existing_lock.owner == owner { + if existing_lock.owner == l.owner { // Same owner, refresh the lock refreshed_lock := Lock {...existing_lock, - resource: resource - owner: owner - depth: depth - timeout: timeout + resource: l.resource + owner: l.owner + depth: l.depth + timeout: l.timeout created_at: time.now() } - lm.locks[resource] = refreshed_lock + lm.locks[l.resource] = refreshed_lock return refreshed_lock } else { // Different owner, return an error @@ -41,19 +41,16 @@ pub fn (mut lm LockManager) lock(resource string, owner string, depth int, timeo } } // Expired lock, remove it - lm.unlock(resource) + lm.unlock(l.resource) } // Generate a new lock token new_lock := Lock{ - resource: resource - owner: owner + ...l, token: rand.uuid_v4() - depth: depth - timeout: timeout created_at: time.now() } - lm.locks[resource] = new_lock + lm.locks[l.resource] = new_lock return new_lock } @@ -102,13 +99,13 @@ pub fn (mut lm LockManager) unlock_with_token(resource string, token string) boo return false } -fn (mut lm LockManager) lock_recursive(resource string, owner string, depth int, timeout int) !Lock { - if depth == 0 { - return lm.lock(resource, owner, depth, timeout) +fn (mut lm LockManager) lock_recursive(l Lock) !Lock { + if l.depth == 0 { + return lm.lock(l) } // Implement logic to lock child resources if depth == 1 // For now, just lock the parent resource - return lm.lock(resource, owner, depth, timeout) + return lm.lock(l) } pub fn (mut lm LockManager) cleanup_expired_locks() { diff --git a/lib/dav/webdav/methods.v b/lib/dav/webdav/methods.v index b5771b85..91c246ee 100644 --- a/lib/dav/webdav/methods.v +++ b/lib/dav/webdav/methods.v @@ -31,10 +31,8 @@ pub fn (mut app App) lock(mut ctx Context, path string) veb.Result { ctx.res.set_status(.bad_request) return ctx.text('Invalid lock request: ${err}') } - + // Get depth and timeout from headers (these are still in headers) - depth := ctx.get_custom_header('Depth') or { '0' }.int() - // Parse timeout header which can be in format "Second-600" timeout_str := ctx.get_custom_header('Timeout') or { 'Second-3600' } mut timeout := 3600 // Default 1 hour @@ -45,23 +43,22 @@ pub fn (mut app App) lock(mut ctx Context, path string) veb.Result { timeout = timeout_val.int() } } - - // Check if the resource is already locked by a different owner - if existing_lock := app.lock_manager.get_lock(resource) { - if existing_lock.owner != lock_info.owner { - // Resource is locked by a different owner - // Return a 423 Locked status with information about the existing lock - ctx.res.set_status(.locked) - return ctx.send_response_to_client('application/xml', existing_lock.xml()) - } + + new_lock := Lock { + ...lock_info, + resource: ctx.req.url + depth: ctx.get_custom_header('Depth') or { '0' }.int() + timeout: timeout } // Try to acquire the lock - lock_result := app.lock_manager.lock(resource, lock_info.owner, depth, timeout) or { + lock_result := app.lock_manager.lock(new_lock) or { // If we get here, the resource is locked by a different owner ctx.res.set_status(.locked) return ctx.text('Resource is already locked by a different owner.') } + + log.debug('[WebDAV] Received lock result ${lock_result.xml()}') ctx.res.set_status(.ok) ctx.set_custom_header('Lock-Token', '${lock_result.token}') or { return ctx.server_error(err.msg()) } @@ -93,22 +90,13 @@ pub fn (mut app App) unlock(mut ctx Context, path string) veb.Result { @['/:path...'; get] pub fn (mut app App) get_file(mut ctx Context, path string) veb.Result { log.info('[WebDAV] Getting file ${path}') - if !app.vfs.exists(path) { - return ctx.not_found() - } - - fs_entry := app.vfs.get(path) or { - log.error('[WebDAV] failed to get FS Entry ${path}: ${err}') - return ctx.server_error(err.msg()) - } - file_data := app.vfs.file_read(path) or { return ctx.server_error(err.msg()) } - - ext := fs_entry.get_metadata().name.all_after_last('.') - content_type := veb.mime_types[ext] or { 'text/plain' } - - ctx.res.header.set(.content_length, file_data.len.str()) - ctx.res.set_status(.ok) + ext := path.all_after_last('.') + content_type := veb.mime_types['.${ext}'] or { 'text/plain' } + println('debugzo000 ${file_data.bytestr().len}') + println('debugzo001 ${file_data.len}') + // ctx.res.header.set(.content_length, file_data.len.str()) + // ctx.res.set_status(.ok) return ctx.send_response_to_client(content_type, file_data.bytestr()) } @@ -157,32 +145,10 @@ pub fn (mut app App) exists(mut ctx Context, path string) veb.Result { @['/:path...'; delete] pub fn (mut app App) delete(mut ctx Context, path string) veb.Result { - if !app.vfs.exists(path) { - return ctx.not_found() - } - - fs_entry := app.vfs.get(path) or { - console.print_stderr('failed to get FS Entry ${path}: ${err}') + app.vfs.delete(path) or { return ctx.server_error(err.msg()) } - - // Check if the resource is locked - if app.lock_manager.is_locked(ctx.req.url) { - // Resource is locked, return a 207 Multi-Status response with a 423 Locked status - ctx.res.set_status(.multi_status) - return ctx.send_response_to_client('application/xml', $tmpl('./templates/delete_response.xml')) - } - - // If not locked, proceed with deletion - if fs_entry.is_dir() { - console.print_debug('deleting directory: ${path}') - app.vfs.dir_delete(path) or { return ctx.server_error(err.msg()) } - } - - if fs_entry.is_file() { - console.print_debug('deleting file: ${path}') - app.vfs.file_delete(path) or { return ctx.server_error(err.msg()) } - } + // Return success response return ctx.no_content() @@ -255,18 +221,7 @@ pub fn (mut app App) mkcol(mut ctx Context, path string) veb.Result { } @['/:path...'; propfind] -fn (mut app App) propfind(mut ctx Context, path string) veb.Result { - log.info('[WebDAV] ${@FN} ${path}') - - // Check if resource exists - if !app.vfs.exists(path) { - return ctx.error( - status: .not_found - message: 'Path ${path} does not exist' - tag: 'resource-must-be-null' - ) - } - +fn (mut app App) propfind(mut ctx Context, path string) veb.Result { // Parse PROPFIND request propfind_req := parse_propfind_xml(ctx.req) or { return ctx.error(WebDAVError{ @@ -276,7 +231,7 @@ fn (mut app App) propfind(mut ctx Context, path string) veb.Result { }) } - log.debug('[WebDAV] ${@FN} Propfind Request: ${propfind_req.typ} ${propfind_req.depth}') + log.debug('[WebDAV] Propfind Request: ${propfind_req.typ} ${propfind_req.depth}') // Check if resource is locked @@ -287,12 +242,20 @@ fn (mut app App) propfind(mut ctx Context, path string) veb.Result { log.info('[WebDAV] Resource is locked: ${ctx.req.url}') } - entry := app.vfs.get(path) or {return ctx.server_error('entry not found ${err}')} + entry := app.vfs.get(path) or { + return ctx.error( + status: .not_found + message: 'Path ${path} does not exist' + tag: 'resource-must-be-null' + ) + } responses := app.get_responses(entry, propfind_req) or { return ctx.server_error('Failed to get entry properties ${err}') } + // log.debug('[WebDAV] Propfind responses ${responses}') + // Create multistatus response using the responses ctx.res.set_status(.multi_status) return ctx.send_response_to_client('application/xml', responses.xml()) diff --git a/lib/dav/webdav/middleware_log.v b/lib/dav/webdav/middleware_log.v index 668ec0ea..1e5b895a 100644 --- a/lib/dav/webdav/middleware_log.v +++ b/lib/dav/webdav/middleware_log.v @@ -9,7 +9,7 @@ fn middleware_log_request(mut ctx Context) bool { } fn middleware_log_response(mut ctx Context) bool { - log.debug('[WebDAV] Response: ${ctx.req.url} ${ctx.res.status()}\n') + log.debug('[WebDAV] Response: ${ctx.req.url} ${ctx.res.header}\n') return true } \ No newline at end of file