· 8 years ago · Oct 29, 2017, 03:02 PM
1var server = require('http').createServer();
2var io = require('socket.io').listen('7979', { log: false }),
3 lobby = require('./lobby.js'),
4 worker = require("socket.io-client"), // here the client modul for connect to workplace-socket-server
5 workerTokken = 'nfof6g34n7m',
6 workerCount = 1,
7 fs = require('fs'),
8 mysql = require("mysql"),
9 squel = require("squel"),
10 vali = require('validator'),
11 striptags = require('striptags'),
12 ftpCon = require('jsftp'),
13 path = require('path'), // needed for ftp (remove not empty dir)
14 xhr = require('request'),
15 errFileName = 'error_dev';
16
17/** Server Settings */
18var errorLogger = {
19 enabled: false,
20 file: '/srv/wpo/errorlog/'+errFileName+'.log'
21};
22var lobbyOptions = {
23 memcache: {
24 port: 11211,
25 server: 'localhost'
26 },
27 lobbyOpt: {
28 debug: 3, // set 0 to show spamScores, set 1 to show child-stage-results, set 2 to show stage-result and 3 or true for show all logs
29 authCookieName: 'WPOCMS', // name of php session-cookie - remove this option to use default 'PHPSESSID'
30 allowProxy: false, // is this false we check the IP-V6 of user and this must are static!!!
31 removeInterval: 15, // check each x minutes have a user 0 connections then can be removed from the lobby (afk, idled users can be removed)
32 offMargin: 15, // in seconds a margin how the user has time for reconnect before send to the contactlis he is now offline
33 sockets: {'owp/dashboard/view': 'main', 'owp/mde/workplace': 'wp'}, // not defined referer will sorted to 'other' or remove this option to use on alle sites the same socket and unlimited connections
34 socketMaxCon: { 'main': 1, 'wp': 1, 'other': 0 }, // set allowed opened tabs by sockets {'main': 1, 'wp': 0, 'other': 0} (0 = unlimited) - if no sockets defined set value as int socketMaxCon: 5 or remove this option to use default (unlimited)
35 statusSync: ['main', 'wp'], // define the server who will sync the onlie-status
36 // socketFuncs: { }
37 },
38 antiSpamOpt: {
39 // no settings use default settings
40 }
41};
42var dbConnection = {'site': { // dont change the key`s!!!
43 host : "localhost",
44 user : "myuser",
45 password: "pass",
46 database : "db",
47 port : "3306"
48 },'wp': {
49 host : "localhost",
50 user : "myuser",
51 password: "pass",
52 database : "db",
53 port : "3306"
54}};
55
56function update_log( nerr )
57{
58 var executeErrLoop = setInterval(function(){
59 if( loggerBusy === false ){
60 loggerBusy = true;
61 fs.readFile(errorLogger.file, 'utf8', function(err, data){
62 if(err){
63 fs.writeFileSync(errorLogger.file, new Date().dateTime()+': '+nerr);
64 loggerBusy = false;
65 clearInterval(executeErrLoop);
66 }else{
67 var tmp = data+'\n'+new Date().dateTime()+': '+nerr;
68 fs.writeFileSync(errorLogger.file, tmp);
69 loggerBusy = false;
70 clearInterval(executeErrLoop);
71 }
72 });
73 }
74 }, 500);
75}
76
77/* Server dependencies. */
78var db, sdb;
79
80function connectSiteMysql( db_config ) {
81 db = mysql.createConnection(db_config); // Recreate the connection, since the old one cannot be reused.
82
83 db.connect(function(err) { // The server is either down
84 if(err) { // or restarting (takes a while sometimes).
85 console.log('Error connecting to site-DB:', err);
86 // setTimeout(connectSiteMysql, 1000); // We introduce a delay before attempting to reconnect,
87 } // to avoid a hot loop, and to allow our node script to
88 }); // process asynchronous requests in the meantime. If you're also serving http, display a 503 error.
89 db.on('error', function(err) {
90 console.log('db error', err);
91 if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually lost due to either server restart, or a connnection idle timeout (the wait_timeout server variable configures this)
92 connectSiteMysql(dbConnection['site']);
93 }else{
94 throw err;
95 }
96 });
97
98 db.config.queryFormat = function( query, values ){
99 if (!values) return query;
100 return query.replace(/\:(\w+)/g, function( txt, key )
101 {
102 var value = ( values.hasOwnProperty(key) ) ? values[key] : txt;
103 value = this.escape(value);
104
105 /** now defined filters used präfix f_ */
106 // stripe tags
107 if( typeof values['f_tags'] != 'undefined' )
108 {
109 value = striptags(value, values['f_tags']);
110 }
111 // console.log(value);
112 return value;
113 }.bind(this));
114 // console.log(query);
115 };
116}
117function connectWpMysql( db_config ) {
118 sdb = mysql.createConnection(db_config); // Recreate the connection, since the old one cannot be reused.
119
120 sdb.connect(function(err) { // The server is either down
121 if(err) { // or restarting (takes a while sometimes).
122 console.log('Error connecting to WP-DB:', err);
123 // setTimeout(connectWpMysql, 1000); // We introduce a delay before attempting to reconnect,
124 } // to avoid a hot loop, and to allow our node script to
125 }); // process asynchronous requests in the meantime. If you're also serving http, display a 503 error.
126 sdb.on('error', function(err) {
127 console.log('sdb error', err);
128 if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually lost due to either server restart, or a connnection idle timeout (the wait_timeout server variable configures this)
129 connectWpMysql(dbConnection['wp']);
130 }else{
131 throw err;
132 }
133 });
134
135 sdb.config.queryFormat = function( query, values ){
136 if (!values) return query;
137 return query.replace(/\:(\w+)/g, function( txt, key )
138 {
139 var value = ( values.hasOwnProperty(key) ) ? values[key] : txt;
140 value = this.escape(value);
141
142 /** now defined filters used präfix f_ */
143 // stripe tags
144 if( typeof values['f_tags'] != 'undefined' )
145 {
146 value = striptags(value, values['f_tags']);
147 }
148 // console.log(value);
149 return value;
150 }.bind(this));
151 // console.log(query);
152 };
153}
154
155if( typeof lobbyOptions != 'undefined' ){
156 Date.prototype.dateTime = function( output, utc ){
157 var string = ( typeof output != 'undefined' && output != '' ) ? output : "yyyy-mm-dd hh:mi:se";
158 var UTC = ( typeof utc != 'undefined' ) ? utc : true;
159 if( UTC === false )
160 {
161 var yyyy = this.getFullYear().toString();
162 var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
163 var dd = this.getDate().toString();
164 var hh = this.getHours().toString();
165 var mi = this.getMinutes().toString();
166 var se = this.getSeconds().toString();
167 }
168 else
169 {
170 var yyyy = this.getUTCFullYear().toString();
171 var mm = (this.getUTCMonth()+1).toString(); // getMonth() is zero-based
172 var dd = this.getUTCDate().toString();
173 var hh = this.getUTCHours().toString();
174 var mi = this.getUTCMinutes().toString();
175 var se = this.getUTCSeconds().toString();
176 }
177
178 return string.replace('yyyy', yyyy)
179 .replace('mm', (mm[1]?mm:"0"+mm[0]))
180 .replace('dd', (dd[1]?dd:"0"+dd[0]))
181 .replace('hh', (hh[1]?hh:"0"+hh[0]))
182 .replace('mi', (mi[1]?mi:"0"+mi[0]))
183 .replace('se', (se[1]?se:"0"+se[0]));
184 };
185 Object.prototype.extend = function( obj ){ for( var key in obj ){ this[key] = obj[key]; } };
186 String.prototype.replaceLast = function(find, replace) {
187 var index = this.lastIndexOf(find);
188
189 if (index >= 0) {
190 return this.substring(0, index) + replace + this.substring(index + find.length);
191 }
192
193 return this.toString();
194 };
195
196 // catch error`s
197 var loggerBusy = false;
198
199 if( errorLogger.enabled === true ){ process.on('uncaughtException', function( err ){ update_log(err); }); }
200
201 // db connections
202 connectSiteMysql(dbConnection['site']);
203 connectWpMysql(dbConnection['wp']);
204
205 // lobby init
206 var lobby = new lobby(lobbyOptions, sdb, io);
207}
208
209/** Server */
210var socket = io.listen(server);
211socket = socket.of('/global'); // set namespace
212socket.on('connection', function(client) // run server
213{
214/** connection handling */
215 lobby.onConnect(client); // add new socket to lobby, this will authorize with cookie/session-ID
216 client.on('reAuth', function(){ lobby.onConnect(client); }); // this for reAuth (if default auth failed will this be called)
217 client.on('disconnect', function(){ lobby.onDisconnect(client.uid, client.socketServer, client.id); });
218
219/** track each call of this user */
220 var fetchOn = client.on;
221 client.on = function( name, func ){
222 fetchOn.call(this, name, function() // var name can not be changed!!!
223 {
224 // var args = ( typeof arguments[0] != 'undefines' ) ? arguments[0] : arguments;
225 if( lobby.maxSpamCheck(name, ((lobby.asOpt.punishDublicates) === true ? JSON.stringify(arguments) : false), client.uid) === true ) // send the emit name then defined emits will not raise the spameScore
226 {
227 func.apply(this, arguments);
228 }
229 });
230 };
231
232/** communication with a workplace client */
233
234 // each emit need data.typ ('wp' or 'pr') and data.srv (the server ID) but not with onLoad
235 client.on('wp', function(data){
236 /*
237 * Wenn der AP geladen wird und ein reAuth ausgeführt wird, entsteht hier ein Fehler da die uid nicht vorhanden ist, also mit der if die Ausführung verhindern.
238 * Der AP verfügt über eine onReAuth Funktion welche ein emit sendet um den AP zu laden wenn reAuth abgeschlossen ist
239 */
240 if( typeof client.uid != 'undefined' ){ wpHandler(client.uid, data); }
241 });
242
243 function wpHandler(uid, data){
244 // get serverconnection and check access of each emit
245 switch( data.e ){
246 case 'onLoad':
247 loadWpConn( uid, data.wp, data.pr, data.active );
248 break;
249
250 case 'connectTo': // connect to a workplace or project
251 connectTo( data.typ, data.srvID, false );
252 break;
253
254 default:
255 if( typeof lobby.user[uid][data.typ+'s'][data.srv] != 'undefined' ) // check user has acces to this server
256 {
257 var connCreated = false;
258
259 // access is allowed but has no connection, create it
260 if( typeof lobby.user[uid][data.typ+'s'][data.srv]['c'] == 'undefined' ){
261 connCreated = connectTo( data.typ, data.srv, false );
262 }
263 else // has connection check is active
264 {
265 connCreated = true;
266 // reconnect if it needed
267 lobby.user[uid][data.typ+'s'][data.srv]['c'].raw("stat", function(err, data) {
268 if( err ){
269 // if( err.code == 530 ){
270 console.log('reconnect');
271 delete( lobby.user[uid][data.typ+'s'][data.srv]['c'] );
272 connCreated = connectTo( data.typ, data.srv, true );
273 // }else{
274 // console.log('no error');
275 // connCreated = true;
276 // }
277
278 console.log('---');
279 console.log(err.code);
280 console.log(data);
281
282 // console.log('error on get stat: ');
283 // console.log( err );
284 // console.log( err.code );
285 // console.log( data );
286
287 // console.log('---');
288 // console.log('reconnect needed:');
289 // lobby.user[uid][data.typ+'s'][data.srv]['c'].raw("rein", function(err, data) { if( err ){ console.log('REIN error: '); console.log( err ); }else{ console.log('re connected:'); } });
290 }
291 else{
292 // // if( data.code !== 211 ){
293 // // console.log('reconnect needed:');
294 // // lobby.user[uid][data.typ+'s'][data.srv]['c'].raw("rein", function(err, data) { if( err ){ console.log('REIN error: '); console.log( err ); }else{ console.log('re connected:'); } });
295 // // }else{
296 // // console.log('connection is active');
297 // // }
298 connCreated = true;
299 }
300 });
301 }
302
303 // loop and wait the server connection is established
304 var loopCnt = 0;
305 var executeComand = setInterval(function()
306 {
307 if( connCreated === true ){
308 clearInterval(executeComand);
309 console.log('execute command');
310
311 // has team-member only we must emit the changes to all online members
312 var sendTask = true;
313 var task = ( !sendTask ) ? false : {
314 aTyp: data.typ,
315 aID: data.srv
316 };
317
318 switch(data.e)
319 {
320 case 'md': // make dir
321 if( task !== false ){
322 task.item = ( data.path != '' ) ? idePrepId(data.path, 'dir_'+data.typ+data.srv) : data.typ+data.srv;
323 task.ir = ( data.path != '' ) ? 'n' : 'y'; // is root?
324 }
325 createDir( lobby.user[uid][data.typ+'s'][data.srv]['c'], data.path, data.newDir, task );
326 break;
327
328 case 'rd': // read dir
329 readDir( lobby.user[uid][data.typ+'s'][data.srv]['c'], data.path, false );
330 break;
331
332 case 'mf': // create a file
333 if( task !== false ){
334 task.item = ( data.path != '.' ) ? idePrepId(data.path, 'dir_'+data.typ+data.srv) : data.typ+data.srv;
335 task.ir = ( data.path != '.' ) ? 'n' : 'y'; // is root?
336 }
337 createFile( lobby.user[uid][data.typ+'s'][data.srv]['c'], data.path, data.file, task );
338 break;
339
340 case 'rf': // read a file
341 readFile( lobby.user[uid][data.typ+'s'][data.srv]['c'], data.file );
342 break;
343
344 case 'rem': // remove a dir or a file
345 if( task !== false ){
346 task.item = idePrepId(data.item, (( data.iTyp == 'f' ) ? 'file_' : 'dir_')+data.typ+data.srv);
347 }
348 removeItem( lobby.user[uid][data.typ+'s'][data.srv]['c'], data.item, data.iTyp, task );
349 break;
350
351 case 'ren': // rename
352 rename( lobby.user[uid][data.typ+'s'][data.srv]['c'], data.from, data.to, data.type, task );
353 break;
354 }
355 }
356
357 if( loopCnt == 500 ){ // connection can not established emit error
358 clearInterval(executeComand);
359
360 }
361 else{ loopCnt++; }
362 }, 50);
363 }
364 else
365 {
366 noAccessToServer( data.srv ); // emit: no access
367 }
368 break;
369 }
370 }
371
372 // load workplace`s datas from db and add to lobby
373 // WP + loadPR : is only for reconnect after server crash/restart to restore the active project
374 function loadWpConn( uid, loadThisWP, loadThisPR, active ){
375
376 if( typeof lobby.user[uid] != 'undefined' && typeof lobby.user[uid]['wps'] == 'undefined' )
377 {
378 sdb.query(
379 "SELECT * FROM workplaces WHERE uid = :id", {id: uid},
380 function( err, workplaces )
381 {
382 if( err ){ // error
383 console.log('SQL error on find WPs of user: '+ uid);
384 console.log( err );
385 }else if( workplaces.length == 0 ){ // empty
386 console.log('User ('+ uid +') has no WP!');
387 }else{
388 // add first datas to lobby
389 lobby.user[uid]['wps'] = {};
390 for( i in workplaces ){
391 if( workplaces.hasOwnProperty(i) ){
392 var wpID = workplaces[i]['id'];
393 lobby.user[uid]['wps'][wpID] = {};
394
395 lobby.user[uid]['wps'][wpID]['name'] = workplaces[i]['name'];
396 lobby.user[uid]['wps'][wpID]['srv'] = workplaces[i]['srv'];
397 lobby.user[uid]['wps'][wpID]['domain'] = workplaces[i]['domain'];
398 lobby.user[uid]['wps'][wpID]['typ'] = workplaces[i]['typ'];
399 lobby.user[uid]['wps'][wpID]['role'] = 'owner';
400 lobby.user[uid]['wps'][wpID]['access'] = {ftp: 0, db: 0, host: 0, ssh: 0}; // set all modules as disabled. Next query get connections and exist moduls will be enabled
401
402 // set the WP id to load it - has no private workplace we must check is at this time == false then we set the business wp to load
403 // or isset a WP then is reconnect and set the last active WP-ID
404 if( loadThisWP === false )
405 {
406 loadThisWP = wpID;
407 }
408 }
409 }
410
411 // load connection-datas of each own workplace
412 if( workplaces.length == 2 )
413 {
414 var connectQuery = 'oid = :id OR oid = :id2',
415 connectId = {typ: 'wp', id: workplaces[0]['id'], id2: workplaces[1]['id']},
416 ownWPs = [{id: workplaces[0]['id'], name: workplaces[0]['name']}, {id: workplaces[1]['id'], name: workplaces[1]['name']}];
417 }
418 else
419 {
420 var connectQuery = 'oid = :id',
421 connectId = {typ: 'wp', id: workplaces[0]['id']},
422 ownWPs = [{id: workplaces[0]['id'], name: workplaces[0]['name']}];
423 }
424
425 // add connection-datas to lobby
426 sdb.query(
427 "SELECT * FROM connect WHERE typ = :typ AND (" + connectQuery+")", connectId,
428 function( err, connections )
429 {
430 if( err ){ // error
431 console.log('SQL error on find connection data of user: '+ uid);
432 console.log( err );
433 }else if( connections.length == 0 ){ // empty
434 console.log('User ('+ uid +') no WP conection found!');
435 }else{
436
437 for( i in connections ){
438 if( connections.hasOwnProperty(i) ){
439 var conSrv = connections[i]['srv'],
440 conWP = connections[i]['oid'];
441
442 lobby.user[uid]['wps'][conWP][conSrv] = {};
443 lobby.user[uid]['wps'][conWP][conSrv]['dev'] = JSON.parse(connections[i]['dev']);
444 lobby.user[uid]['wps'][conWP][conSrv]['test'] = {}; // workplaces have this allways empty
445 lobby.user[uid]['wps'][conWP][conSrv]['live'] = {}; // workplaces have this allways empty
446
447 // switch acces from 0 to 1 if a connecetion (modul) allready exists
448 lobby.user[uid]['wps'][conWP]['access'][conSrv] = 1;
449 }
450 }
451
452 loadWP( uid, ownWPs, loadThisWP, loadThisPR, active );
453 }
454 }
455 );
456 }
457 }
458 );
459 }
460 else // user has page reload the socket session exist, use it!
461 {
462 var ownWPs = [];
463 for( i in lobby.user[uid]['wps'] ){
464 if( lobby.user[uid]['wps'].hasOwnProperty(i) && lobby.user[uid]['wps'][i]['own'] === true ){
465 ownWPs.push( {id: i, name: lobby.user[uid]['wps'][i]['name']} );
466 }
467 }
468 loadWP( uid, ownWPs, loadWP, false, false );
469 }
470 };
471
472 function idePrepId( id, pref )
473 {
474 var prefix = ( pref !== false ) ? pref : '';
475 var newId = prefix + id.replace(/\#/g, '_').replace(/\./g, '').replace(/\//g, '_').replace(/\\/g, '').replace(/\ /g, '').replace(/\(/g, '').replace(/\)/g, '');
476 return newId.replace(/_+/g, '_');
477 }
478
479 function loadWP( uid, ownWPs, loadWP, loadPR, active ){
480 var issetAcces = false, issetWP = false, issetPR = false;
481
482 // load own projects & access to other Projects and Workplaces
483 if( typeof lobby.user[uid]['prs'] == 'undefined' ){
484 lobby.user[uid]['prs'] = {};
485
486 // select own projects
487 sdb.query(
488 "SELECT id, name, typ FROM projects WHERE uid = :id", {id: uid},
489 function( err, projects )
490 {
491 if( err ){ // error
492 console.log('SQL error on find own projects of user: '+ uid);
493 console.log( err );
494 }else{
495 for( i in projects ){
496 if( projects.hasOwnProperty(i) ){
497 var wpID = projects[i]['id'];
498 lobby.user[uid]['prs'][wpID] = {};
499
500 lobby.user[uid]['prs'][wpID]['name'] = projects[i]['name'];
501 lobby.user[uid]['prs'][wpID]['typ'] = projects[i]['typ'];
502 lobby.user[uid]['prs'][wpID]['role'] = 'owner';
503 }
504 }
505 issetAcces = true;
506 }
507 }
508 );
509
510 // load access table for check access to stranger workspaces
511 sdb.query(
512 "SELECT `a`.*, `wp`.`name` FROM `access` AS `a` LEFT JOIN `workplaces` AS `wp` ON `wp`.`id` = `a`.`oid` WHERE `a`.`uid` = :id AND `a`.`typ` = :typ LIMIT 100", {id: uid, typ: 'wp'},
513 function( err, result )
514 {
515 if( err ){ // error
516 console.log('SQL error on find stranger workplaces for user: '+ uid);
517 console.log( err );
518 }else{
519 // console.log('find stranger wp');
520 // console.log(result);
521 for( i in result ){
522 if( result.hasOwnProperty(i) ){
523 var wpID = result[i]['oid'];
524 lobby.user[uid]['wps'][wpID] = {};
525
526 lobby.user[uid]['wps'][wpID]['name'] = result[i]['name'];
527 lobby.user[uid]['wps'][wpID]['role'] = result[i]['role'];
528 lobby.user[uid]['wps'][wpID]['rights'] = JSON.parse(result[i]['rights']);
529 lobby.user[uid]['wps'][wpID]['sort'] = result[i]['sort'];
530 lobby.user[uid]['wps'][wpID]['access'] = {
531 ftp: result[i]['ftp'],
532 db: result[i]['db'],
533 host: result[i]['host'],
534 ssh: result[i]['ssh']
535 };
536 }
537 }
538 issetWP = true;
539 }
540 }
541 );
542
543 // load access table for check access to stranger projects
544 sdb.query(
545 "SELECT `a`.*, `pr`.`name` FROM `access` AS `a` LEFT JOIN `projects` AS `pr` ON `pr`.`id` = `a`.`oid` WHERE `a`.`uid` = :id AND `a`.`typ` = :typ LIMIT 100", {id: uid, typ: 'pr'},
546 function( err, result )
547 {
548 if( err ){ // error
549 console.log('SQL error on find stranger projects for user: '+ uid);
550 console.log( err );
551 }else{
552 for( i in result ){
553 if( result.hasOwnProperty(i) ){
554 var prID = result[i]['oid'];
555 lobby.user[uid]['prs'][prID] = {};
556
557 lobby.user[uid]['prs'][prID]['name'] = result[i]['name'];
558 lobby.user[uid]['prs'][prID]['role'] = result[i]['role'];
559 lobby.user[uid]['prs'][prID]['rights'] = JSON.parse(result[i]['rights']);
560 lobby.user[uid]['prs'][prID]['sort'] = result[i]['sort'];
561 lobby.user[uid]['prs'][prID]['access'] = {
562 ftp: JSON.parse(result[i]['ftp']),
563 db: JSON.parse(result[i]['db']),
564 host: JSON.parse(result[i]['host']),
565 ssh: JSON.parse(result[i]['ssh'])
566 };
567 }
568 }
569 issetPR = true;
570 }
571 }
572 );
573 }
574 else{ issetAcces = true; issetWP = true; issetPR = true; }
575
576 // create a loop that wait of all DB-query`s. If we have all datas we execute the onLoad/reconnect process
577 var executeLoop = setInterval(function(){
578
579 if( issetAcces === true && issetWP === true && issetPR === true ){
580 clearInterval(executeLoop);
581
582 var emitWP = {},
583 emitPR = {};
584
585 // prepare the emit datas, we must remove server and conection datas
586 for( i in lobby.user[uid]['wps'] ){
587 if( lobby.user[uid]['wps'].hasOwnProperty(i) ){
588 var server = lobby.user[uid]['wps'][i];
589
590 emitWP[i] = {
591 name: server.name,
592 role: server.role,
593 typ: server.typ
594 };
595
596 if( server['role'] != 'owner' ){ emitWP[i]['sort'] = server['sort']; }
597 }
598 }
599 for( i in lobby.user[uid]['prs'] ){
600 if( lobby.user[uid]['prs'].hasOwnProperty(i) ){
601 var server = lobby.user[uid]['prs'][i];
602
603 emitPR[i] = {
604 name: server.name,
605 role: server.role,
606 typ: server.typ
607 };
608
609 if( server['role'] != 'owner' ){ emitPR[i]['sort'] = server['sort']; }
610 }
611 }
612
613 // send server datas to the client. The client send new emit to establish the connections
614 client.emit('wp', {e: 'setServers', wps: emitWP, prs: emitPR });
615 }
616 }, 500);
617 }
618
619 // create connection to a workplace or project
620 function connectTo( typ, srvID, reconnect ){
621 var uid = client.uid;
622 var srv = lobby.user[uid][typ+'s'][srvID],
623 srvDataExist = false, srvConDataExist = false,
624 access = {};
625
626 // es wird vorrausgesetzt das in der Lobby bereits ein Index an verfügbaren Projekten/Arbeitsplätzen besteht so dass wenn
627 // ein Projekt geladen wird das noch keine Verbindung hat erst auf Anfrage, dessen Serverdaten aus der db geladen werden.
628 // So muss die Lobby nicht jegliche Verbindungsdaten speichern und auf Grund des Indexes ist auch der Zugriff gewährleistet
629 if( typeof lobby.user[uid][typ+'s'][srvID] != 'undefined' && typeof lobby.user[uid][typ+'s'][srvID]['srv'] == 'undefined' )
630 {
631 // get connectiondatas
632 sdb.query(
633 "SELECT * FROM connect WHERE typ = :typ AND oid = :oid", {typ: typ, oid: srvID},
634 function( err, connections )
635 {
636 if( err ){ // error
637 console.log('SQL error on find connection data of ID: '+ uid);
638 console.log( err );
639 }else{
640 // get name and serverdatas
641 var table = ( typ == 'pr' ) ? 'projects' : 'workplaces';
642 sdb.query(
643 "SELECT srv, domain FROM "+table+" WHERE id = :id", {id: srvID},
644 function( err, srvData )
645 {
646 if( err ){ // error
647 console.log('SQL error on find srv & name of ID: '+ uid);
648 console.log( err );
649 }else{
650 lobby.user[uid][typ+'s'][srvID]['srv'] = srvData['srv'];
651 lobby.user[uid][typ+'s'][srvID]['domain'] = srvData['domain'];
652 srvDataExist = true;
653 }
654 }
655 );
656 for( i in connections ){
657 if( connections.hasOwnProperty(i) ){
658 var conSrv = connections[i]['srv'];
659
660 lobby.user[uid][typ+'s'][srvID][conSrv] = {};
661 lobby.user[uid][typ+'s'][srvID][conSrv]['dev'] = JSON.parse(connections[i]['dev']);
662
663 if( typ == 'pr' ){
664 lobby.user[uid][typ+'s'][srvID][conSrv]['test'] = JSON.parse(connections[i]['test']);
665 lobby.user[uid][typ+'s'][srvID][conSrv]['live'] = JSON.parse(connections[i]['live']);
666 }
667 }
668 }
669 srvConDataExist = true;
670 }
671 }
672 );
673 }
674 else if( typeof lobby.user[uid][typ+'s'][srvID] == 'undefined' )
675 {
676 noAccessToServer( srvID ); // emit has no access
677 return false; // go out of this function (exit)
678 }
679 else
680 {
681 srvDataExist = true;
682 srvConDataExist = true;
683 }
684
685 var executeConnection = setInterval(function(){
686
687 if( srvDataExist === true && srvConDataExist === true )
688 {
689 clearInterval(executeConnection);
690
691 lobby.user[uid][typ+'s'][srvID]['c'] = new ftpCon({
692 host: srv.srv,
693 port: srv.ftp.dev[0] // The port defaults to 21, but let's include it anyway.
694 });
695
696 lobby.user[uid][typ+'s'][srvID]['c'].on("error", function(err) {
697 client.emit('wp', {e: 'wpError', error: 'FTP'+error.code});
698 return false;
699 });
700
701 // First, we authenticate the user
702 lobby.user[uid][typ+'s'][srvID]['c'].auth(srv.ftp.dev[1], srv.ftp.dev[2], function(err, res) {
703 if( typeof err == 'undefined' ){
704 lobby.user[uid][typ+'s'][srvID]['c'].raw('cwd '+srv.ftp.dev[3]); // set homepath
705
706 // call the client server connection is established
707 if( reconnect === false ){
708 console.log('emit connected');
709 client.emit('wp', {e: 'connectedTo', srvID: srvID, typ: typ, rights: lobby.user[uid][typ+'s'][srvID]['rights'], access: lobby.user[uid][typ+'s'][srvID]['access'] }); }
710 }
711 else{
712 client.emit('wp', {e: 'wpError', error: typ+'Fail'});
713 delete lobby.user[uid][typ+'s'][srvID]['c'];
714 return false;
715 }
716 });
717 return true;
718 }
719 }, 500);
720 }
721
722 function noAccessToServer( srvID ){
723 client.emit('wp', {e: 'wpError', error: 'noSrvAccess', name: srvID});
724 }
725
726 // read a folder
727 function readDir( ftp, path, task ){
728 ftp.ls(path, function(err, res) {
729 if( err ){
730 console.log('error on read dir: ');
731 console.log( err );
732 client.emit('wp', {e: 'wpError', error: 'FTPrd'});
733 }else{
734 // emit to the initiator
735 // client.emit('wp', {e: 'addTree', tree: res});
736
737 // emit to online members
738 if( task !== false ){
739 // hier kommt noch ne foreach um jeden user durch zu laufen
740 client.emit('wp', {e: 'addTree', tree: res, task: task});
741 }
742 else{ // wenn foreach da ist die else löschen
743 client.emit('wp', {e: 'addTree', tree: res});
744 }
745 }
746 });
747 }
748
749 // create dir
750 function createDir( ftp, path, newDir, task ){
751 ftp.raw("mkd", path+newDir, function(err, data) {
752 if( err ){
753 client.emit('wp', {e: 'wpError', error: 'FTPmkd'+err.code});
754 }else{
755 client.emit('wp', {e: 'wpSuccess', msg: 'dc'});
756
757 readDir( ftp, ( path == '' ) ? '.' : path, task );
758 }
759 });
760 }
761
762 // create file
763 function createFile( ftp, path, newFile, task ){
764 ftp.put(new Buffer(''), path+newFile, function(hadError) {
765 if( hadError ){
766 client.emit('wp', {e: 'wpError', error: 'FTPcf', msg: hadError });
767 }else{
768 client.emit('wp', {e: 'wpSuccess', msg: 'fc'});
769
770 readDir( ftp, (path == '') ? '.' : path, task );
771 }
772 });
773 }
774
775 // read file
776 function readFile( ftp, file ){
777 ftp.get(file, function(err, socket) {
778
779 if( err ){
780 client.emit('wp', {e: 'wpError', error: 'FTPrf'});
781 }else{
782 socket.on("data", function(d) {
783 this.fileIsEmpty = false;
784 client.emit('wp', {e: 'rf', content: d.toString() });
785 });
786
787 socket.on("close", function(hadErr) {
788 // fallback is file empty
789 if( typeof this.fileIsEmpty === 'undefined' ){
790 client.emit('wp', {e: 'rf', content: '' });
791 delete(this.fileIsEmpty);
792 }
793
794 if( hadErr ){ client.emit('wp', {e: 'wpError', error: 'FTPf'}); }
795 });
796 socket.resume();
797 }
798 });
799 }
800
801 // rename
802 function rename( ftp, from, to, type, task ){
803 var oldName = from.split('/').pop();
804
805 ftp.rename(from, from.replaceLast(oldName, to), function(err, res) {
806 if( err ){
807 console.log( err );
808 client.emit('wp', {e: 'wpError', error: 'FTPre'});
809 }else{
810 // emit to the initiator
811 // client.emit('wp', {e: 'renamed'});
812
813 // emit to online members
814 if( task !== false ){
815 task.oldPath = from;
816 task.newName = to;
817 task.typ = type;
818 // hier kommt noch ne foreach um jeden user durch zu laufen
819 client.emit('wp', {e: 'renamed', task});
820 }
821 else{ // wenn foreach da ist die else löschen
822 client.emit('wp', {e: 'renamed', task});
823 }
824 }
825 });
826 }
827
828 // remove file or dir - nachfolgende Funktionen gehören zur Löschfunktion
829 function removeItem( ftp, item, type, task ){
830 if( item != '' && item != '/' && item != './' ){
831 if( type == 'd' ){
832 // check is dir empty
833 ftp.ls(item, function(err, res) {
834 if( err ){
835 client.emit('wp', {e: 'wpError', error: 'FTPrd'});
836 }else{
837 if( res.length == 0 ){
838 ftp.raw('rmd', item, function(err, data) {
839 if( err ){
840 client.emit('wp', {e: 'wpError', error: 'FTPrem'+err.code});
841 }else{
842 // emit to the initiator
843 // client.emit('wp', {e: 'deleted'});
844
845 // emit to online members
846 if( task !== false ){
847 // hier kommt noch ne foreach um jeden user durch zu laufen
848 client.emit('wp', {e: 'deleted', typ: type, item: task.item});
849 }
850 else{ // wenn foreach da ist die else löschen
851 client.emit('wp', {e: 'deleted'});
852 }
853 }
854 });
855 }else{
856 task.type = type;
857 removeAllInFolder(ftp, item, false, task);
858 }
859 }
860 });
861 }else{
862 ftp.raw('dele', item, function(err, data) {
863 if( err ){
864 client.emit('wp', {e: 'wpError', error: 'FTPrem'+err.code});
865 }else{
866 // emit to the initiator
867 // client.emit('wp', {e: 'deleted'});
868
869 // emit to online members
870 if( task !== false ){
871 // hier kommt noch ne foreach um jeden user durch zu laufen
872 client.emit('wp', {e: 'deleted', typ: type, item: task.item});
873 }
874 else{ // wenn foreach da ist die else löschen
875 client.emit('wp', {e: 'deleted'});
876 }
877 }
878 });
879 }
880 }
881 }
882 function removeAllInFolder(ftp, mainFolder, onlyContent, task) {
883 walk(ftp, mainFolder)
884 .then((results) => {
885 let files = flatten(results)
886 .filter(Boolean);
887
888 // add the mainfolder to the list if not only content
889 if( !onlyContent ){
890 var findName = mainFolder.split('/');
891 files.push({
892 name: findName[Object.keys(findName).length - 1],
893 type: 1,
894 filepath: mainFolder.replace('./', '')
895 });
896 }
897
898 // console.log("About to try deleting ", files.map((file) => file.filepath));
899
900 // Non-empty directories can't be removed, should I remove all files first?
901 let deletions = files.map((file) => {
902 if (isDirectory(file)) {
903 return deleteDirectory(ftp, file);
904 } else {
905 return deleteFile(ftp, file);
906 }
907 });
908
909 return Promise.all(deletions);
910 }).then((deletionResults) => {
911 console.log(task);
912
913 // emit to the initiator
914 // client.emit('wp', {e: 'deleted'});
915
916 // emit to online members
917 if( task !== false ){
918 // hier kommt noch ne foreach um jeden user durch zu laufen
919 client.emit('wp', {e: 'deleted', typ: task.type, item: task.item});
920 }
921 else{ // wenn foreach da ist die else löschen
922 client.emit('wp', {e: 'deleted'});
923 }
924
925 // console.log("Deletion results: ", deletionResults);
926 }).catch((error) => {
927 client.emit('wp', {e: 'wpError', error: 'FTPrem', msg: error});
928 // console.log("Error: ", error);
929 });
930 }
931
932 function walk(ftp, directory) {
933 return list(ftp, directory)
934 .then((files) => {
935 if (files.length === 0) {
936 return Promise.resolve();
937 }
938
939 return Promise.all(files.map((file) => {
940 file.filepath = path.join(directory, file.name);
941
942 let promises = [];
943
944 if (isDirectory(file)) {
945 promises.push(walk(ftp, path.join(directory, file.name)));
946 }
947 // Make sure the directory is after the files in the list of promises
948 promises.push(Promise.resolve(file));
949
950 return Promise.all(promises);
951 }));
952 });
953 }
954
955 function deleteDirectory(ftp, directory) {
956 return new Promise((resolve, reject) => {
957 ftp.raw('rmd', directory.filepath, (error, result) => {
958 if (error) {
959 return reject(error);
960 } else {
961 return resolve(result);
962 }
963 });
964 })
965 }
966
967 function deleteFile(ftp, file) {
968 return new Promise((resolve, reject) => {
969 ftp.raw('dele', file.filepath, (error, result) => {
970 if (error) {
971 return reject(error);
972 } else {
973 return resolve(result);
974 }
975 });
976 })
977 }
978
979 function list(ftp, directory) {
980 return new Promise((resolve, reject) => {
981 ftp.ls(directory, (error, files) => {
982 if (error) {
983 reject(error);
984 return;
985 }
986
987 resolve(files);
988 });
989 });
990 }
991
992 function isDirectory(file) {
993 return file.type === 1;
994 }
995
996 const flatten = list => list.reduce( (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [] );
997
998/** contact interaction */
999 client.on('contact', function(data){
1000 switch(data.e)
1001 {
1002 case 'getList': // emit: getList
1003
1004 // console.log( wSrv );
1005 // wSrv['001'].emit("task", 'illexmedia', client.uid, 'readFolder', {path: '/'}); // wp, user, task, data)
1006
1007
1008 var contactList = lobby.user[client.uid]['contacts'];
1009 for (i = 0; i < contactList.length; ++i)
1010 {
1011 contactList[i]['online'] = ( lobby.isOn(contactList[i]['id']) ) ? 'online' : 'offlline';
1012 }
1013 client.emit('contact', {e: 'getListe', liste: contactList});
1014 break;
1015
1016 case 'sendRequest': // emit: requestPosted
1017 var myID = client.uid,
1018 cID = data.id,
1019 grp = data.gid;
1020
1021 console.log('goRequest to: '+cID+' group: '+grp);
1022 if( vali.isInt(cID) && vali.isInt(grp, { min: 1, max: 7 }) )
1023 {
1024 console.log('go querys');
1025 db.query("SELECT status FROM contacts WHERE uid LIKE :myId AND cid = :cid LIMIT 1", {myId: myID, cid: cID}, // check db of exist request
1026 function( err, result )
1027 {
1028 if( err )
1029 {
1030 socket.emit('error', 'db_error');
1031 }
1032 else if( result.length == 0 ) // no request exist
1033 {
1034 var datum = new Date().dateTime();
1035 var insert = "INSERT INTO contacts (uid, cid, status, grp, date) VALUES (:m_id, :m_cid, '2', :m_grp, :m_date), (:u_id, :u_cid, '3', :u_grp, :u_date)"; // insert request
1036 db.query(
1037 insert, {m_id: myID, m_cid: cID, m_grp: grp, m_date: datum, u_id: cID, u_cid: myID, u_grp: grp, u_date: datum },
1038 function( err, result )
1039 {
1040 console.log( result );
1041 }
1042 );
1043 // client.emit('requestPosted', 'empty');
1044 }
1045 else
1046 {
1047 console.log('request exist');
1048 }
1049 }
1050 );
1051 }
1052 break;
1053
1054 case 'cancleRequest':
1055
1056 break;
1057
1058 case 'add':
1059
1060 break;
1061
1062 case 'remove':
1063
1064 break;
1065
1066 case 'block':
1067
1068 break;
1069
1070 case 'reject':
1071 deliver(socket.id, 8, {'testReceive': 'Bla'});
1072 break;
1073
1074 case 'rejectBlock':
1075
1076 break;
1077
1078 case 'notNew':
1079
1080 break;
1081
1082 case 'chat':
1083
1084 break;
1085 }
1086 });
1087
1088/** header searchbar */
1089 client.on('searchbar',function(data){
1090 var string='';
1091 switch( data['group'] )
1092 {
1093 case 'accounts':
1094 string = "SELECT persons, pid FROM accounts WHERE persons LIKE :param";
1095 var temp = data.string.substr(0, 20).split(" ");
1096 data.string = '%'+temp.join(',')+'%';
1097 break;
1098 }
1099
1100 if( string != '' )
1101 {
1102 db.query(
1103 string, {param: data.string, f_tags: ['<a>','<php>']},
1104 function( err, result )
1105 {
1106 if( err ){
1107 client.emit('searBarResult', 'error');
1108 }else if( result.length == 0 ){
1109 client.emit('searBarResult', 'empty');
1110 }else{
1111 client.emit('searBarResult', {typ: data['group'], result: result});
1112 }
1113 }
1114 );
1115 }
1116 });
1117
1118 /** emit handlings */
1119 client.on('testEmit',function(data)
1120 {
1121 console.log('klick received: '+ data);
1122 // if( lobby.checkSpam('testEmit', arguments) ) // die lobby muss dann nach entsprechender Verarbeitung ture oder false liefern um die Anfrage weiter verarbeiten zu können
1123 // {
1124 // lobby.deliver( client.uid, 1, {'testReceive': {msg: "server empfang und sendete zurück..."}}, 'main');
1125 // }
1126 });
1127});
1128console.log('Juhu Server running');