fixed 0000001
[JIRC.git] / JIRC.js
1 #!/usr/bin/env node
2
3 //growl('5 new emails', { title: 'Email Client' });
4 //process.exit(0);
5 var argv = require('optimist').argv, bindhost="127.0.0.1", bindport="10080";
6 if(argv.h || argv.help){
7 console.log('usage: '+argv.$0+' [options] [bind-host]');
8 console.log('');
9 console.log('Options:');
10 console.log('-q be quiet');
11 console.log('-v verbose logging');
12 process.exit(0);
13 }
14 if(argv._[0]){
15 if(argv._[0].match(/^\d+\.\d+\.\d+\.\d+\:[0-9]{1,5}$/)){
16 bindhost=argv._[0].split(":")[0];
17 bindport=argv._[0].split(":")[1];
18 } else {
19 console.error('Error: bind-host must be in the format [IP]:[PORT]');
20 process.exit(0);
21 }
22 }
23
24 require('./lib/IRC.js');
25 global.argv=argv;
26 global.irc.loadScripts();
27 global.settings = '';
28 global.resume = '';
29
30 var pf = require('policyfile').createServer()
31 pf.listen(8002);
32
33 var http = require('http'),
34 WebSocketRequest = require('websocket').request,
35 ws = require('websocket-server'),
36 url = require('url'),
37 fs = require('fs'),
38 static = require('node-static'),
39 file = new(static.Server)('./public', { cache: 7200, headers: {'X-Hello':'World!'} }),
40 httpServer = http.createServer(function(request, response) {
41 var queryData = "";
42 request.on('data', function(data) {
43 var path = url.parse(request.url).pathname;
44 if(path=="/resume"){
45 queryData += data;
46 if(queryData.length > 1e6) {
47 queryData = "";
48 response.writeHead(413, {'Content-Type': 'text/plain'});
49 request.connection.destroy();
50 }
51 } else if(path=="/settings"){
52 queryData += data;
53 if(queryData.length > 1e6) {
54 queryData = "";
55 response.writeHead(413, {'Content-Type': 'text/plain'});
56 request.connection.destroy();
57 }
58 }
59 });
60
61 request.addListener('end', function () {
62 var path = url.parse(request.url).pathname;
63 if(path=="/emoticons"){
64 var emoticons = fs.readFileSync(
65 __dirname + '/public/images/emoticons/Emoticons.plist', 'utf8'
66 );
67 response.writeHead(200, {"Content-Type": "application/xml"});
68 response.end(emoticons);
69 } else if(path=="/resume"){
70 response.writeHead(200, {"Content-Type": "application/json"});
71 response.end(JSON.stringify(global.resume));
72 if(queryData) {
73 global.resume=JSON.parse(queryData);
74 }
75 } else if(path=="/settings"){
76 response.writeHead(200, {"Content-Type": "application/json"});
77 response.end(JSON.stringify(global.settings));
78 if(queryData) {
79 global.settings=JSON.parse(queryData);
80 }
81 } else{
82 file.serve(request, response, function (err, res) {
83 if (err) {
84 console.error((new Date()) + " > Error serving " + request.url + " - " + err.message);
85 response.writeHead(err.status, err.headers);
86 response.end();
87 } else {
88 if(argv.v) console.log((new Date()) + " > " + request.url + " - " + res.message);
89 }
90 });
91 }
92 });
93 });
94 httpServer.listen(bindport, bindhost, function() {
95 if(!argv.q) console.log((new Date()) + " Server is listening on " + bindhost + ":" + bindport);
96 });
97
98 // node-websocket-server
99 var miksagoConnection = require('./node_modules/websocket-server/lib/ws/connection');
100 var miksagoServer = ws.createServer();
101 miksagoServer.server = httpServer;
102 miksagoServer.addListener('connection', function(connection) {
103 connection.remoteAddress = connection._socket.remoteAddress;
104 connection.sendUTF = connection.send;
105 handleConnection(connection);
106 });
107
108
109 // WebSocket-Node config
110
111 var wsServerConfig = {
112 // All options *except* 'httpServer' are required when bypassing
113 // WebSocketServer.
114 maxReceivedFrameSize: 0x10000,
115 maxReceivedMessageSize: 0x100000,
116 fragmentOutgoingMessages: true,
117 fragmentationThreshold: 0x4000,
118 keepalive: true,
119 keepaliveInterval: 20000,
120 assembleFragments: true,
121 // autoAcceptConnections is not applicable when bypassing WebSocketServer
122 // autoAcceptConnections: false,
123 disableNagleAlgorithm: true,
124 closeTimeout: 5000
125 };
126
127 httpServer.on('upgrade', function(req, socket, head) {
128 if (typeof req.headers['sec-websocket-version'] !== 'undefined') {
129 // WebSocket hybi-08/-09/-10 connection (WebSocket-Node)
130 var wsRequest = new WebSocketRequest(socket, req, wsServerConfig);
131 try {
132 wsRequest.readHandshake();
133 var wsConnection = wsRequest.accept(wsRequest.requestedProtocols[0], wsRequest.origin);
134 handleConnection(wsConnection);
135 }
136 catch(e) {
137 console.log("WebSocket Request unsupported by WebSocket-Node: " + e.toString());
138 return;
139 }
140 } else {
141 // WebSocket hixie-75/-76/hybi-00 connection (node-websocket-server)
142 if (req.method === 'GET' &&
143 (req.headers.upgrade && req.headers.connection) &&
144 req.headers.upgrade.toLowerCase() === 'websocket' &&
145 req.headers.connection.toLowerCase() === 'upgrade') {
146 new miksagoConnection(miksagoServer.manager, miksagoServer.options, req, socket, head);
147 }
148 }
149 });
150
151 function handleConnection(connection) {
152 if(!argv.q) console.log((new Date()) + " Connection accepted.");
153 global.websocket = connection;
154 connection.addListener('message', function(wsMessage) {
155 var message = wsMessage;
156 // WebSocket-Node adds a "type", node-websocket-server does not
157 if (typeof wsMessage.type !== 'undefined') {
158 if (wsMessage.type !== 'utf8') {
159 return;
160 }
161 message = wsMessage.utf8Data;
162 }
163 // console.log("Received Message: " + message);
164 if (message.match(/^CONNECT (.*)$/i)) {
165 var arrCmd = message.split(" ");
166 global.irc.connect(arrCmd[1], arrCmd[2], arrCmd[3], arrCmd[4], arrCmd[5], arrCmd[6]);
167 } else{
168 global.irc.send(message);
169 }
170 });
171
172 connection.addListener('close', function() {
173 if(!argv.q) console.log((new Date()) + " Peer " + connection.remoteAddress + " disconnected.");
174 if(!global.resume || global.settings.hold != "on") {
175 global.irc.quit('BYE BYE');
176 if(!argv.q) console.log((new Date()) + " Disconnected from IRC");
177 }
178 });
179
180 }
181 if(!argv.n) require("openurl").open("http://" + bindhost + ":" + bindport);