luci-base: ui: fix path handling in UIFileUpload
authorPaul Donald <[email protected]>
Thu, 20 Mar 2025 16:20:08 +0000 (17:20 +0100)
committerPaul Donald <[email protected]>
Thu, 20 Mar 2025 16:24:55 +0000 (17:24 +0100)
Browsing the root path was problematic and the breadcrumb links behaved
inconsistently, requiring a page reload to recover.

canonicalizePath(), splitPath() and renderListing() now handle any path
location properly, including root: '/', and clicks at any breadcrumb
correctly navigate.

Signed-off-by: Paul Donald <[email protected]>
(cherry picked from commit 5e39cf04c41e5a656e612aa36f75ce47211defee)

modules/luci-base/htdocs/luci-static/resources/ui.js

index a7a35bc62eaaad9d6ba18d97c14cd5f2197392de..ce1d8c6b4132b09df09997fb8e78cf388f462d55 100644 (file)
@@ -2876,10 +2876,10 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
 
        /** @private */
        canonicalizePath(path) {
-               return path.replace(/\/{2,}/, '/')
-                       .replace(/\/\.(\/|$)/g, '/')
-                       .replace(/[^\/]+\/\.\.(\/|$)/g, '/')
-                       .replace(/\/$/, '');
+       return path.replace(/\/{2,}/g, '/')                // Collapse multiple slashes
+                               .replace(/\/\.(\/|$)/g, '/')           // Remove `/.`
+                               .replace(/[^\/]+\/\.\.(\/|$)/g, '/')   // Resolve `/..`
+                               .replace(/\/$/g, (m, o, s) => s.length > 1 ? '' : '/'); // Remove trailing `/` only if not root
        },
 
        /** @private */
@@ -2890,10 +2890,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
                if (cpath.length <= croot.length)
                        return [ croot ];
 
-               if (cpath.charAt(croot.length) != '/')
-                       return [ croot ];
-
-               const parts = cpath.substring(croot.length + 1).split(/\//);
+               const parts = cpath.substring(croot.length).split(/\//);
 
                parts.unshift(croot);
 
@@ -3078,13 +3075,13 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
                let cur = '';
 
                for (let i = 0; i < dirs.length; i++) {
-                       cur = cur ? `${cur}/${dirs[i]}` : dirs[i];
+                       cur += dirs[i];
                        dom.append(breadcrumb, [
                                i ? ' ยป ' : '',
                                E('a', {
                                        'href': '#',
                                        'click': UI.prototype.createHandlerFn(this, 'handleSelect', cur ?? '/', null)
-                               }, dirs[i] != '' ? '%h'.format(dirs[i]) : E('em', '(root)')),
+                               }, dirs[i] !== '/' ? '%h'.format(dirs[i]) : E('em', '(root)')),
                        ]);
                }