diff --git a/base b/base index fd9dc6099..7b146478b 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit fd9dc60997518c607d45cdd75d68ed7e7c004db0 +Subproject commit 7b146478b65dcb0e37133201c6b0d1e6b7914c58 diff --git a/frontend/apps/cloudstorage/webdav.lua b/frontend/apps/cloudstorage/webdav.lua index bf9795879..be2a23e85 100644 --- a/frontend/apps/cloudstorage/webdav.lua +++ b/frontend/apps/cloudstorage/webdav.lua @@ -67,7 +67,7 @@ function WebDav:uploadFile(url, address, username, password, local_path, callbac end function WebDav:createFolder(url, address, username, password, folder_name, callback_close) - local code_response = WebDavApi:createFolder(address .. WebDavApi:urlEncode(url .. "/" .. folder_name), username, password, folder_name) + local code_response = WebDavApi:createFolder(address .. WebDavApi.urlEncode(url .. "/" .. folder_name), username, password, folder_name) if code_response == 201 then if callback_close then callback_close() diff --git a/frontend/apps/cloudstorage/webdavapi.lua b/frontend/apps/cloudstorage/webdavapi.lua index f0d36696f..923984d45 100644 --- a/frontend/apps/cloudstorage/webdavapi.lua +++ b/frontend/apps/cloudstorage/webdavapi.lua @@ -12,44 +12,23 @@ local lfs = require("libs/libkoreader-lfs") local WebDavApi = { } -function WebDavApi:getJoinedPath( address, path ) - local path_encoded = self:urlEncode( path ) or "" - local address_strip = address:sub(-1) == "/" and address:sub(1, -2) or address - local path_strip = path_encoded:sub(1, 1) == "/" and path_encoded:sub(2) or path_encoded - return address_strip .. "/" .. path_strip +-- Trim leading & trailing slashes from string `s` (based on util.trim) +function WebDavApi.trim_slashes(s) + local from = s:match"^/*()" + return from > #s and "" or s:match(".*[^/]", from) end -function WebDavApi:isCurrentDirectory( current_item, address, path ) - local is_home, is_parent - local home_path - -- find first occurence of / after http(s):// - local start = string.find( address, "/", 9 ) - if not start then - home_path = "/" - else - home_path = string.sub( address, start ) - end - local item - if string.sub( current_item, -1 ) == "/" then - item = string.sub( current_item, 1, -2 ) - else - item = current_item - end - - if item == home_path then - is_home = true - else - local temp_path = string.sub( item, string.len(home_path) + 1 ) - if string.sub( path, -1 ) == "/" then path = string.sub( path, 1, -2 ) end - if temp_path == path then - is_parent = true - end +-- Trim trailing slashes from string `s` (based on util.rtrim) +function WebDavApi.rtrim_slashes(s) + local n = #s + while n > 0 and s:find("^/", n) do + n = n - 1 end - return is_home or is_parent + return s:sub(1, n) end --- version of urlEncode that doesn't encode the / -function WebDavApi:urlEncode(url_data) +-- Variant of util.urlEncode that doesn't encode the / +function WebDavApi.urlEncode(url_data) local char_to_hex = function(c) return string.format("%%%02X", string.byte(c)) end @@ -60,28 +39,30 @@ function WebDavApi:urlEncode(url_data) return url_data end +-- Append path to address with a slash separator, trimming any unwanted slashes in the process. +function WebDavApi:getJoinedPath(address, path) + local path_encoded = self.urlEncode(path) or "" + -- Strip leading & trailing slashes from `path` + local sane_path = self.trim_slashes(path_encoded) + -- Strip trailing slashes from `address` for now + local sane_address = self.rtrim_slashes(address) + -- Join our final URL + return sane_address .. "/" .. sane_path +end + function WebDavApi:listFolder(address, user, pass, folder_path, folder_mode) - local path = self:urlEncode( folder_path ) + local path = folder_path or "" local webdav_list = {} local webdav_file = {} - local has_trailing_slash = false - local has_leading_slash = false - if string.sub( address, -1 ) == "/" then has_trailing_slash = true end - if path == nil or path == "/" then - path = "" - elseif string.sub( path, 1, 1 ) == "/" then - if has_trailing_slash then - -- too many slashes, remove one - path = string.sub( path, 2 ) - end - has_leading_slash = true - end - if not has_trailing_slash and not has_leading_slash then - address = address .. "/" - end - local webdav_url = address .. path - if string.sub(webdav_url, -1) ~= "/" then + -- Strip leading & trailing slashes from `path` + path = self.trim_slashes(path) + -- Strip trailing slashes from `address` for now + address = self.rtrim_slashes(address) + -- Join our final URL, which *must* have a trailing / (it's a URL) + -- This is where we deviate from getJoinedPath ;). + local webdav_url = address .. "/" .. self.urlEncode(path) + if webdav_url:sub(-1) ~= "/" then webdav_url = webdav_url .. "/" end @@ -122,24 +103,18 @@ function WebDavApi:listFolder(address, user, pass, folder_path, folder_mode) --logger.dbg("WebDav catalog item=", item) -- is the path and filename of the entry. local item_fullpath = item:match("<[^:]*:href[^>]*>(.*)") - if string.sub( item_fullpath, -1 ) == "/" then - item_fullpath = string.sub( item_fullpath, 1, -2 ) - end - local is_current_dir = self:isCurrentDirectory( util.urlDecode(item_fullpath), address, folder_path ) - - local item_name = util.urlDecode( FFIUtil.basename( item_fullpath ) ) - item_name = util.htmlEntitiesToUtf8(item_name) - + local item_name = FFIUtil.basename(util.htmlEntitiesToUtf8(util.urlDecode(item_fullpath))) + local is_current_dir = item_name == string.sub(folder_path, -#item_name) local is_not_collection = item:find("<[^:]*:resourcetype/>") or - item:find("<[^:]*:resourcetype>") + item:find("<[^:]*:resourcetype>") + local item_path = path .. "/" .. item_name - local item_path = (path == "" and has_trailing_slash) and item_name or path .. "/" .. item_name if item:find("<[^:]*:collection[^<]*/>") then item_name = item_name .. "/" if not is_current_dir then table.insert(webdav_list, { text = item_name, - url = util.urlDecode( item_path ), + url = item_path, type = "folder", }) end @@ -147,7 +122,7 @@ function WebDavApi:listFolder(address, user, pass, folder_path, folder_mode) or G_reader_settings:isTrue("show_unsupported")) then table.insert(webdav_file, { text = item_name, - url = util.urlDecode( item_path ), + url = item_path, type = "file", }) end diff --git a/frontend/util.lua b/frontend/util.lua index 62c4cfd83..ddf2b906c 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -54,6 +54,23 @@ function util.trim(s) return from > #s and "" or s:match(".*%S", from) end +--[[ +-- Trim leading & trailing character `c` from string `s` +function util.trim_char(s, c) + local from = s:match"^"..c.."*()" + return from > #s and "" or s:match(".*[^"..c.."]", from) +end + +-- Trim trailing character `c` from string `s` +function util.rtrim_char(s, c) + local n = #s + while n > 0 and s:find("^"..c, n) do + n = n - 1 + end + return s:sub(1, n) +end +--]] + --[[-- Splits a string by a pattern