├── 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 |
--------------------------------------------------------------------------------