From b8e642861102e46d75eb68103964a13bf9b0dd70 Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Mon, 18 Nov 2024 20:18:33 +0000 Subject: [PATCH] added httpfs [webrequest to filesystem] --- com/isoterminal.js | 1 + com/isoterminal/feat/9pfs_utils.js | 44 ++++++++++++++++++++++++++++++ com/isoterminal/feat/httpfs.js | 28 +++++++++++++++++++ com/isoterminal/worker.js | 9 +++--- com/selfcontainer.js | 7 ++++- 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 com/isoterminal/feat/httpfs.js diff --git a/com/isoterminal.js b/com/isoterminal.js index 664d0db..a6a553f 100644 --- a/com/isoterminal.js +++ b/com/isoterminal.js @@ -205,6 +205,7 @@ if( typeof AFRAME != 'undefined '){ indexjs: "com/isoterminal/feat/index.js.js", autorestore: "com/isoterminal/feat/autorestore.js", pastedropFeat: "com/isoterminal/feat/pastedrop.js", + httpfs: "com/isoterminal/feat/httpfs.js", }) this.el.setAttribute("selfcontainer","") diff --git a/com/isoterminal/feat/9pfs_utils.js b/com/isoterminal/feat/9pfs_utils.js index a6fa3eb..e5c7e2a 100644 --- a/com/isoterminal/feat/9pfs_utils.js +++ b/com/isoterminal/feat/9pfs_utils.js @@ -49,3 +49,47 @@ emulator.fs9p.append_file = async function(file,data){ } +emulator.fs9p.read_file_world = async function(file){ + const p = this.SearchPath(file); + + if(p.id === -1) + { + return Promise.resolve(null); + } + + const inode = this.GetInode(p.id); + const perms = this.parseFilePermissions(inode.mode) + + if( !perms.world.read ){ + return Promise.resolve(null); + } + + return this.Read(p.id, 0, inode.size); +} + +emulator.fs9p.parseFilePermissions = function(permissionInt) { + // Convert the permission integer to octal + const octalPermissions = permissionInt.toString(8); + + // Extract the permission bits (last 3 digits in octal) + const permissionBits = octalPermissions.slice(-3); + + + function parsePermission(digit) { + const num = parseInt(digit, 10); + + return { + read: Boolean(num & 4), // 4 = read + write: Boolean(num & 2), // 2 = write + execute: Boolean(num & 1) // 1 = execute + }; + } + // Decode the permissions + const permissions = { + owner: parsePermission(permissionBits[0]), + group: parsePermission(permissionBits[1]), + world: parsePermission(permissionBits[2]), + }; + + return permissions; +} diff --git a/com/isoterminal/feat/httpfs.js b/com/isoterminal/feat/httpfs.js new file mode 100644 index 0000000..5455c48 --- /dev/null +++ b/com/isoterminal/feat/httpfs.js @@ -0,0 +1,28 @@ +if( typeof emulator != 'undefined' ){ + +}else{ + + ISOTerminal.addEventListener('ready', function(e){ + + // listen for http request to the filesystem ( file://host/path ) + xhook.before( (request,callback) => { + + if (request.url.match(/^file:\/\/xrsh\/mnt\/.*/) ){ + let response + let file = request.url.replace(/^file:\/\/xrsh\/mnt\//,'') + this.worker.read_file_world(file) + .then( (data) => { + response = new Response( new Blob( [data] ) ) // wrap Uint8Array into array + response.status = 200 + callback(response) + }) + .catch( (e) => { + response = new Response() + response.status = 404 + callback(response) + }) + } + }) + + }) +} diff --git a/com/isoterminal/worker.js b/com/isoterminal/worker.js index 05a4ed0..dbf1fd2 100644 --- a/com/isoterminal/worker.js +++ b/com/isoterminal/worker.js @@ -42,10 +42,11 @@ this.runISO = function(opts){ /* * forward events/functions so non-worker world can reach them */ - this.create_file = async function(){ return emulator.create_file.apply(emulator, arguments[0]) } - this.read_file = async function(){ return emulator.read_file.apply(emulator, arguments[0]) } - this.append_file = async function(){ emulator.fs9p.append_file.apply(emulator.fs9p, arguments[0]) } - this.update_file = async function(){ emulator.fs9p.update_file.apply(emulator.fs9p, arguments[0]) } + this.create_file = async function(){ return emulator.create_file.apply(emulator, arguments[0]) } + this.read_file = async function(){ return emulator.read_file.apply(emulator, arguments[0]) } + this.read_file_world = async function(){ return emulator.fs9p.read_file_world.apply(emulator.fs9p, arguments[0]) } + this.append_file = async function(){ emulator.fs9p.append_file.apply(emulator.fs9p, arguments[0]) } + this.update_file = async function(){ emulator.fs9p.update_file.apply(emulator.fs9p, arguments[0]) } // filename will be read from 9pfs: "/mnt/"+filename emulator.readFromPipe = function(filename,cb){ diff --git a/com/selfcontainer.js b/com/selfcontainer.js index 03558b9..5584c7a 100644 --- a/com/selfcontainer.js +++ b/com/selfcontainer.js @@ -37,13 +37,18 @@ AFRAME.registerComponent('selfcontainer', { // selfcontain every webrequest to store (and serve if stored) let curry = function(me){ return function(request, response, cb){ + let data = request ? window.store[ request.url ] || false : false if( data ){ // return inline version - console.log('selfcontained cache: '+request.url) + console.log('selfcontainer.js: serving '+request.url+' from cache') let res = new Response() res[ data.binary ? 'data' : 'text' ] = data.binary ? () => me.convert.base64ToArrayBuffer(data.text) : data.text cb(res) }else{ + + if( request.url.match(/(^file:\/\/xrsh)/) ) return cb(response) + + console.log("selfcontainer.js: caching "+request.url) if( response.text ){ data = {text: response.text} }else{