mirror of
https://github.com/falk-werner/webfuse-provider
synced 2024-10-27 20:44:10 +00:00
refactored www
This commit is contained in:
parent
ef10bd7ace
commit
8e4d4868f4
@ -2,10 +2,12 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>LWS Example</title>
|
<title>LWS Example</title>
|
||||||
<meta charset='UTF-8' />
|
<meta charset='UTF-8' />
|
||||||
|
<script type='text/javascript' src='js/connection.js'></script>
|
||||||
|
<script type='text/javascript' src='js/connection_view.js'></script>
|
||||||
|
<script type='text/javascript' src='js/filesystem.js'></script>
|
||||||
|
<script type='text/javascript' src='js/filesystem_handler.js'></script>
|
||||||
|
<script type='text/javascript' src='js/startup.js'></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<textarea id='content'></textarea>
|
|
||||||
<input id='sendButton' type='button' value='send' />
|
|
||||||
<script nonce='42' type='text/javascript' src='script.js'></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
36
src/app/www/js/connection.js
Normal file
36
src/app/www/js/connection.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
class Connection {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.ws = null;
|
||||||
|
this.isConnected = false;
|
||||||
|
this.onopen = () => {};
|
||||||
|
this.onclose = () => {};
|
||||||
|
this.onmessage = () => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
connectTo(url) {
|
||||||
|
if (this.ws) { this.close(); }
|
||||||
|
|
||||||
|
this.ws = new WebSocket(url, 'fs');
|
||||||
|
this.ws.onopen = () => {
|
||||||
|
this.isConnected = true;
|
||||||
|
this.onopen()
|
||||||
|
};
|
||||||
|
this.ws.onclose = () => {
|
||||||
|
this.isConnected = false;
|
||||||
|
this.onclose();
|
||||||
|
};
|
||||||
|
this.ws.onmessage = (message) => {
|
||||||
|
this.onmessage(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
send(message) {
|
||||||
|
this.ws.send(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.ws.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
42
src/app/www/js/connection_view.js
Normal file
42
src/app/www/js/connection_view.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
class ConnectionView {
|
||||||
|
constructor(connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
this.connection.onclose = () => { this.onConnectionClosed(); };
|
||||||
|
this.connection.onopen = () => { this.onConnectionOpened(); };
|
||||||
|
|
||||||
|
this.element = document.createElement('div');
|
||||||
|
|
||||||
|
let urlLabel = document.createElement('span');
|
||||||
|
urlLabel.textContent = 'URL:';
|
||||||
|
this.element.appendChild(urlLabel);
|
||||||
|
|
||||||
|
this.urlTextbox = document.createElement('input');
|
||||||
|
this.urlTextbox.type = 'text';
|
||||||
|
this.urlTextbox.value = window.location.href.replace(/^http/, "ws");
|
||||||
|
this.element.appendChild(this.urlTextbox);
|
||||||
|
|
||||||
|
this.connectButton = document.createElement('input');
|
||||||
|
this.connectButton.type = 'button';
|
||||||
|
this.connectButton.value = 'connect';
|
||||||
|
this.connectButton.addEventListener('click', () => { this.onConnectButtonClicked(); });
|
||||||
|
this.element.appendChild(this.connectButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
onConnectButtonClicked() {
|
||||||
|
if (!this.connection.isConnected) {
|
||||||
|
let url = this.urlTextbox.value;
|
||||||
|
this.connection.connectTo(url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onConnectionOpened() {
|
||||||
|
this.connectButton.value = 'disconnect';
|
||||||
|
}
|
||||||
|
|
||||||
|
onConnectionClosed() {
|
||||||
|
this.connectButton.value = 'connect';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
98
src/app/www/js/filesystem.js
Normal file
98
src/app/www/js/filesystem.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
class FileSystem {
|
||||||
|
static get GOOD() { return 0; }
|
||||||
|
static get BAD() { return 1; }
|
||||||
|
|
||||||
|
static get BAD_NOTIMPLEMENTED() { return 2; }
|
||||||
|
static get BAD_TIMEOUT() { return 3; }
|
||||||
|
static get BAD_FORMAT() { return 4; }
|
||||||
|
|
||||||
|
static get BAD_NOENTRY() { return 101; }
|
||||||
|
static get BAD_NOACCESS() { return 102; }
|
||||||
|
|
||||||
|
static get O_ACCMODE() { return 0x003; }
|
||||||
|
static get O_RDONLY() { return 0x000; }
|
||||||
|
static get O_WRONLY() { return 0x001; }
|
||||||
|
static get O_RDWR() { return 0x002; }
|
||||||
|
static get O_CREAT() { return 0x040; }
|
||||||
|
static get O_EXCL() { return 0x080; }
|
||||||
|
static get O_TRUNK() { return 0x200; }
|
||||||
|
static get O_APPEND() { return 0x400; }
|
||||||
|
|
||||||
|
constructor(root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getEntry(path) {
|
||||||
|
let curItem = this.root;
|
||||||
|
|
||||||
|
for(let item of path.split('/')) {
|
||||||
|
if ('' !== item) {
|
||||||
|
curItem = curItem.entries && curItem.entries[item];
|
||||||
|
if (!curItem) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return curItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
getattr(path) {
|
||||||
|
let entry = this._getEntry(path);
|
||||||
|
if (entry) {
|
||||||
|
return {
|
||||||
|
mode: entry.mode || parseInt("755", 8),
|
||||||
|
type: entry.type || 'file',
|
||||||
|
size: entry.size || (entry.contents && entry.contents.length) || 0,
|
||||||
|
atime: entry.atime || 0,
|
||||||
|
mtime: entry.mtime || 0,
|
||||||
|
ctime: entry.ctime || 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return FilesSystem.BAD_NOENTRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readdir(path) {
|
||||||
|
let result = FileSystem.BAD_NOENTRY;
|
||||||
|
let entry = this._getEntry(path);
|
||||||
|
|
||||||
|
if ((entry) && ("dir" === entry.type)) {
|
||||||
|
result = [".", ".."];
|
||||||
|
for(let subdir of Object.keys(entry.entries)) {
|
||||||
|
result.push(subdir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
open(path, mode) {
|
||||||
|
let result = FileSystem.BAD_NOENTRY;
|
||||||
|
let entry = this._getEntry(path);
|
||||||
|
|
||||||
|
if (entry.type == "file") {
|
||||||
|
result = ((mode & FileSystem.O_ACCMODE) == FileSystem.O_RDONLY) ? true : FileSystem.BAD_NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(path, offset, length) {
|
||||||
|
let result = FileSystem.BAD_NOENTRY;
|
||||||
|
let entry = this._getEntry(path);
|
||||||
|
|
||||||
|
if (entry.type == "file") {
|
||||||
|
let end = Math.min(offset + length, entry.contents.length);
|
||||||
|
let data = (offset < entry.contents.length) ? entry.contents.substring(offset, end) : "";
|
||||||
|
result = {
|
||||||
|
data: data,
|
||||||
|
format: "identity",
|
||||||
|
count: data.length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
53
src/app/www/js/filesystem_handler.js
Normal file
53
src/app/www/js/filesystem_handler.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
class FileSystemHandler {
|
||||||
|
|
||||||
|
constructor(filesystem, connection) {
|
||||||
|
this._fs = filesystem;
|
||||||
|
this._connection = connection;
|
||||||
|
this._connection.onmessage = (message) => {
|
||||||
|
this._onmessage(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_onmessage(message) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
let request = JSON.parse(message.data);
|
||||||
|
let result = -42;
|
||||||
|
let response;
|
||||||
|
|
||||||
|
console.log(request);
|
||||||
|
if (("string" === typeof(request.method)) &&
|
||||||
|
("number" === typeof(request.id)) &&
|
||||||
|
(request.params)) {
|
||||||
|
switch(request.method)
|
||||||
|
{
|
||||||
|
case "getattr":
|
||||||
|
result = this._fs.getattr(request.params[0]);
|
||||||
|
break;
|
||||||
|
case "readdir":
|
||||||
|
result = this._fs.readdir(request.params[0]);
|
||||||
|
break;
|
||||||
|
case "open":
|
||||||
|
result = this._fs.open(request.params[0], request.params[1]);
|
||||||
|
break;
|
||||||
|
case "read":
|
||||||
|
result = this._fs.read(request.params[0], request.params[1], request.params[2]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("number" !== typeof(result)) {
|
||||||
|
response = {result: result, id: request.id};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
response = {error: {code: result}, id: request.id};
|
||||||
|
}
|
||||||
|
console.log(response);
|
||||||
|
this._connection.send(JSON.stringify(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex) { console.log(ex, message); }
|
||||||
|
};
|
||||||
|
}
|
61
src/app/www/js/startup.js
Normal file
61
src/app/www/js/startup.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
function onmessage(message) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
let request = JSON.parse(message.data);
|
||||||
|
let result = -42;
|
||||||
|
let response;
|
||||||
|
|
||||||
|
console.log(request);
|
||||||
|
if (("string" === typeof(request.method)) &&
|
||||||
|
("number" === typeof(request.id)) &&
|
||||||
|
(request.params)) {
|
||||||
|
switch(request.method)
|
||||||
|
{
|
||||||
|
case "getattr":
|
||||||
|
result = fs.getattr(request.params[0]);
|
||||||
|
break;
|
||||||
|
case "readdir":
|
||||||
|
result = fs.readdir(request.params[0]);
|
||||||
|
break;
|
||||||
|
case "open":
|
||||||
|
result = fs.open(request.params[0], request.params[1]);
|
||||||
|
break;
|
||||||
|
case "read":
|
||||||
|
result = fs.read(request.params[0], request.params[1], request.params[2]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("number" !== typeof(result)) {
|
||||||
|
response = {result: result, id: request.id};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
response = {error: {code: result}, id: request.id};
|
||||||
|
}
|
||||||
|
console.log(response);
|
||||||
|
ws.send(JSON.stringify(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex) { console.log(ex, message); }
|
||||||
|
};
|
||||||
|
|
||||||
|
function startup() {
|
||||||
|
let connection = new Connection();
|
||||||
|
let connectionView = new ConnectionView(connection);
|
||||||
|
let body = document.querySelector("body");
|
||||||
|
body.appendChild(connectionView.element);
|
||||||
|
|
||||||
|
let fs = new FileSystem({
|
||||||
|
mode: 0755,
|
||||||
|
type: "dir",
|
||||||
|
entries: {
|
||||||
|
"hello": { mode: 0755, type: "file", /* size: 10 , */contents: "Hello, World!"}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let handler = new FileSystemHandler(fs, connection);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = startup;
|
@ -1,172 +0,0 @@
|
|||||||
function startup()
|
|
||||||
{
|
|
||||||
var FileSystem = function(root) {
|
|
||||||
this.root = root;
|
|
||||||
};
|
|
||||||
|
|
||||||
FileSystem.GOOD = 0;
|
|
||||||
FileSystem.BAD = 1;
|
|
||||||
|
|
||||||
FileSystem.BAD_NOTIMPLEMENTED = 2;
|
|
||||||
FileSystem.BAD_TIMEOUT = 3;
|
|
||||||
FileSystem.BAD_FORMAT = 4;
|
|
||||||
|
|
||||||
FileSystem.BAD_NOENTRY = 101;
|
|
||||||
FileSystem.BAD_NOACCESS = 102;
|
|
||||||
|
|
||||||
FileSystem.O_ACCMODE = 00003;
|
|
||||||
FileSystem.O_RDONLY = 00000;
|
|
||||||
FileSystem.O_WRONLY = 00001;
|
|
||||||
FileSystem.O_RDWR = 00002;
|
|
||||||
FileSystem.O_CREAT = 00100;
|
|
||||||
FileSystem.O_EXCL = 00200;
|
|
||||||
FileSystem.O_TRUNK = 01000;
|
|
||||||
FileSystem.O_APPEND = 02000;
|
|
||||||
|
|
||||||
|
|
||||||
FileSystem.prototype.getEntry = function(path) {
|
|
||||||
var items = path.split('/');
|
|
||||||
var curItem = this.root;
|
|
||||||
var item;
|
|
||||||
var i, len;
|
|
||||||
|
|
||||||
for(i = 0, len = items.length; curItem && (i < len); i++) {
|
|
||||||
item = items[i];
|
|
||||||
if ("" !== item) {
|
|
||||||
curItem = curItem.entries && curItem.entries[item];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return curItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileSystem.prototype.getattr = function(path) {
|
|
||||||
var entry = this.getEntry(path);
|
|
||||||
if (entry) {
|
|
||||||
return {
|
|
||||||
mode: entry.mode || 0755,
|
|
||||||
type: entry.type || 'file',
|
|
||||||
size: entry.size || (entry.contents && entry.contents.length) || 0,
|
|
||||||
atime: entry.atime || 0,
|
|
||||||
mtime: entry.mtime || 0,
|
|
||||||
ctime: entry.ctime || 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return FileSystem.BAD_NOENTRY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FileSystem.prototype.readdir = function(path) {
|
|
||||||
var result, entry, subdir, i, len;
|
|
||||||
|
|
||||||
entry = this.getEntry(path);
|
|
||||||
if ((entry) && (entry.type == "dir")) {
|
|
||||||
result = [".", ".."];
|
|
||||||
for(subdir in entry.entries) {
|
|
||||||
if (entry.entries.hasOwnProperty(subdir)) {
|
|
||||||
result.push(subdir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = FileSystem.BAD_NOENTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
FileSystem.prototype.open = function(path, mode) {
|
|
||||||
var result = FileSystem.BAD_NOENTRY;
|
|
||||||
var entry = this.getEntry(path);
|
|
||||||
|
|
||||||
if (entry.type == "file") {
|
|
||||||
result = ((mode & FileSystem.O_ACCMODE) == FileSystem.O_RDONLY) ? true : FileSystem.BAD_NOACCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
FileSystem.prototype.read = function(path, offset, length) {
|
|
||||||
var result = FileSystem.BAD_NOENTRY;
|
|
||||||
var entry = this.getEntry(path);
|
|
||||||
|
|
||||||
if (entry.type == "file") {
|
|
||||||
var end = Math.min(offset + length, entry.contents.length);
|
|
||||||
var data = (offset < entry.contents.length) ? entry.contents.substring(offset, end) : "";
|
|
||||||
result = {
|
|
||||||
data: data,
|
|
||||||
format: "identity",
|
|
||||||
count: data.length
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
var fs = new FileSystem({
|
|
||||||
mode: 0755,
|
|
||||||
type: "dir",
|
|
||||||
entries: {
|
|
||||||
"hello": { mode: 0755, type: "file", /* size: 10 , */contents: "Hello, World!"}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var ws = new WebSocket('ws://localhost:4711/', 'fs');
|
|
||||||
ws.onopen = function() {
|
|
||||||
console.log('open');
|
|
||||||
};
|
|
||||||
ws.onclose = function() {
|
|
||||||
console.log('close');
|
|
||||||
};
|
|
||||||
ws.onmessage = function(message) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
var request = JSON.parse(message.data);
|
|
||||||
var result = -42;
|
|
||||||
var response;
|
|
||||||
|
|
||||||
console.log(request);
|
|
||||||
if (("string" === typeof(request.method)) &&
|
|
||||||
("number" === typeof(request.id)) &&
|
|
||||||
(request.params)) {
|
|
||||||
switch(request.method)
|
|
||||||
{
|
|
||||||
case "getattr":
|
|
||||||
result = fs.getattr(request.params[0]);
|
|
||||||
break;
|
|
||||||
case "readdir":
|
|
||||||
result = fs.readdir(request.params[0]);
|
|
||||||
break;
|
|
||||||
case "open":
|
|
||||||
result = fs.open(request.params[0], request.params[1]);
|
|
||||||
break;
|
|
||||||
case "read":
|
|
||||||
result = fs.read(request.params[0], request.params[1], request.params[2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("number" !== typeof(result)) {
|
|
||||||
response = {result: result, id: request.id};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
response = {error: {code: result}, id: request.id};
|
|
||||||
}
|
|
||||||
console.log(response);
|
|
||||||
ws.send(JSON.stringify(response));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ex) { console.log(ex, message); }
|
|
||||||
};
|
|
||||||
|
|
||||||
var sendButton = document.getElementById('sendButton');
|
|
||||||
sendButton.addEventListener('click', function() {
|
|
||||||
var content = document.getElementById('content').value;
|
|
||||||
ws.send(content);
|
|
||||||
console.log(content);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
document.onload=startup();
|
|
Loading…
Reference in New Issue
Block a user