From 3678f2ea8db0ec9c8a8975eea12f31fc3b309e77 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 28 Jan 2014 07:20:14 -0500 Subject: [PATCH] refactor(console) add --- lib/server.js | 5 +- lib/server/console.js | 324 +++++++++++++++++++++++++++++++++++++++++ lib/server/main.js | 1 + lib/server/socket.js | 328 ++++-------------------------------------- 4 files changed, 353 insertions(+), 305 deletions(-) create mode 100644 lib/server/console.js diff --git a/lib/server.js b/lib/server.js index 0c884b79..8f84bfd1 100644 --- a/lib/server.js +++ b/lib/server.js @@ -23,6 +23,7 @@ CloudFunc = main.cloudfunc, AppCache = main.appcache, Socket = main.socket, + Console = main.console, zlib = main.zlib, http = main.http, @@ -77,8 +78,10 @@ lSockets = function(pServer) { var lListen, msg, status; - if (lConfig.socket && Socket) + if (lConfig.socket && Socket) { lListen = Socket.listen(pServer); + Console.init(); + } status = lListen ? 'on' : 'off'; msg = CloudFunc.formatMsg('sockets', '', status); diff --git a/lib/server/console.js b/lib/server/console.js new file mode 100644 index 00000000..f9d97099 --- /dev/null +++ b/lib/server/console.js @@ -0,0 +1,324 @@ +/* module make possible connectoin thru socket.io on a server */ + +(function() { + 'use strict'; + + var main = global.cloudcmd.main, + DIR = main.DIR, + SRVDIR = main.SRVDIR, + + socket = main.socket, + 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.init = function() { + var ret; + + ret = socket.on('connection', function(clientSocket) { + onConnection(clientSocket, function(json) { + var msg = Util.stringifyJSON(json); + socket.send(msg, clientSocket); + }); + }); + + return ret; + }; + + function onConnection(clientSocket, callback) { + var msg, onDisconnect, onMessage; + + ++ConNum; + + if (!Clients[ConNum]) { + msg = log(ConNum, 'connected\n'); + + Util.exec(callback, { + stdout : msg + }); + + Clients[ConNum] = true; + + onMessage = getOnMessage(ConNum, callback); + onDisconnect = Util.retFunc(function(conNum) { + OnMessageFuncs [connNum] = + ClientFuncs [connNum] = null; + + log(connNum, 'disconnected'); + + socket.removeListener('message', onMessage, clientSocket); + socket.removeListener('disconnect', onDisconnect, clientSocket); + }, ConNum); + + socket.on('message', onMessage, clientSocket); + socket.on('disconnect', onDisconnect, clientSocket); + } else { + msg = log(ConNum, ' in use. Reconnecting...\n'); + + Util.exec(callback, { + stdout: msg + }); + + socket.disconnect(); + } + } + + /** + * function gets onMessage function + * that execute needed command + * + * @param pConnNum + * @param callback + */ + function getOnMessage(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, callback); + 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, 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, error, + args = pCommand.split(' '); + + pCommand = args.shift(); + + error = Util.tryCatchLog(function() { + cmd = spawn(pCommand, args, options); + }); + + if (!cmd) + send(error + '', null); + else { + 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; + } +})(); diff --git a/lib/server/main.js b/lib/server/main.js index b32542b0..da36bdc8 100644 --- a/lib/server/main.js +++ b/lib/server/main.js @@ -104,6 +104,7 @@ exports.cloudfunc = CloudFunc = librequire('cloudfunc'), exports.pipe = pipe = srvrequire('pipe'), exports.socket = srvrequire('socket'), + exports.console = srvrequire('console'), exports.express = srvrequire('express'), exports.auth = srvrequire('auth').auth, exports.appcache = srvrequire('appcache'), diff --git a/lib/server/socket.js b/lib/server/socket.js index a83f042c..d7ddc864 100644 --- a/lib/server/socket.js +++ b/lib/server/socket.js @@ -4,54 +4,39 @@ 'use strict'; var main = global.cloudcmd.main, - DIR = main.DIR, - SRVDIR = main.SRVDIR, - io = main.require('socket.io'), - update = main.srvrequire('update'), + CloudFunc = main.cloudfunc, - 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', - }, + INFO_LOG_LEVEL = 2, + AllListeners = []; + + exports.on = addListener; + exports.addListener = addListener; + exports.removeListener = removeListener; + exports.send = send; + exports.listen = listen; + + function addListener(name, func, socket) { + if (!socket) + socket = io.sockets; - /* 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']; + CloudFunc.addListener(name, func, AllListeners, socket); + } + + function removeListener(name, func, socket) { + CloudFunc.removeListener(name, func, AllListeners, socket); + } + + function send(msg, clientSocket) { + clientSocket.send(msg); + } /** * function listen on servers port * @pServer {Object} started server object */ - exports.listen = function(pServer) { + function listen(pServer) { var ret; if (io) { @@ -78,273 +63,8 @@ 'xhr-polling', 'jsonp-polling' ]); - - ret = io.sockets.on('connection', function(socket) { - onConnection(socket, function(json) { - var msg = Util.stringifyJSON(json); - socket.send(msg); - }); - }); } return ret; - }; - - function onConnection(socket, callback) { - var msg, onDisconnect, onMessage; - - ++ConNum; - - if (!Clients[ConNum]) { - msg = log(ConNum, 'connected\n'); - - Util.exec(callback, { - stdout : msg - }); - - Clients[ConNum] = true; - - onMessage = getOnMessage(ConNum, callback); - onDisconnect = Util.retFunc(function(conNum) { - OnMessageFuncs [connNum] = - ClientFuncs [connNum] = null; - - log(connNum, 'disconnected'); - - socket.removeListener('message', onMessage); - socket.removeListener('disconnect', onDisconnect); - }, ConNum); - - socket.on('message', onMessage); - socket.on('disconnect', onDisconnect); - } else { - msg = log(ConNum, ' in use. Reconnecting...\n'); - - Util.exec(callback, { - stdout: msg - }); - - socket.disconnect(); - } - } - - /** - * function gets onMessage function - * that execute needed command - * - * @param pConnNum - * @param callback - */ - function getOnMessage(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, callback); - 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, 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, error, - args = pCommand.split(' '); - - pCommand = args.shift(); - - error = Util.tryCatchLog(function() { - cmd = spawn(pCommand, args, options); - }); - - if (!cmd) - send(error + '', null); - else { - 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; } })();