mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 18:55:26 +00:00
351 lines
11 KiB
JavaScript
351 lines
11 KiB
JavaScript
/* module make possible connectoin thru socket.io on a server */
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
var main = global.cloudcmd.main,
|
|
DIR = main.DIR,
|
|
SRVDIR = main.SRVDIR,
|
|
|
|
io = main.require('socket.io'),
|
|
update = main.srvrequire('update'),
|
|
|
|
exec = main.child_process.exec,
|
|
spawn = main.child_process.spawn,
|
|
|
|
Util = main.util,
|
|
path = main.path,
|
|
mainpackage = main.mainpackage,
|
|
equalPart = Util.isContainStrAtBegin,
|
|
CLOUDCMD = mainpackage.name,
|
|
ClientFuncs = [],
|
|
ClientDirs = [],
|
|
Clients = [],
|
|
INFO_LOG_LEVEL = 2,
|
|
ENV = process.env,
|
|
WIN32 = main.WIN32,
|
|
ConNum = 0,
|
|
HELP = {
|
|
stdout : CLOUDCMD + ' exit \n' +
|
|
CLOUDCMD + ' update \n',
|
|
},
|
|
|
|
/* windows commands thet require
|
|
* unicode charset on locales
|
|
* different then English
|
|
*/
|
|
Win32Commands = ['ASSOC', 'AT', 'ATTRIB', 'BREAK', 'CACLS', 'CALL',
|
|
'CD', 'CHCP', 'CHDIR', 'CHKDSK', 'CHKNTFS', 'CLS',
|
|
'CMD', 'COLOR', 'COMP', 'COMPACT', 'CONVERT', 'COPY',
|
|
'DATE', 'DEL', 'DIR', 'DISKCOMP', 'DISKCOPY', 'DOSKEY',
|
|
'ECHO', 'ENDLOCAL', 'ERASE', 'EXIT', 'FC', 'FIND',
|
|
'FINDSTR', 'FOR', 'FORMAT', 'FTYPE', 'GOTO', 'GRAFTABL',
|
|
'HELP', 'IF', 'LABEL', 'MD', 'MKDIR', 'MODE', 'MORE',
|
|
'MOVE', 'PATH', 'PAUSE', 'POPD', 'PRINT', 'PROMPT',
|
|
'PUSHD', 'RD', 'RECOVER', 'REM', 'REN', 'RENAME',
|
|
'REPLACE', 'RMDIR', 'SET', 'SETLOCAL', 'SHIFT', 'SORT',
|
|
'START', 'SUBST', 'TIME', 'TITLE', 'TREE', 'TYPE',
|
|
'VER', 'VERIFY', 'VOL', 'XCOPY'];
|
|
|
|
/**
|
|
* function listen on servers port
|
|
* @pServer {Object} started server object
|
|
*/
|
|
exports.listen = function(pServer) {
|
|
var ret;
|
|
|
|
if (io) {
|
|
io = io.listen(pServer);
|
|
|
|
io.set('log level', INFO_LOG_LEVEL);
|
|
|
|
/*
|
|
* on Win7 application is crashing,
|
|
* when options below is used.
|
|
*
|
|
* https://github.com/LearnBoost/socket.io/issues/1314
|
|
*
|
|
*/
|
|
if (!WIN32) {
|
|
io.enable('browser client minification');
|
|
io.enable('browser client gzip');
|
|
io.enable('browser client etag');
|
|
}
|
|
|
|
io.set('transports', [
|
|
'websocket',
|
|
'htmlfile',
|
|
'xhr-polling',
|
|
'jsonp-polling'
|
|
]);
|
|
|
|
ret = io.sockets.on('connection', onConnection);
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
function jsonSend(socket, json) {
|
|
var msg = Util.stringifyJSON(json);
|
|
socket.send(msg);
|
|
}
|
|
|
|
function onConnection(socket) {
|
|
var msg, onDisconect, onConnect;
|
|
|
|
++ConNum;
|
|
|
|
if (!Clients[ConNum]) {
|
|
msg = log(ConNum, 'connected\n');
|
|
|
|
jsonSend(socket, {
|
|
stdout : msg
|
|
});
|
|
|
|
Clients[ConNum] = true;
|
|
onConnect = onMessage(ConNum, function(json) {
|
|
jsonSend(socket, json);
|
|
});
|
|
onDisconect = Util.retFunc(disconnect, ConNum);
|
|
|
|
socket.on('message', onConnect);
|
|
socket.on('disconnect', function() {
|
|
socket.removeListener('message', onConnect);
|
|
socket.removeListener('disconnect', onDisconect);
|
|
});
|
|
} else {
|
|
msg = log(ConNum, ' in use. Reconnecting...');
|
|
|
|
jsonSend(socket, {
|
|
stdout: msg
|
|
});
|
|
|
|
socket.disconnect();
|
|
}
|
|
}
|
|
|
|
function disconnect(connNum) {
|
|
OnMessageFuncs [connNum] =
|
|
ClientFuncs [connNum] = null;
|
|
|
|
log(connNum, 'disconnected');
|
|
}
|
|
|
|
/**
|
|
* function gets onMessage function
|
|
* that execute needed command
|
|
*
|
|
* @param pConnNum
|
|
* @param callback
|
|
*/
|
|
function onMessage(pConnNum, callback) {
|
|
return function(pCommand) {
|
|
var lMsg, lWinCommand, lExec_func, firstChar,
|
|
connName,
|
|
lError, lRet, lExecSymbols, isContain,
|
|
dir, options = {};
|
|
|
|
dir = ClientDirs[pConnNum];
|
|
|
|
if (!dir)
|
|
dir = ClientDirs[pConnNum] = DIR;
|
|
|
|
connName = '#' + pConnNum + ': ';
|
|
Util.log(connName + pCommand);
|
|
|
|
if (equalPart(pCommand, CLOUDCMD))
|
|
lRet = onCloudCmd(pCommand, Util.retExec(callback, json));
|
|
else if (equalPart(pCommand, 'cd ')) {
|
|
lRet = true;
|
|
|
|
onCD(pCommand, dir, function(json) {
|
|
var error = json.stderr,
|
|
stdout = json.stdout;
|
|
|
|
if (error)
|
|
Util.exec(callback, json);
|
|
else
|
|
ClientDirs[pConnNum] = stdout;
|
|
});
|
|
}
|
|
|
|
if (!lRet) {
|
|
/* if we on windows and command is build in
|
|
* change code page to unicode becouse
|
|
* windows use unicode on non English versions
|
|
*/
|
|
if (WIN32) {
|
|
lWinCommand = pCommand.toUpperCase();
|
|
|
|
if (Win32Commands.indexOf(lWinCommand) >= 0)
|
|
pCommand = 'chcp 65001 |' + pCommand;
|
|
}
|
|
|
|
if (!ClientFuncs[pConnNum])
|
|
ClientFuncs[pConnNum] = getExec(function(json, pError, pStderr) {
|
|
log(pConnNum, pError, 'error');
|
|
log(pConnNum, pStderr, 'stderror');
|
|
|
|
Util.exec(callback, json);
|
|
});
|
|
|
|
lExec_func = ClientFuncs[pConnNum];
|
|
lExecSymbols = ['*', '&', '{', '}', '|', '\'', '"'];
|
|
isContain = Util.isContainStr(pCommand, lExecSymbols);
|
|
firstChar = pCommand[0];
|
|
options.cwd = dir;
|
|
|
|
if (firstChar === '#') {
|
|
pCommand = pCommand.slice(1);
|
|
pCommand = connName + pCommand;
|
|
pCommand = Util.addNewLine(pCommand);
|
|
|
|
lMsg = Util.stringifyJSON({
|
|
stdout: pCommand
|
|
});
|
|
|
|
io.sockets.emit('message', lMsg);
|
|
} else if (WIN32 || firstChar === ' ' || isContain)
|
|
exec(pCommand, options, lExec_func);
|
|
else
|
|
getSpawn(pCommand, options, Util.retExec(callback));
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
* function send result of command to client
|
|
* @param callback
|
|
*/
|
|
function getExec(callback) {
|
|
return function(pError, pStdout, pStderr) {
|
|
var lErrorStr, lExecStr, lExec,
|
|
lError = pStderr || pError;
|
|
|
|
if (lError) {
|
|
if (Util.isString(lError))
|
|
lErrorStr = lError;
|
|
else
|
|
lErrorStr = lError.toString();
|
|
|
|
lErrorStr = Util.addNewLine(lErrorStr);
|
|
}
|
|
|
|
lExec = {
|
|
stdout : pStdout,
|
|
stderr : lErrorStr || lError
|
|
};
|
|
|
|
Util.exec(callback, lExec, pError, pStderr);
|
|
};
|
|
}
|
|
|
|
function getSpawn(pCommand, options, callback) {
|
|
var send, cmd,
|
|
args = pCommand.split(' ');
|
|
|
|
pCommand = args.shift();
|
|
|
|
Util.tryCatchLog(function() {
|
|
cmd = spawn(pCommand, args, options);
|
|
});
|
|
|
|
if (cmd) {
|
|
send = function(error, data) {
|
|
var exec = {
|
|
stderr: error,
|
|
stdout: data
|
|
};
|
|
|
|
Util.exec(callback, exec);
|
|
};
|
|
|
|
cmd.stdout.on('data', function(data) {
|
|
send(null, data + '');
|
|
});
|
|
|
|
cmd.stderr.on('data', function(error) {
|
|
send(error + '', null);
|
|
});
|
|
|
|
cmd.on('error', Util.retFalse);
|
|
cmd.on('close', function (code) {
|
|
cmd = null;
|
|
});
|
|
}
|
|
}
|
|
|
|
function onCloudCmd(pCommand, callback) {
|
|
var lRet;
|
|
|
|
pCommand = Util.removeStr(pCommand, CLOUDCMD);
|
|
|
|
if (!equalPart(pCommand, ' ')) {
|
|
lRet = true;
|
|
Util.exec(callback, HELP);
|
|
}
|
|
else {
|
|
pCommand = Util.removeStr(pCommand, ' ');
|
|
|
|
if (equalPart(pCommand, 'update') && update) {
|
|
lRet = true;
|
|
update.get();
|
|
|
|
Util.exec(callback, {
|
|
stdout: Util.addNewLine('update: ok')
|
|
});
|
|
}
|
|
|
|
if (Util.strCmp(pCommand, 'exit'))
|
|
process.exit();
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
function onCD(pCommand, currDir, callback) {
|
|
var dir,
|
|
getDir = WIN32 ? 'chdir' : 'pwd',
|
|
paramDir = Util.removeStr(pCommand, 'cd ');
|
|
|
|
if (equalPart(paramDir, ['/', '~']))
|
|
dir = paramDir;
|
|
else
|
|
dir = path.join(currDir, paramDir);
|
|
|
|
exec('cd ' + dir + ' && ' + getDir, function (error, stdout, stderr) {
|
|
var lRet,
|
|
lMsg = '',
|
|
lError = error || stderr;
|
|
|
|
if (lError) {
|
|
lError = Util.stringifyJSON(lError);
|
|
lMsg = lError;
|
|
}
|
|
|
|
Util.exec(callback, {
|
|
stderr : lMsg,
|
|
stdout : Util.rmNewLine(stdout)
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
function log(pConnNum, pStr, pType) {
|
|
var lRet,
|
|
lType = ' ';
|
|
|
|
if (pStr) {
|
|
|
|
if (pType)
|
|
lType += pType + ':';
|
|
|
|
lRet = 'client #' + pConnNum + lType + pStr;
|
|
|
|
Util.log(lRet);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
})();
|