├── README.md ├── bin └── run ├── lib ├── textareaserver.coffee └── textareaserver.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | TextareaServer is a backend of [TextareaConnect][]. 2 | 3 | # NOTE 4 | 5 | Due to updates in both Chrome and Node.js TextareaConnect/Server is currently broken. 6 | Also I'm currently bit busy with my other projects so this will have to wait for now. 7 | Pull requests are very welcome thou! 8 | 9 | # Installing 10 | 11 | TextareaServer runs on [Node.js][] v0.4 (or higher) and is installable using 12 | [npm][]. 13 | 14 | In Ubuntu you can get all the building dependecies for Node.js and its 15 | extensions using apt-get (npm will automatically install and compile all the 16 | extensions). 17 | 18 | sudo apt-get install build-essential libssl-dev 19 | 20 | More detailed Node.js & npm install instructions can be found from the [Node.js 21 | wiki](https://github.com/ry/node/wiki/Installation) 22 | 23 | Then just install TextareaServer using npm: 24 | 25 | npm install textareaserver 26 | 27 | And start it by entering commmand: 28 | 29 | textareaserver --editor-cmd gedit 30 | 31 | Please report possible issues to [TextareaConnect tracker][]. 32 | 33 | [Node.js]: http://nodejs.org/ 34 | [npm]: http://npmjs.org/ 35 | [TextareaConnect]: https://github.com/epeli/TextareaConnect 36 | [TextareaConnect tracker]: https://github.com/epeli/TextareaConnect/issues 37 | -------------------------------------------------------------------------------- /bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require("textareaserver").run(); 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lib/textareaserver.coffee: -------------------------------------------------------------------------------- 1 | 2 | http = require "http" 3 | exec = require('child_process').exec 4 | fs = require "fs" 5 | path = require "path" 6 | 7 | 8 | io = require "socket.io" 9 | cli = require( "cli") 10 | Inotify = require('inotify').Inotify 11 | 12 | DIR = path.join process.env['HOME'], ".textareaserver" 13 | 14 | 15 | try 16 | stats = fs.realpathSync DIR 17 | catch error 18 | fs.mkdirSync DIR,0777 19 | 20 | for file in fs.readdirSync DIR 21 | fs.unlink path.join DIR, file 22 | 23 | 24 | 25 | 26 | cli.parse 27 | port: ['p', "Port to listen", "number", 32942 ] 28 | host: ['l', "Host to listen", "string", "127.0.0.1"] 29 | "editor-cmd": ['c', 'Editor to use. {file} will substituted with the file path. Use quotes.', 30 | "string", "gedit {file}"] 31 | 32 | 33 | 34 | inotify = new Inotify() 35 | server = http.createServer (req, res) -> 36 | res.writeHead(200, {'Content-Type': 'text/html'}) 37 | res.end('

Hello world

') 38 | 39 | socket = io.listen server, transports: ['websocket'] 40 | 41 | 42 | 43 | clients = {} 44 | 45 | 46 | 47 | cleanUuid = (uuid) -> 48 | # Make sure that there are no funny characters 49 | uuid.replace(/[^a-zA-Z0-9_\-]/g, "") 50 | 51 | inotify.addWatch 52 | path: DIR 53 | watch_for: Inotify.IN_CLOSE_WRITE 54 | callback: (event) -> 55 | fs.readFile (path.join DIR, event.name), (err, data) -> 56 | 57 | client = clients[event.name] 58 | 59 | if client 60 | msg = 61 | textarea: data.toString() 62 | uuid: event.name 63 | client.send JSON.stringify msg 64 | 65 | 66 | actions = 67 | 68 | delete: (client, msg) -> 69 | 70 | for uuid in msg.uuids 71 | delete clients[uuid] 72 | console.log path.join DIR, uuid 73 | fs.unlink path.join DIR, uuid 74 | 75 | 76 | socket.on 'connection', (client) -> 77 | client.on 'message', (msg) -> 78 | msg = JSON.parse msg 79 | 80 | 81 | action = actions[msg.action] 82 | if action 83 | action client, msg 84 | else 85 | console.log "Bad action " + msg.action 86 | 87 | client.on 'disconnect', -> 88 | console.log "browser disconnected" 89 | 90 | 91 | exports.run = -> 92 | 93 | cli.main (args, options) -> 94 | actions.open = (client, msg) -> 95 | 96 | clients[msg.uuid] = client 97 | 98 | file = path.join DIR, cleanUuid msg.uuid 99 | 100 | fs.writeFile file, msg.textarea, -> 101 | if msg.spawn 102 | 103 | fileRegx = /\{ *file *\}/ 104 | editorCmd = options["editor-cmd"] 105 | 106 | if !! editorCmd.match fileRegx 107 | cmd = editorCmd.replace(fileRegx, file) 108 | else 109 | cmd = "#{editorCmd.trim()} #{file}" 110 | 111 | console.log cmd 112 | 113 | editor = exec cmd 114 | 115 | 116 | 117 | try 118 | server.listen options.port, options.host 119 | console.log "TextareaServer is running at #{options.host}:#{options.port}" 120 | catch error 121 | console.log "Could not start the server: #{ error.message }" 122 | process.exit 1 123 | 124 | 125 | -------------------------------------------------------------------------------- /lib/textareaserver.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var DIR, Inotify, actions, cleanUuid, cli, clients, exec, file, fs, http, inotify, io, path, server, socket, stats, _i, _len, _ref; 3 | http = require("http"); 4 | exec = require('child_process').exec; 5 | fs = require("fs"); 6 | path = require("path"); 7 | io = require("socket.io"); 8 | cli = require("cli"); 9 | Inotify = require('inotify').Inotify; 10 | DIR = path.join(process.env['HOME'], ".textareaserver"); 11 | try { 12 | stats = fs.realpathSync(DIR); 13 | } catch (error) { 14 | fs.mkdirSync(DIR, 0777); 15 | } 16 | _ref = fs.readdirSync(DIR); 17 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 18 | file = _ref[_i]; 19 | fs.unlink(path.join(DIR, file)); 20 | } 21 | cli.parse({ 22 | port: ['p', "Port to listen", "number", 32942], 23 | host: ['l', "Host to listen", "string", "127.0.0.1"], 24 | "editor-cmd": ['c', 'Editor to use. {file} will substituted with the file path. Use quotes.', "string", "gedit {file}"] 25 | }); 26 | inotify = new Inotify(); 27 | server = http.createServer(function(req, res) { 28 | res.writeHead(200, { 29 | 'Content-Type': 'text/html' 30 | }); 31 | return res.end('

Hello world

'); 32 | }); 33 | socket = io.listen(server, { 34 | transports: ['websocket'] 35 | }); 36 | clients = {}; 37 | cleanUuid = function(uuid) { 38 | return uuid.replace(/[^a-zA-Z0-9_\-]/g, ""); 39 | }; 40 | inotify.addWatch({ 41 | path: DIR, 42 | watch_for: Inotify.IN_CLOSE_WRITE, 43 | callback: function(event) { 44 | return fs.readFile(path.join(DIR, event.name), function(err, data) { 45 | var client, msg; 46 | client = clients[event.name]; 47 | if (client) { 48 | msg = { 49 | textarea: data.toString(), 50 | uuid: event.name 51 | }; 52 | return client.send(JSON.stringify(msg)); 53 | } 54 | }); 55 | } 56 | }); 57 | actions = { 58 | "delete": function(client, msg) { 59 | var uuid, _i, _len, _ref, _results; 60 | _ref = msg.uuids; 61 | _results = []; 62 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 63 | uuid = _ref[_i]; 64 | delete clients[uuid]; 65 | console.log(path.join(DIR, uuid)); 66 | _results.push(fs.unlink(path.join(DIR, uuid))); 67 | } 68 | return _results; 69 | } 70 | }; 71 | socket.on('connection', function(client) { 72 | client.on('message', function(msg) { 73 | var action; 74 | msg = JSON.parse(msg); 75 | action = actions[msg.action]; 76 | if (action) { 77 | return action(client, msg); 78 | } else { 79 | return console.log("Bad action " + msg.action); 80 | } 81 | }); 82 | return client.on('disconnect', function() { 83 | return console.log("browser disconnected"); 84 | }); 85 | }); 86 | exports.run = function() { 87 | return cli.main(function(args, options) { 88 | actions.open = function(client, msg) { 89 | clients[msg.uuid] = client; 90 | file = path.join(DIR, cleanUuid(msg.uuid)); 91 | return fs.writeFile(file, msg.textarea, function() { 92 | var cmd, editor, editorCmd, fileRegx; 93 | if (msg.spawn) { 94 | fileRegx = /\{ *file *\}/; 95 | editorCmd = options["editor-cmd"]; 96 | if (!!editorCmd.match(fileRegx)) { 97 | cmd = editorCmd.replace(fileRegx, file); 98 | } else { 99 | cmd = "" + (editorCmd.trim()) + " " + file; 100 | } 101 | console.log(cmd); 102 | return editor = exec(cmd); 103 | } 104 | }); 105 | }; 106 | try { 107 | server.listen(options.port, options.host); 108 | return console.log("TextareaServer is running at " + options.host + ":" + options.port); 109 | } catch (error) { 110 | console.log("Could not start the server: " + error.message); 111 | return process.exit(1); 112 | } 113 | }); 114 | }; 115 | }).call(this); 116 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "textareaserver" 3 | , "version": "0.1.3" 4 | , "author": "Esa-Matti Suuronen" 5 | , "bin": { 6 | "textareaserver": "./bin/run" 7 | } 8 | , "directories": { 9 | "lib" : "./lib" 10 | } 11 | , "main": "./lib/textareaserver" 12 | , "dependencies": { 13 | "socket.io": "" 14 | , "inotify": "" 15 | , "cli": "" 16 | } 17 | } 18 | 19 | --------------------------------------------------------------------------------