UNPKG

31.8 kBJavaScriptView Raw
1/*
2
3Unzips, and then runs each of the commands in a
4
5
6*/
7
8
9
10
11var url = require("url");
12var path = require("path");
13var unzip = require('unzip');
14var request = require('request');
15var path = require("path");
16var upath = require("upath");
17var queryString = require('querystring');
18var http = require('http');
19var https = require('https');
20var fs = require('fs');
21var fsExtra = require('fs-extra');
22var async = require('async');
23var exec = require('child_process').exec;
24var spawn = require('child_process').spawn;
25
26const Entities = require('html-entities').AllHtmlEntities;
27
28const entities = new Entities();
29
30
31
32var httpsFlag = false; //whether we are serving up https (= true) or http (= false)
33var serverOptions = {}; //default https server options (see nodejs https module)
34var verbose = false;
35
36
37var configFile = __dirname + '/../../config.json';
38var targetAddonsFolder = __dirname + "/../";
39var tempDir = 'temp-installation/';
40var descriptorFile = "medimage-installer.json";
41
42
43
44function normalizeInclWinNetworks(path)
45{
46 //Tests to see if the path is a Windows network path first, if so, handle this case slightly differently
47 //to a normal upath.normalization.
48 //Run this before
49 if((path[0] == "\\")&&(path[1] == "\\")) {
50
51 return "\/" + upath.normalize(path); //Prepend the first slash
52 } else {
53 if((path[0] == "\/")&&(path[1] == "\/")) {
54 //In unix style syntax, but still a windows style network path
55 return "\/" + upath.normalize(path); //Prepend the first slash
56 } else {
57 return upath.normalize(path);
58 }
59 }
60
61}
62
63
64function getMasterConfig(defaultConfig, callback) {
65 exec("npm get medimage:configFile", {
66 maxBuffer: 2000 * 1024 //quick fix
67 }, (err, stdout, stderr) => {
68 if (err) {
69 // node couldn't execute the command
70 console.log("There was a problem running the addon. Error:" + err);
71 callback(err, "");
72
73 } else {
74 if((stdout != "")&&(!stdout.startsWith("undefined"))) {
75 callback(null, stdout.trim());
76
77 } else {
78 callback("Global not set", null);
79
80 }
81 }
82 }); //End of the exec
83}
84
85function havePermission(configFile, cb) {
86 //Checks config to see if we have permissions
87 //Returns true or false
88
89
90 getMasterConfig(configFile, function(err, masterConfigFile) {
91 if(err) {
92 //Leave with the configFile
93 } else {
94 configFile = masterConfigFile; //Override with the global option
95 }
96 console.log("Using config file:" + configFile);
97
98 //Write to a json file with the current drive. This can be removed later manually by user, or added to
99 fs.readFile(configFile, function read(err, data) {
100 if (err) {
101 cb("Sorry, cannot read config file! " + err);
102 } else {
103 var content = JSON.parse(data);
104
105
106 if(content.lockDown == false) { //For security purposes, only allow this change through the interface if we are a client machine
107
108 cb(null, true);
109
110 } else {
111
112 cb(null, false);
113 }
114
115
116
117 };
118 });
119 });
120
121}
122
123
124function noTrailSlash(str)
125{
126 if(str.slice(-1) == "/") {
127 return str.slice(0,-1); //Chop off last char
128 } else {
129 return str;
130 }
131
132}
133
134
135
136
137
138function getPlatform() {
139
140 var platform = process.platform;
141 if(verbose == true) console.log(process.platform);
142 var isWin = /^win/.test(platform);
143 if(verbose == true) console.log("IsWin=" + isWin);
144 if(isWin) {
145 if(process.arch == 'x64') {
146 return "win64";
147 } else {
148 return "win32";
149 }
150 } else {
151 if(platform == "darwin") {
152 return "mac";
153 } else {
154 return "unix";
155 }
156
157 }
158
159
160}
161
162
163
164function unzipAndRemoveNew(filename, tmpFilePath, cb) {
165 //filename is e.g. 'medimage-addon-ehr-medtech32-0.0.4.zip'
166 //tmpFilePath is the full path e.g. 'C:/medimage/addons/medimage-addon-ehr-medtech32-0.0.4.zip'
167 //Convert filename into one without extension
168 var possFileName = filename.replace(/.zip/i, "") + "/";
169
170 try {
171
172 fs.createReadStream(tmpFilePath).pipe(unzip.Extract({ path: targetAddonsFolder + tempDir }))
173 .on('close', function() {
174 console.log("Finished");
175
176 //Check if our files are one directory in
177 var dir = "";
178 var fileCnt = 0;
179 var dirCnt = 0;
180
181 fs.readdirSync(targetAddonsFolder + tempDir).forEach(file => {
182 if(verbose == true) console.log(file);
183 if(fs.lstatSync(targetAddonsFolder + tempDir + '/' + file).isDirectory()) {
184 if(verbose == true) console.log("Is a directory");
185 dir = file;
186 dirCnt ++;
187 } else {
188 if((file[0] == '.')||(file == filename)) {
189 if(verbose == true) console.log("Is a hidden file - not counted");
190 } else {
191 if(verbose == true) console.log("Is a file");
192 fileCnt ++;
193 }
194 }
195 })
196
197 if((fileCnt == 0)&&(dirCnt == 1)) {
198 //Yes at least one directory in
199 var dirName = dir;
200
201 //Now check if we're two directories in
202 var fileCnt = 0;
203 var dirCnt = 0;
204 var dir = "";
205
206 fs.readdirSync(targetAddonsFolder + tempDir + '/' + dirName).forEach(file => {
207 if(verbose == true) console.log(file);
208 if(fs.lstatSync(targetAddonsFolder + tempDir + '/' + dirName + '/' + file).isDirectory()) {
209 if(verbose == true) console.log("Is a directory");
210 dir = file;
211 dirCnt ++;
212 } else {
213 if(file[0] == '.') {
214 if(verbose == true) console.log("Is a hidden file - not counted");
215 } else {
216 if(verbose == true) console.log("Is a file");
217 fileCnt ++;
218 }
219 }
220 })
221
222 if((fileCnt == 0)&&(dirCnt == 1)) {
223 //Yes, we're two directories in. Append this to the output directory
224 dirName = dirName + "/" + dir;
225
226 }
227
228
229
230 } else {
231
232 var dirName = "";
233 }
234
235 console.log("Output dirname = '" + dirName +"'");
236
237
238 //Remove the temporary .zip file
239 fs.unlink(tmpFilePath, function(err) {
240 if(err) {
241 cb(err, null);
242 } else {
243 cb(null, dirName);
244 }
245 }); //Remove the zip file itself
246
247
248 });
249 } catch(err) {
250 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=There was a problem unzipping the file.&EXTENDED=" + err + " Expected folder:" + tempDir);
251 process.exit(0);
252 }
253
254
255
256}
257
258
259
260
261
262//With thanks from http://rajiev.com/download-an-extract-a-zip-file-with-node-js/
263function downloadAndUnzip(filename, url, opts, cb) {
264 var tmpFilePath = targetAddonsFolder + tempDir + filename;
265 fsExtra.ensureDir(targetAddonsFolder + tempDir, function(err) {
266 if(err) {
267 cb(err, null) // => null
268 } else {
269 // dir has now been created, including the directory it is to be placed in
270
271
272 var stream = request({url: url, forever: true, followAllRedirects: true });
273 var alreadyClosed = false;
274 stream.pipe(fs.createWriteStream(tmpFilePath)
275 .on('error', function(err) {
276 console.log("Error writing to file");
277 cb(err, null);
278 })
279 )
280 .on('close', function() {
281
282 console.log("Downloaded successfully!" + tmpFilePath);
283 if(alreadyClosed == false) {
284 alreadyClosed = true;
285
286 //Downloaded in here
287 unzipAndRemoveNew(filename, tmpFilePath, cb);
288
289 } else {
290 console.log("2nd close event");
291 }
292 });
293
294
295 }
296 })
297
298
299}
300
301function removeUnreadableChars(str)
302{
303 str = str.replace(/\&quot\;/g, '');
304 str = str.replace(/\&\#10\;/g, '');
305 return str;
306}
307
308
309function execCommands(commandArray, prepend, cb)
310{
311 //Asyncronously call each item, but in sequential order. This means the process could
312 //be doing something processor intensive without holding up the main server, but still allow
313 //each add-on to potentially process sequentially.
314
315 var commandStatus = "success";
316 var commandMessage = "";
317
318 async.eachOfSeries(commandArray,
319 // 2nd param is the function that each item is passed to
320 function(runBlock, cnt, callback){
321
322 var timeOut = 400000; //For a maximum worst case longest install time (400 seconds ~ 6 minutes)
323 var timedOut = false; //If we timed out - affects whether we report an error or keep the current warning/error status
324
325
326 if(commandArray[cnt].attempt) {
327 //Will make an attempt
328 var cmd = prepend + commandArray[cnt].attempt;
329
330 if(commandArray[cnt].timeoutAfterSeconds) {
331 timeOut = commandArray[cnt].timeoutAfterSeconds * 1000;
332
333 }
334
335 if(commandArray[cnt].warnOnTimeout) {
336 var warningMessage = commandArray[cnt].warnOnTimeout;
337 }
338 } else {
339
340 var cmd = prepend + commandArray[cnt];
341 }
342 console.log("Running command: " + cmd);
343
344 var runningOutput = "";
345
346 var outputStdOut = "";
347 var outputStdError = "";
348
349 try {
350
351
352
353
354 //Do it the better spawn way
355 cmds = cmd.split(" ");
356 var args = [];
357 var command = "";
358 if(cmds[0]) {
359 args = cmds;
360 }
361
362 //Now, based off platform, decide to run it slowly
363 var platform = getPlatform();
364 if((platform == "win32")||(platform == "win64")) {
365 command = "cmd.exe"
366 args.unshift('/low','/s','/c');
367
368 } else {
369 //Unix/mac
370 command = "nice";
371 args.unshift('-10'); //This is a priority of 10, which is pretty low.
372 }
373
374 var running = spawn(command, args);
375
376 running.stdout.on('data', (data) => {
377 if(verbose == true) console.log(data.toString());
378 outputStdOut += data.toString();
379
380 });
381
382 running.stderr.on('data', (data) => {
383 if(verbose == true) console.log(data.toString());
384 outputStdError += data.toString();
385 });
386
387
388
389 running.on('close', (code, signal) => {
390 if(code != 0) {
391
392 //Error. Code in 'code'
393 // node couldn't execute the command
394 var msg = "Command: " + cmd + ". Error:" + outputStdError;
395 console.log(msg);
396
397 //Send to the log anyway
398 console.log("Stdout:" + outputStdOut);
399 console.log("Stderr:" + outputStdError);
400
401
402 //Get rid of any strange chars before sending back to GUI
403 msg = entities.encodeNonUTF(msg);
404
405 //Remove newlines
406 msg = removeUnreadableChars(msg).substr(0,500);
407
408
409
410 if(timedOut == false) {
411 commandStatus = "error";
412 commandMessage = "The installation was not complete. There was a problem running one of the installation commands. " + msg;
413 } else {
414 //Keep the timeout message
415 }
416 callback(commandMessage, commandStatus);
417 } else {
418 //Success
419 console.log("Stdout from command:" + outputStdOut);
420 callback(null, commandStatus);
421
422 }
423 });
424
425
426 if(timeOut) {
427 //Kill the process after too long
428 setTimeout(function(){
429 if(commandArray[cnt].warnOnTimeout) {
430 commandMessage = commandMessage + commandArray[cnt].warnOnTimeout;
431 commandStatus = "warn";
432 } else {
433 commandMessage = commandMessage + " The installation command timed out and was not complete."
434 commandStatus = "error";
435
436 }
437 timedOut = true;
438
439 if((platform == 'win32')||(platform == 'win64')) {
440 console.log(running.pid + " timed out");
441 //This won't work: running.kill();, See: https://stackoverflow.com/questions/32705857/cant-kill-child-process-on-windows
442
443 exec('taskkill /pid ' + running.pid + ' /T /F');
444 } else {
445
446 console.log(running.pid + " timed out");
447 process.kill(running.pid, 'SIGHUP');
448 }
449
450
451 }, timeOut);
452 }
453
454
455
456 } catch(err) {
457 var msg = "There was a problem running the command " + cmd;
458 var ext = err;
459
460 console.log("Error:" + err);
461 console.log("Stdout:" + outputStdOut);
462 console.log("Stderr:" + outputStdError);
463
464 //Get rid of any strange chars
465 ext = entities.encodeNonUTF(ext);
466
467 //Remove newlines
468
469 ext = removeUnreadableChars(msg).substr(0,500);
470 commandMessage = "The installation was not complete. There was a problem running the one of the installation commands.&EXTENDED=" + cmd + " Error:" + ext;
471
472 commandStatus = "error";
473 callback(commandMessage, commandStatus);
474
475 }
476
477 }, //End of async eachOf single item
478 function(err){
479 // All tasks are done now
480 console.log("All tasks finished");
481 if(err) {
482 //Pass back status, and any error message
483 cb(err, commandStatus);
484 } else {
485 console.log('Completed all commands successfully!');
486 if(commandStatus == "warn") {
487 //Send back the warning in the 'error' field
488 cb(commandMessage, commandStatus);
489 } else {
490 cb(null, commandStatus);
491 }
492 }
493 }
494 ); //End of async eachOf all items
495
496
497}
498
499
500
501function openAndRunDescriptor(directory, opts)
502{
503 var commandStatus = "success"; //Assume success unless we know otherwise. This can be "warn", "error" or "success" at the end.
504 var commandMessage = ""; //We hold a running list of any warnings in this string, the get appended to each other.
505
506
507 //Change into the directory of the add-on
508 try {
509 process.chdir(directory);
510 } catch(err) {
511 return console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=This is not a directory.&EXTENDED=" + err);
512 process.exit(0);
513 }
514 var desc = directory + "/" + descriptorFile;
515 console.log("Checking installer file " + desc);
516
517 if(fs.existsSync(desc) == true) {
518 try {
519 var data = fsExtra.readJsonSync(desc);
520 } catch(err) {
521 console.log("Error: there was a problem in the medimage-installer .json file. " + err);
522 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=There was a problem in the medimage-installer .json file.&EXTENDED=" + err);
523 process.exit(0);
524
525 }
526
527
528 if(data) {
529 //Yes there is an installer script to run
530 if(data.installCommands) {
531
532 //Determine our current platform
533 var platform = getPlatform();
534 async.waterfall([
535 function(callback) {
536 console.log("Checking all platform commands");
537 if(data.installCommands.all) {
538 //Run through these commands always - all platforms
539 var prepend = "";
540 if((platform == "unix")||(platform == "mac")) {
541 if(opts.password != "") {
542 prepend = "echo \"" + opts.password + "\" | sudo -S ";
543 }
544 }
545 execCommands(data.installCommands.all, prepend, function(err, type) {
546 if(type == "warn") {
547 commandMessage = commandMessage + " " + err;
548 callback(null); //Don't pass along the error message
549 } else {
550 callback(err); //err could either be nothing or a genuine error
551 }
552 });
553 } else {
554 callback(null);
555 }
556 },
557 function(callback) {
558 console.log("Checking Win32 commands");
559 if((data.installCommands.win32) && (platform == "win32")) {
560 //Run through these commands on Win32
561 execCommands(data.installCommands.win32, "", function(err, type) {
562 if(type == "warn") {
563 commandMessage = commandMessage + " " + err;
564 callback(null); //Don't pass along the error message
565 } else {
566 callback(err); //err could either be nothing or a genuine error
567 }
568 });
569 } else {
570 callback(null);
571 }
572 },
573 function(callback) {
574 console.log("Checking Win64 commands");
575 if((data.installCommands.win64) && (platform == "win64")) {
576 //Run through these commands on Win64
577 execCommands(data.installCommands.win64, "", function(err, type) {
578 if(type == "warn") {
579 commandMessage = commandMessage + " " + err;
580 callback(null); //Don't pass along the error message
581 } else {
582 callback(err); //err could either be nothing or a genuine error
583 }
584 });
585 } else {
586 callback(null);
587 }
588 },
589 function(callback) {
590 console.log("Checking Unix commands");
591 if((data.installCommands.unix) && (platform == "unix")) {
592 //Run through these commands on unix/linux
593 if(opts.password != "") {
594 var prepend = "echo \"" + opts.password + "\" | sudo -S ";
595 } else {
596 var prepend = "";
597 }
598 execCommands(data.installCommands.unix, prepend, function(err, type) {
599 if(type == "warn") {
600 commandMessage = commandMessage + " " + err;
601 callback(null); //Don't pass along the error message
602 } else {
603 callback(err); //err could either be nothing or a genuine error
604 }
605 });
606 } else {
607 callback(null);
608 }
609 },
610 function(callback) {
611 console.log("Checking Mac commands");
612 if((data.installCommands.mac) && (platform == "mac")) {
613 //Run through these commands on mac
614 if(opts.password != "") {
615 var prepend = "echo \"" + opts.password + "\" | sudo -S ";
616 } else {
617 var prepend = "";
618 }
619 execCommands(data.installCommands.mac, prepend, function(err, type) {
620 if(type == "warn") {
621 commandMessage = commandMessage + " " + err;
622 callback(null, 'done'); //Don't pass along the error message
623 } else {
624 callback(err, 'done'); //err could either be nothing or a genuine error
625 }
626 });
627 } else {
628 callback(null, 'done');
629 }
630 }
631 ],
632 function (err, result) {
633 // result now equals 'done'
634 if(err) {
635 console.log("The installation was not complete.");
636 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=" + err);
637
638 process.exit(0);
639 } else {
640
641 //Success, installing - now display a standard message, unless the installer json knows differently
642 var mainMessage = "The installation was completed successfully!";
643 var extendedMessage = "";
644
645 if(data.successMessages) {
646
647
648 if(data.successMessages.all) {
649 //Any platform unspecific message? This will override the default.
650 if(data.successMessages.all.main) {
651 mainMessage = data.successMessages.all.main;
652 }
653 if(data.successMessages.all.extended) {
654 extendedMessage = data.successMessages.all.extended;
655 }
656
657 }
658
659 if(data.successMessages[platform]) {
660 //Any platform specific message? This will overwrite the one for all platforms.
661 if(data.successMessages[platform].main) {
662 mainMessage = data.successMessages[platform].main;
663 }
664 if(data.successMessages[platform].extended) {
665 extendedMessage = data.successMessages[platform].extended;
666 }
667
668 }
669 }
670
671 //If there were any warning messages, these get added into a warning html box
672 if(commandMessage != "") {
673 mainMessage = mainMessage + "<div style='padding-top:20px;'><div class='panel panel-warning'><div class='panel-heading'>Warning</div><div class='panel-body'>" + commandMessage + "</div></div></div>";
674 }
675
676 //Now we can attempt to clean up.
677 removeOldTemp(opts, function(err) {
678
679
680
681 if(err) {
682 //Could leave a warning
683 console.log("The installation was completed successfully, but the cleanup was not. ");
684 console.log("reloadConfig:true");
685 console.log("returnParams:?FINISHED=true&TABSTART=install-addon-tab&MSG=" + mainMessage + " Warning: the cleanup was not finished.&EXTENDED=You should check your add-ons folder and remove the " + tempDir + " folder manually. " + extendedMessage);
686 process.exit(0);
687 } else {
688
689
690
691
692 console.log(mainMessage);
693 console.log("reloadConfig:true");
694 console.log("returnParams:?FINISHED=true&TABSTART=install-addon-tab&MSG=" + mainMessage + "&EXTENDED=" + extendedMessage);
695 process.exit(0);
696
697 }
698
699 })
700
701 }
702 });
703
704 } else {
705 console.log("Warning: no valid install commands.");
706 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=No valid install commands.");
707 process.exit(0);
708
709 }
710 } else {
711 console.log("Warning: no valid JSON data found");
712 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=No valid JSON data found.");
713 process.exit(0);
714 }
715 } else {
716 console.log("Warning: no installer script was found");
717 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=No installer script was found.");
718 process.exit(0);
719 }
720
721
722}
723
724
725
726
727
728function renameFolder(filename, dirname, opts) {
729 //Input will be 'wound-0.7.3.zip'
730 //We want to convert '../wound-0.7.3' folder to '../wound' folder
731 //Trim up to 1st digit, or dot '.'. Then trim '-' chars at the end.
732
733 var nozipFilename = filename.replace(/.zip/i, "");
734
735 var dirIn = normalizeInclWinNetworks(targetAddonsFolder + tempDir);
736 if(dirname) {
737 dirIn = normalizeInclWinNetworks(targetAddonsFolder + tempDir + "/" + noTrailSlash(dirname));
738 }
739
740 //Read in the json descriptor to get an output folder name of the addon
741 var desc = normalizeInclWinNetworks(dirIn + "/" + descriptorFile);
742 console.log("Checking for file:" + desc);
743 var dirOut = "";
744 if(fs.existsSync(desc) == true) {
745 try {
746 var data = fsExtra.readJsonSync(desc);
747 if(data) {
748 dirOut = normalizeInclWinNetworks(targetAddonsFolder + data.name);
749 }
750 } catch(err) {
751 console.log("Error: there was a problem in the medimage-installer .json file.");
752 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=There was a problem in the medimage-installer .json file.&EXTENDED=" + err);
753 process.exit(0);
754
755 }
756 }
757
758 if(dirOut == "") {
759 console.log("Using filename to determine directory...");
760 //We will need to determine out own version based on the filename
761
762 var dirOut = filename.replace(/[0-9\.]+/g, "");
763 dirOut = dirOut.replace(/zip/i, "");
764 dirOut = targetAddonsFolder + dirOut.replace(/-$/, '');
765 }
766
767 dirIn = normalizeInclWinNetworks(dirIn);
768 dirOut = normalizeInclWinNetworks(dirOut);
769 console.log("Dir in=" + dirIn + "\nDir out=" + dirOut);
770 //fsExtra.move(dirIn, dirOut);
771
772 fsExtra.move(dirIn, dirOut, { overwrite: true }, function(err) { //overwrite: true
773 if (err) {
774 return console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=Could not rename the folder.&EXTENDED=" + err);
775 } else {
776 console.log('Success renaming!');
777 openAndRunDescriptor(dirOut, opts);
778 return;
779 }
780 });
781
782}
783
784function uninstall(addonName, opts)
785{
786 var dirOut = normalizeInclWinNetworks(targetAddonsFolder + addonName); //Absolute path to folder to delete
787
788 //Change into the directory of the add-on
789 try {
790 process.chdir(dirOut);
791 } catch(err) {
792 return console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=This is not a directory.&EXTENDED=" + err);
793 process.exit(0);
794 }
795
796
797 //Read in the json descriptor to get
798 var desc = dirOut + "/" + descriptorFile;
799 console.log("Checking for file:" + desc);
800
801
802
803 if(fs.existsSync(desc) == true) {
804 try {
805 var data = fsExtra.readJsonSync(desc);
806 } catch(err) {
807 console.log("Error: there was a problem in the medimage-installer .json file. " + err);
808 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=There was a problem in the medimage-installer .json file.&EXTENDED=" + err);
809 process.exit(0);
810
811 }
812
813
814 if(data) {
815 //Yes there is an uninstaller script to run
816 if(data.uninstallCommands) {
817
818 //Determine our current platform
819
820 var platform = getPlatform();
821 async.waterfall([
822 function(callback) {
823 console.log("Checking all platform commands");
824 if(data.uninstallCommands.all) {
825 var prepend = "";
826 if((platform == "unix")||(platform == "mac")) {
827 if(opts.password != "") {
828 prepend = "echo \"" + opts.password + "\" | sudo -S ";
829 }
830 }
831 //Run through these commands always - all platforms
832 execCommands(data.uninstallCommands.all, prepend, function(err) {
833 callback(err);
834 });
835 } else {
836 callback(null);
837 }
838 },
839 function(callback) {
840 console.log("Checking Win32 commands");
841 if((data.uninstallCommands.win32) && (platform == "win32")) {
842 //Run through these commands win32
843 execCommands(data.uninstallCommands.win32, "", function(err) {
844 callback(err);
845 });
846 } else {
847 callback(null);
848 }
849 },
850 function(callback) {
851 console.log("Checking Win64 commands");
852 if((data.uninstallCommands.win64) && (platform == "win64")) {
853 //Run through these commands win64
854 execCommands(data.uninstallCommands.win64, "", function(err) {
855 callback(err);
856 });
857 } else {
858 callback(null);
859 }
860 },
861 function(callback) {
862 console.log("Checking Unix commands");
863 if((data.uninstallCommands.unix) && (platform == "unix")) {
864 //Run through these commands unix/linux
865 if(opts.password != "") {
866 var prepend = "echo \"" + opts.password + "\" | sudo -S ";
867 }
868 execCommands(data.uninstallCommands.unix, prepend, function(err) {
869 callback(err);
870 });
871 } else {
872 callback(null);
873 }
874 },
875 function(callback) {
876 console.log("Checking Mac commands");
877 if((data.uninstallCommands.mac) && (platform == "mac")) {
878 //Run through these commands mac
879 if(opts.password != "") {
880 var prepend = "echo \"" + opts.password + "\" | sudo -S ";
881 }
882 execCommands(data.uninstallCommands.mac, prepend, function(err) {
883 callback(err, 'done');
884 });
885 } else {
886 callback(null);
887 }
888 }
889 ],
890 function (err, success) {
891 // result now equals 'done'
892 if(err) {
893 console.log("The uninstallation was not complete.");
894 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=The uninstallation was not complete.&EXTENDED=" + err);
895 process.exit(0);
896 } else {
897
898 //Change back out of our folder
899 process.chdir(targetAddonsFolder);
900
901 //Now clear out the folder
902 console.log("Removing folder:" + dirOut);
903 if(((platform == "unix")||(platform == "mac"))&&(opts.password != "")) {
904 var rmrf = [ "echo \"" + opts.password + "\" | sudo -S rm -rf " + dirOut ]; //Do an OS level sudo rm dir
905 execCommands(rmrf, "", function(err) {
906 if(err) {
907 console.log("The uninstallation was not complete.");
908 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=The uninstallation was not complete.&EXTENDED=" + err);
909 } else {
910 console.log("The uninstallation was completed successfully!");
911 console.log("reloadConfig:true");
912 console.log("returnParams:?FINISHED=true&TABSTART=install-addon-tab&MSG=The uninstallation was completed successfully!");
913 }
914 process.exit(0);
915 });
916 } else {
917
918 fsExtra.remove(dirOut, function(err) {
919 if(err) {
920 console.log("The uninstallation was not complete.");
921 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=The uninstallation was not complete.&EXTENDED=" + err);
922
923 } else {
924 console.log("The uninstallation was completed successfully!");
925 console.log("reloadConfig:true");
926 console.log("returnParams:?FINISHED=true&TABSTART=install-addon-tab&MSG=The uninstallation was completed successfully!");
927
928
929 }
930 process.exit(0);
931
932 });
933
934
935
936 }
937 }
938 });
939
940 }
941 } else {
942 console.log("Warning: no valid JSON data found");
943 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=Warning: no valid JSON datafound");
944 process.exit(0);
945 }
946 } else {
947 console.log("Warning: no valid JSON data found");
948 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=Warning: no valid JSON data found");
949 process.exit(0);
950 }
951
952
953
954
955}
956
957
958function removeOldTemp(opts, cb)
959{
960 //Remove the old temporary installer folder
961 //Change back out of our folder
962 var platform = getPlatform();
963
964 process.chdir(targetAddonsFolder);
965 var dirOut = targetAddonsFolder + tempDir;
966
967 if(((platform == "unix")||(platform == "mac"))&&(opts.password != "")) {
968 var rmrf = [ "echo \"" + opts.password + "\" | sudo -S rm -rf " + dirOut ]; //Do an OS level sudo rm dir
969 execCommands(rmrf, "", function(err) {
970 if(err) {
971 console.log("The installation was not complete.");
972 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=The installation was not complete. The old temporary folder could not be removed.&EXTENDED=" + err);
973 process.exit(0);
974 } else {
975 cb(null);
976 }
977 });
978 } else {
979
980 fsExtra.remove(dirOut, function(err) {
981 if(err) {
982 console.log("The installation was not complete.");
983 console.log("returnParams:?FINISHED=false&TABSTART=install-addon-tab&MSG=The installation was not complete. The old temporary folder could not be removed.&EXTENDED=" + err);
984 process.exit(0);
985
986 } else {
987 cb(null);
988 }
989 });
990
991 }
992
993}
994
995
996
997
998havePermission(configFile, function(err, ret) {
999
1000 if(err) {
1001 console.log("returnParams:?FINISHED=false&MSG=Sorry you do not have permissions to install add-ons. Please contact your administrator.");
1002
1003 } else {
1004
1005 if(ret == true) {
1006 //Yes we have permission to install
1007 if(process.argv[2]) {
1008
1009 var opts = queryString.parse(decodeURIComponent(process.argv[2]));
1010
1011 if((opts.zipfileURL)&&(opts.zipfileURL != "")) {
1012 //If passing in a zip file url to install
1013 var zipfileURL = opts.zipfileURL;
1014
1015
1016
1017 var parsed = url.parse(zipfileURL);
1018 var filename = path.basename(parsed.pathname);
1019
1020 console.log("Filename: " + filename + " URL: " + zipfileURL);
1021 //Get the filename of the path to the URL
1022
1023 try {
1024 removeOldTemp(opts, function() {
1025
1026 downloadAndUnzip(filename, zipfileURL, opts, function(err, dirname) {
1027 console.log("Files unzipped");
1028
1029 renameFolder(filename, dirname, opts);
1030
1031 });
1032 });
1033 } catch(err) {
1034 console.log("returnParams:?FINISHED=false&MSG=The installation was not complete.&EXTENDED=" + err);
1035 process.exit(0);
1036
1037 }
1038 }
1039
1040 if(opts.uninstall) {
1041 try {
1042 uninstall(opts.uninstall, opts);
1043 } catch(err) {
1044 console.log("returnParams:?FINISHED=false&MSG=The installation was not complete.&EXTENDED=" + err);
1045 process.exit(0);
1046
1047 }
1048 }
1049
1050 if((!opts.uninstall)&&(!opts.zipfileURL)) {
1051 console.log("You should enter a 'zipfileURL' or 'uninstall' param.");
1052 console.log("returnParams:?FINISHED=false&MSG=Sorry, we don't seem to have an Add-on requested.");
1053 process.exit(0);
1054 }
1055
1056
1057
1058 } else {
1059 console.log("Usage: node install-addon.js zipfileURL%3Dhttp://url.To.Zip/file/name.zip (with urlencoded URL)");
1060
1061 }
1062 } else {
1063 //No permission, sorry
1064 console.log("returnParams:?FINISHED=false&MSG=Sorry, you don't have permission to install or uninstall add-ons. Please check your config.json.");
1065 }
1066 }
1067});