diff --git a/packages/puter-js/src/modules/UI.js b/packages/puter-js/src/modules/UI.js index 08b0839f..c9b99033 100644 --- a/packages/puter-js/src/modules/UI.js +++ b/packages/puter-js/src/modules/UI.js @@ -466,7 +466,10 @@ class UI extends EventListener { let URLParams = new URLSearchParams(window.location.search); if(URLParams.has('puter.item.name') && URLParams.has('puter.item.uid') && URLParams.has('puter.item.read_url')){ let fpath = URLParams.get('puter.item.path'); - fpath = `~/` + fpath.split('/').slice(2).join('/'); + + if(!fpath.startsWith('~/') && !fpath.startsWith('/')) + fpath = '~/' + fpath + callback([new FSItem({ name: URLParams.get('puter.item.name'), path: fpath, @@ -495,7 +498,10 @@ class UI extends EventListener { let URLParams = new URLSearchParams(window.location.search); if(URLParams.has('puter.item.name') && URLParams.has('puter.item.uid') && URLParams.has('puter.item.read_url')){ let fpath = URLParams.get('puter.item.path'); - fpath = `~/` + fpath.split('/').slice(2).join('/'); + + if(!fpath.startsWith('~/') && !fpath.startsWith('/')) + fpath = '~/' + fpath; + callback([new FSItem({ name: URLParams.get('puter.item.name'), path: fpath, diff --git a/src/IPC.js b/src/IPC.js index aab0e7d8..1f1f3e81 100644 --- a/src/IPC.js +++ b/src/IPC.js @@ -747,7 +747,7 @@ window.addEventListener('message', async (event) => { signature = signature.items; signature.signatures = signature.signatures ?? [signature]; if(signature.signatures.length > 0 && signature.signatures[0].path){ - signature.signatures[0].path = `~/` + signature.signatures[0].path.split('/').slice(2).join('/') + signature.signatures[0].path = privacy_aware_path(signature.signatures[0].path) // send confirmation to requester window target_iframe.contentWindow.postMessage({ msg: "readAppDataFileSucceeded", @@ -1064,7 +1064,7 @@ window.addEventListener('message', async (event) => { metadataURL: file_signature.metadata_url, type: file_signature.type, uid: file_signature.uid, - path: `~/` + res.path.split('/').slice(2).join('/'), + path: privacy_aware_path(res.path) }, }, '*'); @@ -1247,7 +1247,7 @@ window.addEventListener('message', async (event) => { writeURL: file_signature.write_url, metadataURL: file_signature.metadata_url, uid: file_signature.uid, - path: `~/` + res.path.split('/').slice(2).join('/'), + path: privacy_aware_path(res.path), }, }, '*'); $(target_iframe).get(0).focus({preventScroll:true}); diff --git a/src/UI/UIWindow.js b/src/UI/UIWindow.js index 1ad4839f..66f35ac4 100644 --- a/src/UI/UIWindow.js +++ b/src/UI/UIWindow.js @@ -662,7 +662,7 @@ async function UIWindow(options) { // change path of each item to preserve privacy for(let i=0; i{ if(file_signature){ iframe_url.searchParams.append('puter.item.uid', file_signature.uid); - iframe_url.searchParams.append('puter.item.path', options.file_path ? `~/` + options.file_path.split('/').slice(1).join('/') : file_signature.path); + iframe_url.searchParams.append('puter.item.path', privacy_aware_path(options.file_path) || file_signature.path); iframe_url.searchParams.append('puter.item.name', file_signature.fsentry_name); iframe_url.searchParams.append('puter.item.read_url', file_signature.read_url); iframe_url.searchParams.append('puter.item.write_url', file_signature.write_url); @@ -1728,7 +1728,7 @@ window.launch_app = async (options)=>{ } else if(options.readURL){ iframe_url.searchParams.append('puter.item.name', options.filename); - iframe_url.searchParams.append('puter.item.path', options.file_path ? `~/` + options.file_path.split('/').slice(1).join('/') : undefined); + iframe_url.searchParams.append('puter.item.path', privacy_aware_path(options.file_path)); iframe_url.searchParams.append('puter.item.read_url', options.readURL); iframe_url.searchParams.append('puter.domain', window.app_domain); } @@ -1911,7 +1911,7 @@ window.open_item = async function(options){ let res = await puter.fs.sign(window.host_app_uid ?? parent_window_app_uid, {uid: uid, action: 'write'}); res = res.items; // todo split is buggy because there might be a slash in the filename - res.path = `~/` + item_path.split('/').slice(2).join('/'); + res.path = privacy_aware_path(item_path); const parent_uuid = $el_parent_window.attr('data-parent_uuid'); const return_to_parent_window = $el_parent_window.attr('data-return_to_parent_window') === 'true'; if(return_to_parent_window){ diff --git a/src/initgui.js b/src/initgui.js index b697e186..20bffd78 100644 --- a/src/initgui.js +++ b/src/initgui.js @@ -659,7 +659,7 @@ window.initgui = async function(options){ metadataURL: file_signature.metadata_url, type: file_signature.type, uid: file_signature.uid, - path: `~/` + res.path.split('/').slice(2).join('/'), + path: privacy_aware_path(res.path), }, }, '*'); @@ -1015,7 +1015,7 @@ window.initgui = async function(options){ metadataURL: file_signature.metadata_url, type: file_signature.type, uid: file_signature.uid, - path: `~/` + res.path.split('/').slice(2).join('/'), + path: privacy_aware_path(res.path), }, }, '*'); @@ -1391,4 +1391,34 @@ $(document).on('contextmenu', '.disable-context-menu', function(e){ e.preventDefault(); return false; } -}) \ No newline at end of file +}) + + +/** + * Converts a file system path to a privacy-aware path. + * - Paths starting with `~/` are returned unchanged. + * - Paths starting with the user's home path are replaced with `~`. + * - Absolute paths not starting with the user's home path are returned unchanged. + * - Relative paths are prefixed with `~/`. + * - Other paths are returned unchanged. + * + * @param {string} fspath - The file system path to be converted. + * @returns {string} The privacy-aware path. + */ +window.privacy_aware_path = function(fspath){ + // e.g. /my_username/test.txt -> ~/test.txt + if(fspath.startsWith('~/')) + return fspath; + // e.g. /my_username/test.txt -> ~/test.txt + else if(fspath.startsWith(window.home_path)) + return fspath.replace(window.home_path, '~'); + // e.g. /other_username/test.txt -> /other_username/test.txt + else if(fspath.startsWith('/') && !fspath.startsWith(window.home_path)) + return fspath; + // e.g. test.txt -> ~/test.txt + else if(!fspath.startsWith('/')) + return '~/' + fspath; + // e.g. /username/path/to/item -> /username/path/to/item + else + return fspath; +} \ No newline at end of file