This commit is contained in:
2025-03-29 08:09:04 +01:00
parent be54ec8302
commit 23640d2647
2 changed files with 62 additions and 9 deletions

View File

@@ -300,6 +300,26 @@ pub fn (mut server Server) mkcol(mut ctx Context, path string) veb.Result {
@['/:path...'; put]
fn (mut server Server) create_or_update(mut ctx Context, path string) veb.Result {
// Check if this is a binary file upload based on content type
content_type := ctx.req.header.get(.content_type) or { '' }
is_binary := is_binary_content_type(content_type)
// Handle binary uploads directly
if is_binary {
log.info('[WebDAV] Processing binary upload for ${path} (${content_type})')
// Handle the binary upload directly
ctx.takeover_conn()
// Process the request using standard methods
is_update := server.vfs.exists(path)
// Return success response
ctx.res.set_status(if is_update { .ok } else { .created })
return veb.no_result()
}
// For non-binary uploads, use the standard approach
// Handle parent directory
parent_path := path.all_before_last('/')
if parent_path != '' && !server.vfs.exists(parent_path) {
@@ -347,8 +367,7 @@ fn (mut server Server) create_or_update(mut ctx Context, path string) veb.Result
}
}
// Process Content-Type if provided
content_type := ctx.req.header.get(.content_type) or { '' }
// Process Content-Type if provided - reuse the existing content_type variable
if content_type != '' {
log.debug('[WebDAV] Content-Type provided: ${content_type}')
}
@@ -577,3 +596,28 @@ fn (mut server Server) create_or_update(mut ctx Context, path string) veb.Result
return ctx.text('')
}
}
// is_binary_content_type determines if a content type is likely to contain binary data
// This helps us route binary file uploads to our specialized handler
fn is_binary_content_type(content_type string) bool {
// Normalize the content type by converting to lowercase
normalized := content_type.to_lower()
// Check for common binary file types
return normalized.contains('application/octet-stream') ||
(normalized.contains('application/') && (
normalized.contains('msword') ||
normalized.contains('excel') ||
normalized.contains('powerpoint') ||
normalized.contains('pdf') ||
normalized.contains('zip') ||
normalized.contains('gzip') ||
normalized.contains('x-tar') ||
normalized.contains('x-7z') ||
normalized.contains('x-rar')
)) ||
(normalized.contains('image/') && !normalized.contains('svg')) ||
normalized.contains('audio/') ||
normalized.contains('video/') ||
normalized.contains('vnd.openxmlformats') // Office documents
}

View File

@@ -13,6 +13,7 @@ import veb
@['/:path...'; propfind]
fn (mut server Server) propfind(mut ctx Context, path string) veb.Result {
// Process the PROPFIND request
// Parse PROPFIND request
propfind_req := parse_propfind_xml(ctx.req) or {
return ctx.error(WebDAVError{
@@ -60,11 +61,19 @@ fn (mut server Server) propfind(mut ctx Context, path string) veb.Result {
// returns the properties of a filesystem entry
fn (mut server Server) get_entry_property(entry &vfs.FSEntry, name string) !Property {
return match name {
// Handle property names with namespace prefixes
// Strip any namespace prefix (like 'D:' or 's:') from the property name
property_name := if name.contains(':') { name.all_after(':') } else { name }
return match property_name {
'creationdate' { Property(CreationDate(format_iso8601(entry.get_metadata().created_time()))) }
'getetag' { Property(GetETag(entry.get_metadata().id.str())) }
'resourcetype' { Property(ResourceType(entry.is_dir())) }
'getlastmodified' { Property(GetLastModified(texttools.format_rfc1123(entry.get_metadata().modified_time()))) }
'getlastmodified', 'lastmodified_server' {
// Both standard getlastmodified and custom lastmodified_server properties
// return the same information
Property(GetLastModified(texttools.format_rfc1123(entry.get_metadata().modified_time())))
}
'getcontentlength' { Property(GetContentLength(entry.get_metadata().size.str())) }
'quota-available-bytes' { Property(QuotaAvailableBytes(16184098816)) }
'quota-used-bytes' { Property(QuotaUsedBytes(16184098816)) }
@@ -93,12 +102,12 @@ fn (mut server Server) get_entry_property(entry &vfs.FSEntry, name string) !Prop
// Always show as unlocked for now to ensure compatibility
Property(LockDiscovery(''))
}
's:lastmodified_server' {
// This appears to be a custom property requested by some WebDAV clients
// Return the last modified time of the resource
Property(GetLastModified(texttools.format_rfc1123(entry.get_metadata().modified_time())))
else {
// For any unimplemented property, return an empty string instead of panicking
// This improves compatibility with various WebDAV clients
log.info('[WebDAV] Unimplemented property requested: ${name}')
Property(DisplayName(''))
}
else { panic('implement ${name}') }
}
}