Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: subfolder path when exists #11

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
package-lock.json
165 changes: 107 additions & 58 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ if (SUBFOLDER != '/') {
//// Application Variables ////
var socketIO = require('socket.io');
var express = require('express');
var path_node = require('path');
var morgan = require('morgan');
var ejs = require('ejs');
var app = require('express')();
var http = require('http').Server(app);
var app = express();
var http = require('http').createServer(app);
var bodyParser = require('body-parser');
var baseRouter = express.Router();
var fsw = require('fs').promises;
Expand All @@ -27,34 +29,40 @@ var audioEnabled = true;
var PulseAudio = require('pulseaudio2');
var pulse = new PulseAudio();
pulse.on('error', function(error) {
console.log(error);
console.error("[kclient] pulse audio error: ", error);
audioEnabled = false;
console.log('Kclient was unable to init audio, it is possible your host lacks support!!!!');
console.log('[kclient] Kclient was unable to init audio, it is possible your host lacks support!!!!');
});

var port = 6900;

//// Server Paths Main ////
app.engine('html', require('ejs').renderFile);
app.engine('json', require('ejs').renderFile);
baseRouter.use('/public', express.static(__dirname + '/public'));
baseRouter.use('/vnc', express.static("/usr/share/kasmvnc/www/"));
baseRouter.get('/', function (req, res) {
res.render(__dirname + '/public/index.html', {title: TITLE, path: PATH});
var public_dir = path_node.join(__dirname, 'public');

app.engine('html', ejs.renderFile);
app.engine('json', ejs.renderFile);
app.use(morgan('combined'));

//// Routes ////
baseRouter.get('/ping', function (req, res) {
res.send("pong");
});
baseRouter.get('/favicon.ico', function (req, res) {
res.sendFile(__dirname + '/public/favicon.ico');
res.sendFile(path_node.join(public_dir, 'favicon.ico'));
});
baseRouter.get('/', function (req, res) {
res.render(path_node.join(public_dir, 'index.html'), {title: TITLE, path: PATH, path_prefix: SUBFOLDER});
});
baseRouter.get('/manifest.json', function (req, res) {
res.render(__dirname + '/public/manifest.json', {title: TITLE});
res.render(path_node.join(public_dir, 'manifest.json'), {title: TITLE, path_prefix: SUBFOLDER});
});

//// Web File Browser ////
// Send landing page
baseRouter.get('/files', function (req, res) {
res.sendFile( __dirname + '/public/filebrowser.html');
res.render(path_node.join(public_dir, 'filebrowser.html'), {path_prefix: SUBFOLDER});
});

app.use(SUBFOLDER, baseRouter);

// Websocket comms //
io = socketIO(http, {path: SUBFOLDER + 'files/socket.io',maxHttpBufferSize: 200000000});
var io = socketIO(http, {path: SUBFOLDER + 'files/socket.io', maxHttpBufferSize: 200000000});
io.on('connection', async function (socket) {
let id = socket.id;

Expand All @@ -72,69 +80,90 @@ io.on('connection', async function (socket) {

// Get file list for directory
async function getFiles(directory) {
try {
let items = await fsw.readdir(directory);
if (items.length > 0) {
let dirs = [];
let files = [];
for await (let item of items) {
let fullPath = directory + '/' + item;
if (fs.lstatSync(fullPath).isDirectory()) {
dirs.push(item);
} else {
files.push(item);
try {
if (fs.existsSync(directory)) {
let items = await fsw.readdir(directory);
if (items.length > 0) {
let dirs = [];
let files = [];
for await (let item of items) {
let fullPath = directory + '/' + item;
if (fs.lstatSync(fullPath).isDirectory()) {
dirs.push(item);
} else {
files.push(item);
}
}
send('renderfiles', [dirs, files, directory]);
} else {
send('renderfiles', [[], [], directory]);
}
send('renderfiles', [dirs, files, directory]);
} else {
send('renderfiles', [[], [], directory]);
}
} catch (error) {
console.error("[kclient] getFiles error: ", error);
send('renderfiles', [[], [], directory]);
}
}

// Send file to client
async function downloadFile(file) {
let fileName = file.split('/').slice(-1)[0];
let data = await fsw.readFile(file);
send('sendfile', [data, fileName]);
try {
let fileName = file.split('/').slice(-1)[0];
let data = await fsw.readFile(file);
send('sendfile', [data, fileName]);
} catch (error) {
console.error("[kclient] Error on downloadFile: ", error);
}
}

// Write client sent file
async function uploadFile(res) {
let directory = res[0];
let filePath = res[1];
let data = res[2];
let render = res[3];
let dirArr = filePath.split('/');
let folder = filePath.replace(dirArr[dirArr.length - 1], '')
await fsw.mkdir(folder, { recursive: true });
await fsw.writeFile(filePath, Buffer.from(data));
if (render) {
getFiles(directory);
try {
let directory = res[0];
let filePath = res[1];
let data = res[2];
let render = res[3];
let dirArr = filePath.split('/');
let folder = filePath.replace(dirArr[dirArr.length - 1], '')

await fsw.mkdir(folder, { recursive: true });
await fsw.writeFile(filePath, Buffer.from(data));

if (render) {
getFiles(directory);
}
} catch (error) {
console.error("[kclient] Error on uploadFile: ", error);
}
}

// Delete files
async function deleteFiles(res) {
let item = res[0];
let directory = res[1];
item = item.replace("|","'");
if (fs.lstatSync(item).isDirectory()) {
await fsw.rm(item, {recursive: true});
} else {
await fsw.unlink(item);
try {
let item = res[0];
let directory = res[1];
item = item.replace("|","'");
if (fs.lstatSync(item).isDirectory()) {
await fsw.rm(item, {recursive: true});
} else {
await fsw.unlink(item);
}
getFiles(directory);
} catch (error) {
console.error("[kclient] Error on deleteFiles: ", error);
}
getFiles(directory);
}

// Create a folder
async function createFolder(res) {
let dir = res[0];
let directory = res[1];
if (!fs.existsSync(dir)){
await fsw.mkdir(dir);
try {
await fsw.mkdir(dir, { recursive: true });
} catch (error) {
console.info("[kclient] Dir exists!");
}
getFiles(directory);
}
Expand All @@ -149,7 +178,7 @@ io.on('connection', async function (socket) {
});

//// PCM Audio Wrapper ////
aio = socketIO(http, {path: SUBFOLDER + 'audio/socket.io'});
var aio = socketIO(http, {path: SUBFOLDER + 'audio/socket.io'});
aio.on('connection', function (socket) {
var record;
let id = socket.id;
Expand All @@ -175,14 +204,19 @@ aio.on('connection', function (socket) {
}
}
function close() {
console.info('[kclient] audio socket closed.');
if (audioEnabled) {
if (record) record.end();
}
}

// Dump blobs to pulseaudio sink
async function micData(buffer) {
await fsw.writeFile('/defaults/mic.sock', buffer);
try {
await fsw.writeFile('/defaults/mic.sock', buffer);
} catch (error) {
console.error('[kclient] Error on micData: ' + error);
}
}

// Incoming socket requests
Expand All @@ -192,6 +226,21 @@ aio.on('connection', function (socket) {
socket.on('micdata', micData);
});

// Spin up application on 6900
app.use(SUBFOLDER, baseRouter);
http.listen(6900);
// Spin up application on port
http
.listen(port, function() {
console.log('[kclient] Listening on port ' + port);
})
.on('error', function(err) {
console.log('[kclient] Error on http server: ');
console.error(err);
});

process
.on('unhandledRejection', function (reason, p) {
console.error('[kclient] Unhandled Rejection at:', p, 'reason:', reason);
})
.on('uncaughtException', function (err) {
console.log('[kclient] Uncaught exception: ');
console.error(err.stack);
});
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
"dependencies": {
"ejs": "^3.1.8",
"express": "^4.18.2",
"morgan": "^1.10.0",
"pulseaudio2": "^0.5.5",
"socket.io": "^4.6.0"
"socket.io": "^4.8.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down
8 changes: 4 additions & 4 deletions public/filebrowser.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="public/css/filebrowser.css">
<script type="text/javascript" src="public/js/jquery.min.js"></script>
<script src="files/socket.io/socket.io.js"></script>
<script type="text/javascript" src="public/js/filebrowser.js"></script>
<link rel="stylesheet" href="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/css/filebrowser.css">
<script type="text/javascript" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/js/jquery.min.js"></script>
<script src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/js/socket.io.js"></script>
<script type="text/javascript" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/js/filebrowser.js"></script>
</head>
<body>
<span id="buttons">
Expand Down
22 changes: 11 additions & 11 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@
<title><%- title -%></title>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" href="icon.png">
<link rel="manifest" href="manifest.json" crossorigin="use-credentials">
<link href="public/css/kclient.css" rel="stylesheet">
<script src="audio/socket.io/socket.io.js"></script>
<link rel="apple-touch-icon" href="<% if(path_prefix){ %><%- path_prefix -%><% } %>icon.png">
<link rel="manifest" href="<% if(path_prefix){ %><%- path_prefix -%><% } %>manifest.json" crossorigin="use-credentials">
<link href="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/css/kclient.css" rel="stylesheet">
<script src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/js/socket.io.js"></script>
</head>
<body>
<!--KasmVNC Iframe-->
<iframe class="vnc" src="vnc/index.html?autoconnect=1&resize=remote&clipboard_up=true&clipboard_down=true&clipboard_seamless=true&show_control_bar=true<% if(path){ %><%- path -%><% } %>"></iframe>
<iframe class="vnc" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>vnc/index.html?autoconnect=1&resize=remote&clipboard_up=true&clipboard_down=true&clipboard_seamless=true&show_control_bar=true<% if(path){ %><%- path -%><% } %>"></iframe>
<!--LSIO Function Bar-->
<div id="lsbar">
<img class="icons" id="fileButton" title="File Manager" src="public/css/files.svg" onclick="toggle('#files')"/>
<img class="icons" id="audioButton" title="Enable Audio" src="public/css/speaker.svg" onclick="audio()"/>
<img class="icons" id="micButton" title="Enable Microphone" src="public/css/mic.svg" onclick="mic()"/>
<img class="icons" id="fileButton" title="File Manager" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/css/files.svg" onclick="toggle('#files')"/>
<img class="icons" id="audioButton" title="Enable Audio" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/css/speaker.svg" onclick="audio()"/>
<img class="icons" id="micButton" title="Enable Microphone" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/css/mic.svg" onclick="mic()"/>
</div>
<!--File Browser-->
<div id="files">
<iframe id="files_frame" name="files_frame" src="files" frameborder="0"></iframe>
<iframe id="files_frame" name="files_frame" src="<% if(path_prefix){ %><%- path_prefix -%><% } %>files" frameborder="0"></iframe>
<div class="close" onclick="closeToggle('#files')"></div>
</div>
<!--Main logic-->
<script src="public/js/jquery.min.js"></script>
<script src="public/js/kclient.js"></script>
<script src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/js/jquery.min.js"></script>
<script src="<% if(path_prefix){ %><%- path_prefix -%><% } %>public/js/kclient.js"></script>
</body>
</html>
Loading