UNPKG

29.1 kBJavaScriptView Raw
1#!/usr/bin/env node
2/*
3
4Fast Loop-Server reader - runs an http server which accepts requests like the PHP software, and quickly reads the results ready for display on-screen.
5To be used in the most common cases only (i.e. it doesn't handle bulk message downloads etc.)
6
7The loop-server config.json contains the settings for this server.
8Usage: node loop-server-fast.js config/path/config.json [-production]
9
10
11Testing https connection:
12openssl s_client -CApath /etc/ssl/certs -connect yourdomain.com:5566
13
14
15Possible future project:
16Implement a mysql connection pool ala:
17https://codeforgeek.com/2015/01/nodejs-mysql-tutorial/
18
19However, this may not be necessary - we already have multi-core handled by pm2, and we are one connection per
20database, but the requests are async.
21
22*/
23
24
25
26var multiparty = require('multiparty');
27var http = require('http');
28var https = require('https');
29var util = require('util');
30var path = require("path");
31require("date-format-lite");
32var mv = require('mv');
33var fs = require('fs');
34var exec = require('child_process').exec;
35var fsExtra = require('fs-extra');
36var request = require("request");
37var needle = require('needle');
38var readChunk = require('read-chunk'); // npm install read-chunk
39var async = require('async');
40var mysql = require('mysql');
41var os = require('os');
42const querystring = require('querystring');
43var crypto = require('crypto');
44var get_ip = require('ipware')().get_ip;
45
46
47var httpsFlag = false; //whether we are serving up https (= true) or http (= false)
48var serverOptions = {}; //default https server options (see nodejs https module)
49var listenPort = 3277; //default listen port. Will get from the config readPort if it is set there
50var msg = {};
51var lang;
52var timeUnits; //time units
53var agoDefault; //Usually in English set to 'ago' - the word displayed after the time units
54var verbose = false;
55var currentDbServer = [];
56currentDbServer[0] = 0;
57var usage = "Usage: node loop-server-fast.js config/path/config.json config/path/messages.json [-production]\n\nOr:\n\nnpm config set loop-server-fast:configFile /path/to/your/loop/server/config.json\nnpm config set loop-server-fast:messagesFile /path/to/your/loop/server/messages.json\n[npm config set loop-server-fast:production true]\nnpm run start\n\n";
58var defaultPHPScript = "search-chat.php?";
59var defaultPHPScriptLen = defaultPHPScript.length;
60
61
62process.on('SIGINT', function() {
63 //Cleanly handle a process kill
64 console.log("Requesting a shutdown.");
65 closeAllConnections();
66 setTimeout(function() {
67 // 300ms later the process kill it self to allow a restart
68 console.log("Clean exit.");
69 process.exit(0);
70 }, 300);
71});
72
73
74
75if((process.argv)&&(process.argv[2])){
76 var loopServerConfig = process.argv[2];
77} else {
78 if(process.env.npm_package_config_configFile) {
79 var loopServerConfig = process.env.npm_package_config_configFile;
80 } else {
81
82 console.log(usage);
83 process.exit(0);
84 }
85}
86
87
88
89
90var config = JSON.parse(fs.readFileSync(loopServerConfig));
91if(!config) {
92 console.log("Couldn't find config file " + loopServerConfig);
93 process.exit(0);
94}
95
96
97if(((process.argv)&&(process.argv[3]))||(process.env.npm_package_config_messagesFile)){
98 //Get the messages and ago constants
99 if(process.argv[3]) {
100 var loopServerMessages = process.argv[3];
101 } else {
102 //Get from the npm config
103 var loopServerMessages = process.env.npm_package_config_messagesFile;
104 }
105 msg = JSON.parse(fs.readFileSync(loopServerMessages));
106 if(!msg) {
107 console.log("Couldn't find messages file " + loopServerMessages);
108 process.exit(0);
109 }
110 lang = msg.defaultLanguage;
111
112
113 var time = msg.msgs[lang].time;
114 timeUnits = [
115 { name: time.second, plural: time.seconds, limit: 60, in_seconds: 1 },
116 { name: time.minute, plural: time.minutes, limit: 3600, in_seconds: 60 },
117 { name: time.hour, plural: time.hours, limit: 86400, in_seconds: 3600 },
118 { name: time.day, plural: time.days, limit: 604800, in_seconds: 86400 },
119 { name: time.week, plural: time.weeks, limit: 2629743, in_seconds: 604800 },
120 { name: time.month, plural: time.months, limit: 31556926, in_seconds: 2629743 },
121 { name: time.year, plural: time.years, limit: null, in_seconds: 31556926 }
122 ];
123
124 agoDefault = time.ago;
125
126
127} else {
128 console.log(usage);
129 process.exit(0);
130}
131
132
133if((process.argv[4]) && (process.argv[4] == '-production')){
134 var cnf = config.production;
135} else {
136 if(process.env.npm_package_config_production) {
137 if(process.env.npm_package_config_production == 'true') {
138 var cnf = config.production;
139 } else {
140 var cnf = config.staging;
141 }
142
143 } else {
144 var cnf = config.staging;
145 }
146}
147
148//Configurable verbose variable
149if(process.env.npm_package_config_verbose) {
150 if(process.env.npm_package_config_verbose == 'true') {
151 verbose = true;
152 } else {
153 verbose = false;
154 }
155
156}
157
158//Use the port specified in the config
159if(cnf.readPort) {
160 listenPort = cnf.readPort;
161}
162
163//Create an https server if we specify a key and cert file
164if(cnf.httpsKey) {
165 //httpsKey should point to the key .pem file
166 httpsFlag = true;
167 if(!serverOptions.key) {
168 serverOptions.key = fs.readFileSync(cnf.httpsKey);
169 console.log("https key loaded");
170 }
171 }
172
173 if(cnf.httpsCert) {
174 //httpsCert should point to the cert .pem file
175 httpsFlag = true;
176 if(!serverOptions.cert) {
177 serverOptions.cert = fs.readFileSync(cnf.httpsCert);
178 console.log("https cert loaded");
179 }
180
181 }
182
183 var connections = [];
184
185 var closing = false; //This is a global shutting down from mysql flag
186 function closeAllConnections() {
187 if(closing == false) { //Only do this once
188 for(var ccnt = 0; ccnt< cnf.db.hosts.length; ccnt++) {
189 if(connections[0][ccnt]) {
190 connections[0][ccnt].end();
191 }
192 }
193
194 if(cnf.db.scaleUp) {
195 for(var scaleCnt = 0; scaleCnt< cnf.db.scaleUp.length; scaleCnt++) {
196 for(var ccnt = 0; ccnt< cnf.db.scaleUp[scaleCnt].hosts.length; ccnt++) {
197 if(connections[scaleCnt+1][ccnt]) {
198 connections[scaleCnt+1][ccnt].end();
199 }
200 }
201
202 }
203 }
204 }
205
206 }
207
208
209 function handleDisconnect() {
210
211 //Check for a different database
212 /*
213 if((isset($db_cnf['scaleUp']))&&(isset($layer_name))) {
214 //We are scaling up
215 for($cnt = 0; $cnt< count($db_cnf['scaleUp']); $cnt ++) {
216 if(preg_match($db_cnf['scaleUp'][$cnt]['labelRegExp'],$layer_name, $matches) == true) {
217 //Override with this database
218 $db_cnf = $db_cnf['scaleUp'][$cnt];
219 return;
220 }
221
222 }
223 }
224 */
225
226
227
228
229 //Reconnect to all db hosts
230 console.log("Connecting to the database.");
231 connections[0] = {};
232 for(var cnt = 0; cnt< cnf.db.hosts.length; cnt++) {
233
234 if(cnf.db.ssl && cnf.db.ssl.use === true) {
235 var ssl = {
236 ca : fs.readFileSync(cnf.db.ssl.capath)
237 };
238 } else {
239 var ssl = null;
240 }
241
242 connections[0][cnt] = mysql.createConnection({
243 host : cnf.db.hosts[cnt],
244 user : cnf.db.user,
245 password : cnf.db.pass,
246 database : cnf.db.name,
247 port : cnf.db.port,
248 ssl : ssl
249 });
250
251 //connections[cnt].connect();
252 connections[0][cnt].connect(function(err) { // The server is either down
253 if(err) { // or restarting (takes a while sometimes).
254 //Error on trying to connect - try again in 2 seconds
255 console.log('error when connecting to db:', err);
256 closeAllConnections();
257
258 if(closing == false) {
259 closing = true;
260 setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
261 }
262
263 } // to avoid a hot loop, and to allow our node script to
264 }); // process asynchronous requests in the meantime.
265 // If you're also serving http, display a 503 error.
266 connections[0][cnt].on('error', function(err) {
267 console.log('db error: ', err);
268
269 closeAllConnections();
270
271
272 if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
273 //Close and restart all the connections
274
275
276 if(closing == false) {
277 closing = true;
278 setTimeout(handleDisconnect, 2000); // lost due to either server restart, or a
279 }
280 } else { // connnection idle timeout (the wait_timeout
281 //throw err; // server variable configures this)
282 //closeAllConnections();
283 if(closing == false) {
284 closing = true;
285 setTimeout(handleDisconnect, 2000);
286 }
287
288 }
289 });
290
291
292 }
293
294 if(cnf.db.scaleUp) {
295 //Create more connections
296 for(var scaleCnt = 0; scaleCnt< cnf.db.scaleUp.length; scaleCnt++) {
297
298 connections[scaleCnt+1] = [];
299 currentDbServer[scaleCnt+1] = 0;
300 dbCnf = cnf.db.scaleUp[scaleCnt];
301
302 if(dbCnf.ssl && dbCnf.ssl.use === true) {
303 var ssl = {
304 ca : fs.readFileSync(dbCnf.ssl.capath)
305 };
306 } else {
307 var ssl = null;
308 }
309
310
311 for(var cnt = 0; cnt< dbCnf.hosts.length; cnt++) {
312
313 connections[scaleCnt+1][cnt] = mysql.createConnection({
314 host : dbCnf.hosts[cnt],
315 user : dbCnf.user,
316 password : dbCnf.pass,
317 database : dbCnf.name,
318 port : dbCnf.port,
319 ssl : ssl
320 });
321
322 //connections[cnt].connect();
323 connections[scaleCnt+1][cnt].connect(function(err) { // The server is either down
324 if(err) { // or restarting (takes a while sometimes).
325 console.log('error when connecting to db:', err);
326 closeAllConnections();
327
328 if(closing == false) {
329 closing = true;
330 setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
331 }
332 } // to avoid a hot loop, and to allow our node script to
333 }); // process asynchronous requests in the meantime.
334 // If you're also serving http, display a 503 error.
335 connections[scaleCnt+1][cnt].on('error', function(err) {
336 console.log('db error: ', err);
337
338 closeAllConnections();
339
340
341 if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
342 //Close and restart all the connections
343 //closeAllConnections();
344
345 if(closing == false) {
346 closing = true;
347 setTimeout(handleDisconnect, 2000); // lost due to either server restart, or a
348 }
349 } else { // connnection idle timeout (the wait_timeout
350 //throw err; // server variable configures this)
351
352 if(closing == false) {
353 closing = true;
354 setTimeout(handleDisconnect, 2000);
355 }
356 }
357
358
359 });
360
361
362 }
363 }
364
365 }
366
367 if(closing == true) {
368 //Have finished getting db connections
369 console.log("Finished connecting to the database.");
370 closing = false;
371 }
372
373
374}
375
376handleDisconnect();
377
378function escapeRegExp(str) {
379 return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
380}
381
382
383function cleanData(str)
384{
385 //Clean for database requests
386 return escapeRegExp(str);
387}
388
389
390function trimChar(string, charToRemove) {
391 while(string.substring(0,1) == charToRemove) {
392 string = string.substring(1);
393 }
394
395 while(string.slice(-1) == charToRemove) {
396 string = string.slice(0, -1);
397 }
398
399 return string;
400}
401
402
403
404
405function readSession(params, cb)
406{
407
408 /*
409
410 Sample session record
411 | sgo3vosp1ej150sln9cvdslqm0 | 736 | 2016-06-09 16:04:03 | 2016-06-26 16:40:54 | view-count|i:1;logged-user|i:736;user-ip|s:15:"128.199.221.111";layer-group-user|s:0:"";authenticated-layer|s:3:"181";temp-user-name|s:7:"Anon 11";lat|i:51;lon|i:0;
412 */
413 var keyValues = {};
414
415 if(verbose == true) console.log("SessionID" + cleanData(params.sessionId));
416
417 if(!params.connection) {
418 //No connection
419 cb(null);
420 return;
421
422 }
423
424 params.connection.query("SELECT * FROM php_session WHERE session_id='" + cleanData(params.sessionId) + "'", function(err, rows, fields) {
425
426 if (err) {
427 console.log("Database error:" + err);
428 cb(null);
429 } else {
430
431
432 if((rows[0])&&(rows[0].session_data)) {
433
434 if(verbose == true) console.log("Session data:" + rows[0].session_data);
435 var params = rows[0].session_data.split(";");
436 for(var cnt=0; cnt< params.length; cnt++) {
437
438 var paramData = params[cnt].split("|");
439 if(paramData[1]) {
440 //There is some data about this param
441 var paramValues = paramData[1].split(":");
442 if(paramValues[0] == 'i') {
443 //An integer - value proceeds
444 var paramValue = paramValues[1];
445 } else {
446 //A string, [1] is the string length, [2] is the string itself
447 var paramValue = trimChar(paramValues[2], '"');
448 }
449
450 keyValues[paramData[0]] = paramValue;
451 if(verbose == true) console.log("Key:" + paramData[0] + " = " + paramValue);
452 }
453 }
454 }
455
456 cb(keyValues);
457 }
458 });
459
460}
461
462
463
464function httpHttpsCreateServer(options) {
465 if(httpsFlag == true) {
466 console.log("Starting https server.");
467 https.createServer(options, handleServer).listen(listenPort);
468
469
470 } else {
471 console.log("Starting http server.");
472 http.createServer(handleServer).listen(listenPort);
473 }
474
475
476
477}
478
479
480
481
482
483function handleServer(_req, _res) {
484
485 var req = _req;
486 var res = _res;
487 var body = [];
488
489 //Start ordinary error handling
490 req.on('error', function(err) {
491 // This prints the error message and stack trace to `stderr`.
492 console.error(err.stack);
493
494 res.statusCode = 400; //Error during transmission - tell the app about it
495 res.end();
496 });
497
498 req.on('data', function(chunk) {
499 body.push(chunk);
500 });
501
502 req.on('end', function() {
503
504
505 //A get request to pull from the server
506
507
508
509 // show a file upload form
510 if(verbose == true) console.log("Requesting: " + req.url);
511
512 //It must include search-chat.php or it is ignored.
513 if(req.url.indexOf(defaultPHPScript) < 0) {
514 res.writeHead(200, {'content-type': 'text/html'});
515 res.end("Not available");
516 return;
517 }
518
519 var url = req.url.substring(req.url.indexOf(defaultPHPScript) + defaultPHPScriptLen); //16 is length of 'search-chat.php'. We want the url as all the params after this. search-chat.php
520 //is the current standard request entry point
521
522 if(verbose == true) console.log("Parsed to query string:" + url);
523 var params = querystring.parse(url);
524 if(verbose == true) console.log("Query params = " + JSON.stringify(params));
525
526 var cookies = parseCookies(req);
527 if(!params.sessionId) { //Only if not passed in on the command line
528 params.sessionId = cookies.PHPSESSID; //This is our custom cookie.
529 }
530 if(!params.sessionId) {
531 res.statusCode = 400; //Error - tell the app about it
532 res.end();
533 console.log("Error: You must include a PHP Session ID");
534 return;
535
536 }
537
538 if(cookies.lang) {
539 //A language modifier exists
540 var time = msg.msgs[cookies.lang].time;
541 params.timeUnits = [
542 { name: time.second, plural: time.seconds, limit: 60, in_seconds: 1 },
543 { name: time.minute, plural: time.minutes, limit: 3600, in_seconds: 60 },
544 { name: time.hour, plural: time.hours, limit: 86400, in_seconds: 3600 },
545 { name: time.day, plural: time.days, limit: 604800, in_seconds: 86400 },
546 { name: time.week, plural: time.weeks, limit: 2629743, in_seconds: 604800 },
547 { name: time.month, plural: time.months, limit: 31556926, in_seconds: 2629743 },
548 { name: time.year, plural: time.years, limit: null, in_seconds: 31556926 }
549 ];
550
551 params.ago = time.ago;
552
553 }
554
555 params.ip = getFakeIpAddress(params.sessionId);
556
557 //Choose a random db connection
558 params.connection = connections[0][currentDbServer[0]];
559
560 //Round robin the connection
561 currentDbServer[0] ++;
562 if(currentDbServer[0] >= cnf.db.hosts.length) currentDbServer[0] = 0;
563
564 //Double up on this
565 var myres = res;
566
567 var jsonData = searchProcess(params, function(err, data) {
568 if(err) {
569 if(err == 'PHP') {
570 //Call the PHP version of this script
571
572 var fullUrl = cnf.webRoot + '/' + defaultPHPScript + url;
573 if(verbose == true) console.log("Webroot:" + cnf.webRoot + " Default PHP script:" + defaultPHPScript + " Url:" + url + " fullUrl:" + fullUrl);
574 callPHP(fullUrl, myres);
575 return;
576 }
577
578 console.log(err);
579 res.statusCode = 400;
580 res.end();
581 }
582
583 //Prepare the result set for the jsonp result
584 var strData = params.callback + "(" + JSON.stringify( data ) + ")";
585
586 res.on('error', function(err){
587 //Handle the errors here
588 res.statusCode = 400;
589 res.end();
590 })
591
592 res.writeHead(200, {'content-type': 'text/html'});
593
594
595 res.end(strData, function(err) {
596 //Wait until finished sending, then delete locally
597 if(err) {
598 console.log(err);
599 } else {
600 //success, do nothing
601 process.stdout.write("."); //Show successful pings
602 }
603 });
604 }); //End of process
605
606 }); //End of req end
607
608}
609
610
611function parseCookies (request) {
612 var list = {},
613 rc = request.headers.cookie;
614
615 rc && rc.split(';').forEach(function( cookie ) {
616 var parts = cookie.split('=');
617 list[parts.shift().trim()] = decodeURI(parts.join('='));
618 });
619
620 return list;
621}
622
623
624function ago(timeStr, thisTimeUnits, agoWord) {
625
626
627
628
629 var recTime = new Date(timeStr);
630 var recTimeSecs = recTime.getTime();
631 //Get diff in seconds
632
633 var nowSecs = new Date().getTime();
634 var diff = (nowSecs - recTimeSecs) / 1000;
635
636 var i = 0;
637 var unit = {};
638
639 while (unit = thisTimeUnits[i]) {
640 if ((diff < unit.limit) || (!unit.limit)){
641 var diff = Math.round(diff / unit.in_seconds); //was floor
642 var timeOut = diff + " " + (diff>1 ? unit.plural : unit.name) + " " + agoWord;
643 return timeOut;
644 }
645 i++;
646 }
647
648 return "Unknown";
649
650
651
652}
653
654function md5(data) {
655
656 return crypto.createHash('md5').update(data).digest("hex");
657}
658
659
660function getFakeIpAddress(sessionId) {
661 //This is a copy of the PHP version - it creates an ip with 192.a.b.c where
662 //a = ASCII value of sessionId's first character
663 //b = ASCII value of sessionId's second character
664 //c = ASCII value of sessionId's third character
665
666 if(sessionId) {
667 var ip = "192." + parseInt(sessionId.charCodeAt(0)) + "." +
668 parseInt(sessionId.charCodeAt(1)) + "." +
669 parseInt(sessionId.charCodeAt(2));
670 return ip;
671 } else {
672 //OK, so we don't have a session id - use a fixed random ip
673 return "192.168.10.10";
674 }
675}
676
677function getRealIpAddress(req) {
678
679 var ip_info = get_ip(req);
680
681 return ip_info.clientIp.replace(/^[0-9.,]+$/,"");
682}
683
684
685
686
687
688function callPHP(url, res) {
689 //Reads in from the PHP script url for a .jsonp response (plain text)
690 //and write it out to the requester
691 if(verbose == true) console.log("Redirecting to " + url);
692
693 res.writeHead(302, {
694 'Location': url
695 //add other headers here...
696 });
697 res.end();
698
699
700}
701
702
703
704function foundLayer(params,
705 session,
706 layer,
707 ip,
708 userCheck,
709 initialRecords,
710 outputJSON,
711 debug,
712 cb) {
713
714 if((params.units) && (params.units != '')) {
715 units = params.units;
716 }
717
718 if((params.dbg) && (params.dbg == 'true')) {
719 debug = true;
720 } else {
721 debug = false;
722 }
723
724 if(session['logged-user']) {
725 userCheck = " OR int_author_id = " + session['logged-user'] + " OR int_whisper_to_id = " + session['logged-user'];
726
727 }
728
729 if(session['logged-group-user']) {
730 userCheck = userCheck + " OR int_author_id = " + session['logged-group-user'] + " OR int_whisper_to_id = " + session['logged-group-user'];
731
732 }
733
734 if((params.records) && (params.records < 100)) {
735 initialRecords = 100; //min this can be - needs to be about 4 to 1 of private to public to start reducing the number of public messages visible
736 } else {
737 if(params.records) {
738 initialRecords = params.records;
739 }
740 }
741
742
743
744
745
746
747
748
749 var sql = "SELECT * FROM tbl_ssshout WHERE int_layer_id = " + layer + " AND enm_active = 'true' AND (var_whisper_to = '' OR ISNULL(var_whisper_to) OR var_whisper_to ='" + ip + "' OR var_ip = '" + ip + "' " + userCheck + ") ORDER BY date_when_shouted DESC LIMIT " + initialRecords;
750 if(verbose == true) console.log("Query: " + sql);
751 if(!params.connection) { //check the connection is still valid
752 //No connection
753 cb(err, null);
754 return;
755 }
756
757 params.connection.query(sql, function(err, rows, fields) {
758
759
760 if (err) {
761
762 console.log("Database query error:" + err);
763 cb(err, null);
764 return;
765 }
766
767
768 outputJSON.res = [];
769 outputJSON.ses = params.sessionId;
770
771
772 var mymaxResults = rows.length;
773 if(mymaxResults > params.records) {
774 mymaxResults = params.records; //limit number to records requested
775 var more = true; //show more flag for
776 }
777 var actualCnt = 0;
778
779 //Exit early with no results on no layer access
780 if((session['access-layer-granted'])&&(session['access-layer-granted'] !== "true")
781 &&(session['access-layer-granted'] != true)) {
782 if((session['access-layer-granted'] == 'false') || (session['access-layer-granted'] != layer)) {
783
784 //See if we are in the array of layers, ignore this
785 if((session['access-layers-granted'])&&(Array.isArray(session['access-layers-granted']))) {
786 //Check if the layer is in, if not, then exit
787 var granted = session['access-layers-granted'];
788 if(granted.includes(layer)) {
789 //No action needed
790 } else {
791
792 outputJSON.res = []; //No results
793 cb(null, outputJSON); //No errors
794 return;
795 }
796
797 } else {
798
799 outputJSON.res = []; //No results
800 cb(null, outputJSON); //No errors
801 return;
802 }
803 }
804 }
805
806 //Time unit override
807 var thisTimeUnits = timeUnits; //The default language
808 var thisAgo = agoDefault;
809 if(params.timeUnits) {
810 //An override, which was set by the cookie 'lang'
811 thisTimeUnits = params.timeUnits;
812 thisAgo = params.ago;
813 }
814
815
816 for(var cnt = 0; cnt< rows.length; cnt++) {
817
818 var whisper = true; //default
819 var authorIP = rows[cnt].var_ip;
820 var authorUserID = rows[cnt].int_author_id;
821 var combinedAuthor = authorIP;
822 if(authorUserID) {
823 combinedAuthor = combinedAuthor + ":" + authorUserID;
824 }
825
826 var whisperToIP = rows[cnt].var_whisper_to;
827 var whisperToUserID = rows[cnt].int_whisper_to_id;
828
829
830
831 //If no whispering, or are whispering but to the viewer's ip address, or from the viewer's own ip
832 if((whisperToIP == '')|| //ie. public
833 ((whisperToIP == ip)&&(whisperToUserID == null))|| //private but no user id known
834 (whisperToUserID == session['logged-user'])|| //talk direct to owner
835 ((authorIP == ip)&&(authorUserID == null))|| //authored by this ip no user known of author
836 (authorUserID == session['logged-user'])|| //authored by this viewer
837 ((session['logged-group-user'] != "")&&(whisperToUserID != "") && (whisperToUserID == session['logged-group-user']))) { //private message to group
838
839 //Right actually going to include message - now decide if whispering or public
840
841 if(((whisperToIP == ip) && (whisperToUserID == null))|| //if it was a whisper intended for our ip but unknown user
842 (whisperToUserID == session['logged-user'])|| //or a whisper specifically for us
843 ((authorIP == ip) && ((whisperToIP != '')||(whisperToUserID)))|| //or def a whisper by viewer
844 (authorUserID == session['logged-user'] && ((whisperToIP != '')|| (whisperToUserID)))) { //or a whisper by viewer logged in
845 //This is a whisper to you or from you, use 1/3 font size
846 whisper = true;
847 } else {
848 //A shout
849 whisper = false;
850 }
851
852 if(session['logged-group-user']) {
853 if(whisperToUserID == session['logged-group-user']) {
854 whisper = true;
855
856 }
857 }
858
859 if(!session['logged-user']) {
860 //Force a blank user to see only public requests, until he has actually commented.
861 whisper = false;
862
863 }
864
865
866
867 var shade = rows[cnt].int_ssshout_id %2;
868 if(layer == 0) {
869 //Public layer
870 if(shade == 0) {
871 bgcolor = "public-light";
872 } else {
873 bgcolor = "public-dark";
874 }
875 } else {
876 //Private layer - different colours
877 if(shade == 0) {
878 bgcolor = "private-light";
879 } else {
880 bgcolor = "private-dark";
881 }
882
883 }
884
885 //In PHP here? date_default_timezone_set($server_timezone); //E.g. "UTC" GMT"
886
887
888 if(actualCnt <= mymaxResults) {
889
890
891
892
893 var newEntry = {
894 'id': rows[cnt].int_ssshout_id,
895 'text': rows[cnt].var_shouted_processed,
896 'lat': rows[cnt].latitude,
897 'lon': rows[cnt].longtiude,
898 'dist': rows[cnt].dist,
899 'ago': ago(rows[cnt].date_when_shouted, thisTimeUnits, thisAgo),
900 'whisper': whisper
901
902 }
903
904 outputJSON.res.push(newEntry);
905
906 actualCnt ++; //Increment the actual result count
907 }
908
909
910 } //End of valid message
911
912 } //End of for loop
913
914 cb(null, outputJSON); //No errors
915
916
917 }); //End of query
918
919
920}
921
922
923function checkScaleupHorizontally(layerName, params) {
924
925 if(cnf.db.scaleUp) {
926 //Create more connections
927 for(var scaleCnt = 0; scaleCnt< cnf.db.scaleUp.length; scaleCnt++) {
928
929 var regExp = new RegExp(cnf.db.scaleUp[scaleCnt].labelRegExp);
930 if(layerName.search(regExp) >= 0) {
931 //OK switch over to this db connection
932 //Choose a random db connection
933 params.connection = connections[scaleCnt+1][currentDbServer[scaleCnt+1]];
934
935 //Round robin the connection
936 currentDbServer[scaleCnt+1] ++;
937 if(currentDbServer[scaleCnt+1] >= cnf.db.scaleUp[scaleCnt].hosts.length) currentDbServer[scaleCnt+1] = 0;
938 return;
939 }
940 }
941 }
942
943 return;
944}
945
946
947
948function searchProcess(params, cb) {
949
950 //Get the session data
951 checkScaleupHorizontally(params.passcode, params); //This should be before the 'readSession' because the session comes from this horiontal database also.
952
953
954 readSession(params, function(session) { //eg. 'sgo3vosp1ej150sln9cvdslqm0'
955 if(verbose == true) console.log("Finished getting session data. Logged user:" + session['logged-user']);
956
957
958
959
960 if((session)&&(session['logged-user'])&&(session['logged-user'] != '')) {
961 //Already logged in, but check if we know the ip address
962 if((!session['user-ip'])||(session['user-ip'] == '')) {
963 //No ip. Will have to revert back to the PHP version
964 console.log('No ip. Going to PHP');
965 cb("PHP", null);
966 return;
967 } else {
968
969 //We're good to make a db request
970
971 //If this is the first request this session, we need to use the PHP
972 //version to ensure we have registered the count
973 if(session['view-count'] == 0) {
974 console.log("view-count = " + session['view-count'] + " Going to PHP");
975 cb("PHP", null);
976 return;
977 }
978
979 var layer = 1;
980 var ip = params.ip;
981 var userCheck = "";
982 var initialRecords = 100;
983 var outputJSON = {};
984 var debug = false;
985
986
987 if((params.passcode) && (params.passcode != '')||((params.reading) && (params.reading != ''))) {
988
989 //See if we need to switch to a different db connection based off the layer name
990 //OLD: checkScaleupHorizontally(params.passcode, params);
991
992 var sql = "SELECT int_layer_id FROM tbl_layer WHERE passcode = '" + md5(params.passcode) + "'";
993
994 if(params.connection) { //check the connection is still valid
995 params.connection.query(sql, function(err, rows, fields) {
996
997 if(err) {
998 console.log("Database error: " + err);
999 return;
1000 } else {
1001 if((rows)&&(rows[0])) {
1002 layer = rows[0].int_layer_id;
1003
1004 foundLayer(params, session, layer, ip, userCheck, initialRecords, outputJSON, debug, cb);
1005 } else {
1006 console.log("No layer " + md5(params.passcode) + " - likely new. Going to PHP");
1007 cb("PHP", null);
1008 return;
1009 //Unknown or new layer - head back to PHP
1010
1011
1012 }
1013 }
1014 });
1015 }
1016
1017
1018
1019
1020
1021
1022 } else { //End of passcode not = ''
1023
1024 if(session['authenticated-layer']) {
1025 layer = session['authenticated-layer'];
1026 } else {
1027 layer = 1; //Default to about layer
1028 }
1029
1030 foundLayer(params, session, layer, ip, userCheck, initialRecords, outputJSON, debug, cb);
1031 }
1032
1033
1034 } //End of do have an ip
1035
1036
1037 } else {
1038 //Not logged in - revert back to the PHP version
1039 console.log("Not logged in - back to PHP version");
1040 cb("PHP", null);
1041 return;
1042
1043 }
1044
1045
1046 }); //End of readSession
1047
1048
1049}
1050
1051
1052
1053
1054
1055
1056
1057//Run at server startup
1058httpHttpsCreateServer(serverOptions);
1059
1060