[SOLVED] WebDAV error while filename contains special chars

Hello, using linux server version 9.0.2 (same error occur on 8.0.5), whenever i try to use WebDAV on macOS while filename contains special character for example: “á”, there is an error, related seafdav.log:

2022-01-14 14:51:48.903 - <140285241718528> wsgidav.wsgidav_app         INFO    :  127.0.0.1 - example@example.com - [2022-01-14 13:51:48] "PROPFIND /library/á.txt" length=167, depth=0, elap=0.083sec -> 404 Not Found
2022-01-14 14:51:49.077 - <140285328119552> wsgidav.error_printer       ERROR   :  Caught HTTPRequestException(HTTP_INTERNAL_ERROR)
Traceback (most recent call last):
  File "/opt/seafile/seafile-server-9.0.2/seahub/thirdpart/wsgidav/error_printer.py", line 52, in __call__
    for v in app_iter:
  File "/opt/seafile/seafile-server-9.0.2/seahub/thirdpart/wsgidav/request_resolver.py", line 213, in __call__
    for v in app_iter:
  File "/opt/seafile/seafile-server-9.0.2/seahub/thirdpart/wsgidav/request_server.py", line 126, in __call__
    app_iter = provider.custom_request_handler(environ, start_response, method)
  File "/opt/seafile/seafile-server-9.0.2/seahub/thirdpart/wsgidav/dav_provider.py", line 1525, in custom_request_handler
    return default_handler(environ, start_response)
  File "/opt/seafile/seafile-server-9.0.2/seahub/thirdpart/wsgidav/request_server.py", line 780, in do_PUT
    res = parentRes.create_empty_resource(util.get_uri_name(path))
  File "/opt/seafile/seafile-server-9.0.2/seahub/thirdpart/wsgidav/seafile_dav_provider.py", line 457, in create_empty_resource
    raise DAVError(HTTP_INTERNAL_ERROR)
wsgidav.dav_error.DAVError: DAVError(500 Internal Server Error: An internal server error occurred)

2022-01-14 14:51:49.078 - <140285328119552> wsgidav.error_printer       ERROR   :  e.src_exception:
None
2022-01-14 14:51:49.079 - <140285328119552> wsgidav.wsgidav_app         INFO    :  127.0.0.1 - example@example.com - [2022-01-14 13:51:49] "PUT /library/á.txt" length=15872, elap=0.139sec -> 500 Internal Server Error

What is wierd is that the file gets created but have 0 bytes. When i tryed to take a look at souce there are two functions which seems to handle encoding differently, code from “/seahub/thirdpart/wsgidav/seafile_dav_provider.py”:

def create_empty_resource(self, name):
    #...
    seafile_api.post_empty_file(self.repo.id, self.rel_path, name, self.username) # this seems to handle it properly
    #...
    member_rel_path = "/".join([self.rel_path, name])
    member_path = "/".join([self.path, name])
    obj = resolveRepoPath(repo, member_rel_path) # but here i guess encoding somehow mess things up

Wanted to kinda dump the values to log but i dunno how, seems like these files are cached or something like that, because any change i do in there doesn’t make a difference.

Edit:
Found solution, in source code to server i found out that the seafile_api.post_empty_file utf8-normalize the file name, so running pip install unicodedata2 and modifying file mentioned above seafile_dav_provider.py, adding import unicodedata to “import section” and then simply adding this line: name = unicodedata.normalize('NFC',name) as first line in function def create_empty_resource(self, name): did the job

Edit 2:
Server version 9.0.4 solves this issue.

1 Like

@daniel.pan Wouldn’t this be something that should be merged into the code base of Seafile Server?

Thanks for the notification. We will check it.

The problem is that now Seafile is always storing the file names in NFC form, which basically changes the file name. We use it to host files and now links to unicode file names are broken because the link is in decomposed form, the original file name is in decomposed form, but Seafile changes it to the composed form and hence the file cannot be found anymore under the original name.

What software do you use to mount WebDAV? Currently seafdav doesn’t convert file names back to NFD before returning to the client.

I am using seaf-fuse. I haven’t tested it, but it seems that this new conversion to NFC happens when files are uploaded via WebDAV? Because then it means that if I store the same file once per WebDAV and once per Seafile client then the file names might not be identical, the WebDAV one will always be NFC form whereas the others stay in their original form if they were in decomposed form.

No. All filenames in Seafile are stored in NFC format internally. It’s converted to NFC before saving. Previously WebDAV doesn’t do this conversion so there was a bug. As I said, the filenames returned by WebDAV is not converted back to NFD. This should be handled by the client on macOS. But this depends on which client you use.