2014-08-14 09:35:37 -07:00
var _ = require ( "lodash" ) ;
2016-06-12 02:44:28 +01:00
var pkg = require ( "../package.json" ) ;
2014-10-03 02:57:35 -07:00
var bcrypt = require ( "bcrypt-nodejs" ) ;
2014-08-14 09:35:37 -07:00
var Client = require ( "./client" ) ;
var ClientManager = require ( "./clientManager" ) ;
2014-09-26 15:12:53 -07:00
var express = require ( "express" ) ;
2014-08-14 09:35:37 -07:00
var fs = require ( "fs" ) ;
var io = require ( "socket.io" ) ;
2016-04-03 01:12:49 -04:00
var dns = require ( "dns" ) ;
2014-09-13 14:23:17 +02:00
var Helper = require ( "./helper" ) ;
2014-08-14 09:35:37 -07:00
2016-04-26 16:41:08 -04:00
var manager = null ;
2014-08-14 09:35:37 -07:00
2016-06-08 12:26:24 +03:00
module . exports = function ( ) {
2016-04-26 16:41:08 -04:00
manager = new ClientManager ( ) ;
2014-08-14 09:35:37 -07:00
2014-09-26 15:12:53 -07:00
var app = express ( )
2016-05-01 20:27:10 +03:00
. use ( allRequests )
2014-08-14 09:35:37 -07:00
. use ( index )
2014-10-03 16:33:44 -07:00
. use ( express . static ( "client" ) ) ;
2014-11-01 22:06:01 +02:00
2016-06-08 12:26:24 +03:00
var config = Helper . config ;
2014-09-26 16:26:21 -07:00
var server = null ;
2016-06-08 12:26:24 +03:00
if ( ! config . https . enable ) {
2014-09-26 16:26:21 -07:00
server = require ( "http" ) ;
2016-06-08 12:26:24 +03:00
server = server . createServer ( app ) . listen ( config . port , config . host ) ;
2014-09-26 16:26:21 -07:00
} else {
2016-03-09 14:04:05 +02:00
server = require ( "spdy" ) ;
2014-09-26 16:26:21 -07:00
server = server . createServer ( {
2016-06-08 12:26:24 +03:00
key : fs . readFileSync ( Helper . expandHome ( config . https . key ) ) ,
cert : fs . readFileSync ( Helper . expandHome ( config . https . certificate ) )
} , app ) . listen ( config . port , config . host ) ;
2014-09-26 16:26:21 -07:00
}
2016-06-08 12:26:24 +03:00
if ( config . identd . enable ) {
2016-04-26 16:53:29 -04:00
if ( manager . identHandler ) {
log . warn ( "Using both identd and oidentd at the same time!" ) ;
}
2014-10-11 19:33:28 +02:00
require ( "./identd" ) . start ( config . identd . port ) ;
2014-10-11 11:09:27 +01:00
}
2016-02-29 01:19:11 +00:00
var sockets = io ( server , {
2016-06-08 12:26:24 +03:00
transports : config . transports
2014-11-01 22:06:01 +02:00
} ) ;
2014-08-14 09:35:37 -07:00
sockets . on ( "connect" , function ( socket ) {
if ( config . public ) {
auth . call ( socket ) ;
} else {
init ( socket ) ;
}
} ) ;
2014-09-24 15:23:54 -07:00
manager . sockets = sockets ;
2016-06-08 12:26:24 +03:00
var protocol = config . https . enable ? "https" : "http" ;
log . info ( "The Lounge v" + pkg . version + " is now running on" , protocol + "://" + ( config . host || "*" ) + ":" + config . port + "/" , ( config . public ? "in public mode" : "in private mode" ) ) ;
2016-04-26 13:51:11 +03:00
log . info ( "Press ctrl-c to stop\n" ) ;
2014-08-14 09:35:37 -07:00
if ( ! config . public ) {
2014-09-24 15:23:54 -07:00
manager . loadUsers ( ) ;
if ( config . autoload ) {
manager . autoload ( ) ;
}
2014-08-14 09:35:37 -07:00
}
} ;
2016-04-03 01:12:49 -04:00
function getClientIp ( req ) {
2016-06-08 12:26:24 +03:00
if ( ! Helper . config . reverseProxy ) {
2016-04-03 01:12:49 -04:00
return req . connection . remoteAddress ;
} else {
return req . headers [ "x-forwarded-for" ] || req . connection . remoteAddress ;
}
}
2016-05-01 20:27:10 +03:00
function allRequests ( req , res , next ) {
res . setHeader ( "X-Content-Type-Options" , "nosniff" ) ;
return next ( ) ;
}
2014-08-14 09:35:37 -07:00
function index ( req , res , next ) {
2016-05-01 12:41:17 +03:00
if ( req . url . split ( "?" ) [ 0 ] !== "/" ) {
return next ( ) ;
}
2014-08-14 09:35:37 -07:00
return fs . readFile ( "client/index.html" , "utf-8" , function ( err , file ) {
var data = _ . merge (
2016-06-12 02:44:28 +01:00
pkg ,
2016-06-08 12:26:24 +03:00
Helper . config
2014-08-14 09:35:37 -07:00
) ;
2016-02-14 19:09:51 +02:00
var template = _ . template ( file ) ;
2016-05-01 20:27:10 +03:00
res . setHeader ( "Content-Security-Policy" , "default-src *; style-src * 'unsafe-inline'; script-src 'self'; child-src 'none'; object-src 'none'; form-action 'none'; referrer no-referrer;" ) ;
2014-09-13 05:54:17 +01:00
res . setHeader ( "Content-Type" , "text/html" ) ;
res . writeHead ( 200 ) ;
2016-02-14 19:09:51 +02:00
res . end ( template ( data ) ) ;
2014-08-14 09:35:37 -07:00
} ) ;
}
2016-06-01 00:28:31 +03:00
function init ( socket , client ) {
2014-08-14 09:35:37 -07:00
if ( ! client ) {
2016-06-01 00:02:10 +03:00
socket . emit ( "auth" , { success : true } ) ;
2014-08-14 09:35:37 -07:00
socket . on ( "auth" , auth ) ;
} else {
socket . on (
"input" ,
function ( data ) {
2014-09-09 12:31:23 -07:00
client . input ( data ) ;
2014-08-14 09:35:37 -07:00
}
) ;
socket . on (
2014-09-10 12:23:56 -07:00
"more" ,
2014-08-14 09:35:37 -07:00
function ( data ) {
2014-09-10 12:23:56 -07:00
client . more ( data ) ;
2014-08-14 09:35:37 -07:00
}
) ;
socket . on (
"conn" ,
function ( data ) {
2016-04-03 01:12:49 -04:00
// prevent people from overriding webirc settings
data . ip = null ;
data . hostname = null ;
2014-08-14 09:35:37 -07:00
client . connect ( data ) ;
}
) ;
2016-06-08 12:26:24 +03:00
if ( ! Helper . config . public ) {
2016-02-17 00:14:43 +00:00
socket . on (
"change-password" ,
function ( data ) {
var old = data . old _password ;
var p1 = data . new _password ;
var p2 = data . verify _password ;
if ( typeof p1 === "undefined" || p1 === "" ) {
socket . emit ( "change-password" , {
error : "Please enter a new password"
} ) ;
return ;
}
if ( p1 !== p2 ) {
socket . emit ( "change-password" , {
error : "Both new password fields must match"
} ) ;
return ;
}
if ( ! bcrypt . compareSync ( old || "" , client . config . password ) ) {
socket . emit ( "change-password" , {
error : "The current password field does not match your account password"
} ) ;
return ;
}
2016-06-01 00:28:31 +03:00
2016-02-17 00:14:43 +00:00
var salt = bcrypt . genSaltSync ( 8 ) ;
var hash = bcrypt . hashSync ( p1 , salt ) ;
2016-06-01 00:28:31 +03:00
client . setPassword ( hash , function ( success ) {
var obj = { } ;
if ( success ) {
obj . success = "Successfully updated your password, all your other sessions were logged out" ;
obj . token = client . config . token ;
} else {
obj . error = "Failed to update your password" ;
}
socket . emit ( "change-password" , obj ) ;
2016-02-17 00:14:43 +00:00
} ) ;
}
) ;
}
2014-09-21 09:46:43 -07:00
socket . on (
"open" ,
function ( data ) {
client . open ( data ) ;
}
2014-09-24 12:42:36 -07:00
) ;
socket . on (
"sort" ,
function ( data ) {
client . sort ( data ) ;
}
) ;
2016-02-16 21:29:44 -05:00
socket . on (
"names" ,
function ( data ) {
client . names ( data ) ;
}
) ;
2014-08-14 09:35:37 -07:00
socket . join ( client . id ) ;
socket . emit ( "init" , {
2014-09-21 09:46:43 -07:00
active : client . activeChannel ,
2014-09-15 14:13:03 -07:00
networks : client . networks ,
2016-06-30 15:06:07 +02:00
token : client . config . token || null
2014-08-14 09:35:37 -07:00
} ) ;
}
}
2016-06-01 00:28:31 +03:00
function reverseDnsLookup ( socket , client ) {
2016-04-03 01:12:49 -04:00
client . ip = getClientIp ( socket . request ) ;
dns . reverse ( client . ip , function ( err , host ) {
if ( ! err && host . length ) {
client . hostname = host [ 0 ] ;
} else {
client . hostname = client . ip ;
}
2016-06-01 00:28:31 +03:00
init ( socket , client ) ;
2016-04-03 01:12:49 -04:00
} ) ;
}
2014-08-14 09:35:37 -07:00
function auth ( data ) {
var socket = this ;
2016-06-08 12:26:24 +03:00
if ( Helper . config . public ) {
2016-02-29 01:19:11 +00:00
var client = new Client ( manager ) ;
2014-08-14 09:35:37 -07:00
manager . clients . push ( client ) ;
socket . on ( "disconnect" , function ( ) {
manager . clients = _ . without ( manager . clients , client ) ;
client . quit ( ) ;
} ) ;
2016-06-08 12:26:24 +03:00
if ( Helper . config . webirc ) {
2016-04-03 01:12:49 -04:00
reverseDnsLookup ( socket , client ) ;
} else {
init ( socket , client ) ;
}
2014-08-14 09:35:37 -07:00
} else {
2014-09-11 13:37:16 -07:00
var success = false ;
2014-08-14 09:35:37 -07:00
_ . each ( manager . clients , function ( client ) {
2014-09-15 14:13:03 -07:00
if ( data . token ) {
2016-06-01 00:28:31 +03:00
if ( data . token === client . config . token ) {
2014-09-15 14:13:03 -07:00
success = true ;
}
2015-10-01 00:39:57 +02:00
} else if ( client . config . user === data . user ) {
2014-09-14 12:13:34 -07:00
if ( bcrypt . compareSync ( data . password || "" , client . config . password ) ) {
2014-09-11 13:37:16 -07:00
success = true ;
}
2014-08-14 09:35:37 -07:00
}
2014-09-15 14:13:03 -07:00
if ( success ) {
2016-06-08 12:26:24 +03:00
if ( Helper . config . webirc !== null && ! client . config [ "ip" ] ) {
2016-06-01 00:28:31 +03:00
reverseDnsLookup ( socket , client ) ;
2016-04-03 01:12:49 -04:00
} else {
2016-06-01 00:28:31 +03:00
init ( socket , client ) ;
2016-04-03 01:12:49 -04:00
}
2014-09-16 10:42:49 -07:00
return false ;
2014-09-15 14:13:03 -07:00
}
2014-08-14 09:35:37 -07:00
} ) ;
if ( ! success ) {
2016-06-01 00:02:10 +03:00
socket . emit ( "auth" , { success : success } ) ;
2014-08-14 09:35:37 -07:00
}
}
}