diff options
Diffstat (limited to 'modules/ext/webdav.js')
| -rw-r--r-- | modules/ext/webdav.js | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/modules/ext/webdav.js b/modules/ext/webdav.js index 310d6f3..ed312a5 100644 --- a/modules/ext/webdav.js +++ b/modules/ext/webdav.js @@ -1722,20 +1722,42 @@ class WebDAVModule { if (window.webx11 && window.webx11.inputField) window.webx11.inputField.focus(); }; - // Share: copy direct folder URL to clipboard - document.getElementById('wdav-share').onclick = function() { - const spaceName = self._resolveSpaceName(); - const cleanPath = (path || '/').replace(/\/+$/, '') + '/'; - const shareUrl = 'https://webx11.duckdns.org/spaces/' + (spaceName || '') + cleanPath; - if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText(shareUrl).then(function() { - self.terminal.print('🔗 Shared URL copied: ' + shareUrl, 'success'); - }, function() { - self.terminal.print('🔗 Share URL: ' + shareUrl, 'info'); - }); - } else { - self.terminal.print('🔗 Share URL: ' + shareUrl, 'info'); + // Share: copy the public URL of the selected FILE(s). Folder listings need the + // owner session, so a folder URL is a guaranteed 403 for the recipient (2026-10-21). + document.getElementById('wdav-share').onclick = async function() { + const space = self._resolveSpaceName() || ''; + const sel = Object.keys(self._selected || {}).filter(function(n) { return self._selected[n]; }); + const files = sel.filter(function(n) { + const e = (allEntries || []).find(function(x) { return x.name === n; }); + return e && e.type === 'file'; + }); + if (!files.length) { + const dirName = String(path || '/').replace(/^\/+/, '').replace(/\/+$/, ''); + const _mods = self.terminal && self.terminal.moduleManager && self.terminal.moduleManager.modules; + const gz = _mods && _mods.CryptoGzipModule; + if (gz && dirName) { + self.terminal.print('🔗 Folders cannot be shared directly — archiving ' + dirName + ' …', 'info'); + try { await self.terminal.security.checkAndRun('tar -c ' + dirName); } catch (e) {} + self.terminal.print('Now select the resulting .tar and press 🔗 (it is a file).', 'info'); + } else { + self.terminal.print('🔗 Select one or more FILES to share — folder listings require the owner session and return 403 for everyone else.', 'warning'); + } + return; } + const dir = String(path || '/').replace(/^\/+/, '').replace(/\/+$/, ''); + const prefix = 'https://webx11.duckdns.org/spaces/' + space + '/' + (dir ? dir + '/' : ''); + const urls = files.map(function(n) { return prefix + encodeURIComponent(n); }); + const verified = []; + for (let i = 0; i < urls.length; i++) { + let st = null; + try { const h = await fetch(urls[i], { method: 'HEAD', credentials: 'omit' }); st = h.status; } catch (e) {} + if (st === 200) verified.push(urls[i]); + else self.terminal.print('⚠️ Not shareable: ' + urls[i] + ' → HTTP ' + (st === null ? 'no network' : st), 'warning'); + } + if (!verified.length) return; + const text = verified.join('\n'); + try { await navigator.clipboard.writeText(text); } catch (e) { prompt('Copy share link(s):', text); } + self.terminal.print('🔗 Copied ' + verified.length + ' verified link(s): ' + verified.join(' , '), 'success'); }; function renderList() { |