diff --git a/Makefile b/Makefile index ce25268..2778a73 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ EXT=dylib SERVER=plugin_manager.o ini.o http_server.o plugins/dictionary.o plugins/utils.o SERVERLIB=-lpthread -ldl #-lsocket -PLUGINS= dummy.$(EXT) fileman.$(EXT) pluginsman.$(EXT) +PLUGINS= dummy.$(EXT) fileman.$(EXT) pluginsman.$(EXT) wterm.$(EXT) PLUGINSDEP = plugins/plugin.o plugins/dbhelper.o plugins/dictionary.o plugins/utils.o plugins/list.o PLUGINLIBS = -lsqlite3 diff --git a/build/htdocs/index.html b/build/htdocs/index.html index 9be0adc..de4872c 100644 --- a/build/htdocs/index.html +++ b/build/htdocs/index.html @@ -1,12 +1,14 @@ - + + + diff --git a/build/htdocs/scripts/camviewer.js b/build/htdocs/scripts/camviewer.js index 8369770..be73550 100644 --- a/build/htdocs/scripts/camviewer.js +++ b/build/htdocs/scripts/camviewer.js @@ -1,3 +1,4 @@ + var picam_config = { name: 'picam_layout', toolbar:{ diff --git a/build/htdocs/scripts/sidebar.js b/build/htdocs/scripts/sidebar.js index e42cdf1..ef93fec 100644 --- a/build/htdocs/scripts/sidebar.js +++ b/build/htdocs/scripts/sidebar.js @@ -14,7 +14,8 @@ var sidebar_config = { text: 'Plugins', icon: 'fa-cogs' }, - { id: 'level-fman', text: 'File manager', icon: 'fa-folder-open' } + { id: 'level-fman', text: 'File manager', icon: 'fa-folder-open' }, + { id: 'level-wterm', text: 'Terminal', icon: 'fa-wrench' } ] }, { @@ -47,6 +48,9 @@ var sidebar_config = { case 'level-picam': w2ui.layout.content('main', w2ui.picam_layout); break; + case 'level-wterm': + w2ui.layout.content('main', w2ui.wterm_layout); + break; default: //do nothing w2ui.layout.content('main',"Empty page"); console.log('Event: ' + event.type + ' Target: ' + event.target); diff --git a/build/htdocs/scripts/wterm.js b/build/htdocs/scripts/wterm.js new file mode 100644 index 0000000..3dbfcbb --- /dev/null +++ b/build/htdocs/scripts/wterm.js @@ -0,0 +1,245 @@ +/*! terminal.js v2.0 | (c) 2014 Erik Österberg | https://github.com/eosterberg/terminaljs */ + +var Terminal = (function () { + // PROMPT_TYPE + var PROMPT_INPUT = 1, PROMPT_PASSWORD = 2, PROMPT_CONFIRM = 3 + + var fireCursorInterval = function (inputField, terminalObj) { + var cursor = terminalObj._cursor + setTimeout(function () { + if (inputField.parentElement && terminalObj._shouldBlinkCursor) { + cursor.style.visibility = cursor.style.visibility === 'visible' ? 'hidden' : 'visible' + fireCursorInterval(inputField, terminalObj) + } else { + cursor.style.visibility = 'visible' + } + }, 500) + } + + var firstPrompt = true; + promptInput = function (terminalObj, message, PROMPT_TYPE, callback) { + var shouldDisplayInput = (PROMPT_TYPE === PROMPT_INPUT) + var inputField = document.createElement('input') + + inputField.style.position = 'absolute' + inputField.style.zIndex = '-100' + inputField.style.outline = 'none' + inputField.style.border = 'none' + inputField.style.opacity = '0' + inputField.style.fontSize = '0.2em' + + terminalObj._inputLine.textContent = '' + terminalObj._input.style.display = 'block' + terminalObj.html.appendChild(inputField) + fireCursorInterval(inputField, terminalObj) + + if (message.length) terminalObj.msg(PROMPT_TYPE === PROMPT_CONFIRM ? message + ' (y/n)' : message) + + inputField.onblur = function () { + terminalObj._cursor.style.display = 'none' + } + + inputField.onfocus = function () { + inputField.value = terminalObj._inputLine.textContent + terminalObj._cursor.style.display = 'inline' + } + + terminalObj.html.onclick = function () { + inputField.focus() + } + + inputField.onkeydown = function (e) { + if (e.which === 37 || e.which === 39 || e.which === 38 || e.which === 40 || e.which === 9) { + e.preventDefault() + } else if (shouldDisplayInput && e.which !== 13) { + setTimeout(function () { + terminalObj._inputLine.textContent = inputField.value + }, 1) + } + } + inputField.onkeyup = function (e) { + if (PROMPT_TYPE === PROMPT_CONFIRM || e.which === 13) { + terminalObj._input.style.display = 'none' + var inputValue = inputField.value + if (shouldDisplayInput) terminalObj._print(message+inputValue,"wterm_input_div") + terminalObj.html.removeChild(inputField) + if (typeof(callback) === 'function') { + if (PROMPT_TYPE === PROMPT_CONFIRM) { + callback(inputValue.toUpperCase()[0] === 'Y' ? true : false) + } else callback(inputValue) + } + } + } + if (firstPrompt) { + firstPrompt = false + setTimeout(function () { inputField.focus() }, 50) + } else { + inputField.focus() + } + } + + var terminalBeep + + var TerminalConstructor = function (id) { + if (!terminalBeep) { + terminalBeep = document.createElement('audio') + var source = '' + source + 'ogg" type="audio/ogg">' + terminalBeep.volume = 0.05 + } + + this.html = document.createElement('div') + this.html.className = 'Terminal' + if (typeof(id) === 'string') { this.html.id = id } + + this._innerWindow = document.createElement('div') + this._output = document.createElement('p') + this._inputLine = document.createElement('span') //the span element where the users input is put + this._cursor = document.createElement('span') + this._input = document.createElement('p') //the full element administering the user input, including cursor + this._input.className = "wterm_input_p" + this._cursor.className = "wterm_cursor" + //this._output.className = "wterm_output_p" + this._input.appendChild(document.createElement('span')); + this._shouldBlinkCursor = true + + this.beep = function () { + terminalBeep.load() + terminalBeep.play() + } + this.msg = function (message) { + this._input.firstChild.textContent = message + } + this._print = function(msg,cls) + { + var newLine = document.createElement('div') + newLine.className = cls + newLine.textContent = msg + this._output.appendChild(newLine) + } + this.print = function (message) { + this._print(message,"wterm_output_div") + } + + this.input = function (message, callback) { + promptInput(this, message, PROMPT_INPUT, callback) + } + + this.password = function (message, callback) { + promptInput(this, message, PROMPT_PASSWORD, callback) + } + + this.confirm = function (message, callback) { + promptInput(this, message, PROMPT_CONFIRM, callback) + } + + this.clear = function () { + this._output.innerHTML = '' + } + + this.sleep = function (milliseconds, callback) { + setTimeout(callback, milliseconds) + } + + this.setTextSize = function (size) { + this._output.style.fontSize = size + this._input.style.fontSize = size + } + + this.setTextColor = function (col) { + this.html.style.color = col + this._cursor.style.background = col + } + + this.setBackgroundColor = function (col) { + this.html.style.background = col + } + + this.setWidth = function (width) { + this.html.style.width = width + } + + this.setHeight = function (height) { + this.html.style.height = height + } + + this.blinkingCursor = function (bool) { + bool = bool.toString().toUpperCase() + this._shouldBlinkCursor = (bool === 'TRUE' || bool === '1' || bool === 'YES') + } + + this._input.appendChild(this._inputLine) + this._input.appendChild(this._cursor) + this._innerWindow.appendChild(this._output) + this._innerWindow.appendChild(this._input) + this.html.appendChild(this._innerWindow) + + this.setBackgroundColor('black') + this.setTextColor('white') + this.setTextSize('1em') + this.setWidth('100%') + this.setHeight('100%') + + this.html.style.fontFamily = 'Monaco, Courier' + this.html.style.margin = '0' + this._innerWindow.style.padding = '10px' + this._input.style.margin = '0' + this._output.style.margin = '0' + this._cursor.style.background = '#00cc00' + this._cursor.innerHTML = 'C' //put something in the cursor.. + this._cursor.style.display = 'none' //then hide it + this._input.style.display = 'none' + } + + return TerminalConstructor +}()); +var wtermobj; + +var wterm_config = { + name: 'wterm_layout', + panels: [ + { + type: 'main', + style: 'padding: 0px;', + content: '
' + } + ], + onRefresh:function(event) + { + if($("#wterm_input") ) + { + wtermobj = new Terminal(); + wtermobj.setTextSize(11); + var nest_callback = function(data) + { + if(data.length>0) + { + //send to server + var webtty = new EventSource('/wterm?cmd='+data); + webtty.onmessage = function (e) { + wtermobj.print(e.data); + var par = $("#wterm"); + par.animate({ + scrollTop: par.get(0).scrollHeight + }, 0); + }; + webtty.onerror = function(e) + { + // finish the command + webtty.close(); + wtermobj.input("antd> ",nest_callback); + } + } + else + { + wtermobj.input("antd> ",nest_callback); + } + }; + $("#wterm").html(wtermobj.html); + $("#wterm").parent().css("overflow","hidden"); + $("#wterm").parent().css("background-color","black"); + wtermobj.input("antd> ",nest_callback); + } + } +} +$().w2layout(wterm_config); diff --git a/build/htdocs/style/site.css b/build/htdocs/style/site.css new file mode 100644 index 0000000..ba6325d --- /dev/null +++ b/build/htdocs/style/site.css @@ -0,0 +1,21 @@ +#wterm { + width:100%; + height: 100%; + background-color:black; + position:absolute; + overflow:auto; +} +.wterm_output_div{ + padding-left:15px; +} +.wterm_input_div +{ + color:#00cc00; +} +.wterm_input_p{ + color:#00cc00; +} +.wterm_cursor{ + color:#00cc00; + background-color:#00cc00; +} \ No newline at end of file diff --git a/build/httpd b/build/httpd index c679977..1cdc37f 100755 Binary files a/build/httpd and b/build/httpd differ diff --git a/build/plugins/dummy.dylib b/build/plugins/dummy.dylib index 9294138..6ac1b7d 100755 Binary files a/build/plugins/dummy.dylib and b/build/plugins/dummy.dylib differ diff --git a/build/plugins/fileman.dylib b/build/plugins/fileman.dylib index 8100897..846c316 100755 Binary files a/build/plugins/fileman.dylib and b/build/plugins/fileman.dylib differ diff --git a/build/plugins/pluginsman.dylib b/build/plugins/pluginsman.dylib index 1c53b48..208c682 100755 Binary files a/build/plugins/pluginsman.dylib and b/build/plugins/pluginsman.dylib differ diff --git a/build/plugins/wterm.dylib b/build/plugins/wterm.dylib new file mode 100755 index 0000000..b534109 Binary files /dev/null and b/build/plugins/wterm.dylib differ diff --git a/plugins/wterm/wterm.c b/plugins/wterm/wterm.c new file mode 100644 index 0000000..2692e03 --- /dev/null +++ b/plugins/wterm/wterm.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include "../plugin.h" + +void init(); +call __init__ = init; + +void init() +{ + +} +void pexit() +{ + +} + +int read_buf(int fd, char*buf,int size) +{ + int i = 0; + char c = '\0'; + int n; + while ((i < size - 1) && (c != '\n')) + { + n = read(fd, &c, 1); + if (n > 0) + { + buf[i] = c; + i++; + } + else if(n == -1) return n; + else + c = '\n'; + } + buf[i] = '\0'; + return i; +} +void execute(int client, const char* m, dictionary rq) +{ + textstream(client); + int filedes[2]; + char* code = R_STR(rq, "cmd"); + if(!code) return; + if(pipe(filedes) == -1) + { + perror("pipe"); + return; + } + pid_t pid = fork(); + if(pid == -1) + { + perror("folk"); + return; + } else if(pid == 0) + { + while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {} + close(filedes[1]); + close(filedes[0]); + // executecomand + system(code); + //perror("execl"); + _exit(1); + } + close(filedes[1]); + char buffer[1024]; + while (1) { + ssize_t count = read_buf(filedes[0],buffer, sizeof(buffer)); + if (count == -1) { + if (errno == EINTR) { + continue; + } else { + perror("read"); + return; + } + } else if (count == 0) { + break; + } else { + __t(client,"data:%s\n",buffer); + //handle_child_process_output(buffer, count); + } + } + close(filedes[0]); + wait(0); + free(code); + printf("Child process exit\n"); +} \ No newline at end of file