Install.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. Lib::loadClass('UI');
  4. //TODO install nie kopiuje aktualnej /config/.config_base_structure.php @2017-09-24 bindera - sprawdzone na medicalu
  5. class Route_Install extends RouteBase {
  6. public function handleAuth() {
  7. if (!User::logged()) {
  8. throw new HttpException('Unauthorized', 401);
  9. }
  10. if (!User::isAdmin()) {
  11. throw new HttpException('Unauthorized - only for administrators', 401);
  12. }
  13. }
  14. public function defaultAction() {
  15. UI::gora();
  16. UI::menu();
  17. $this->menu();
  18. UI::setTitleJsTag("Install");
  19. UI::dol();
  20. }
  21. public function menu() {
  22. $serversList = $this->fetchActiveLicences();
  23. ?>
  24. <div class="jumbotron">
  25. <div class="container">
  26. <form class="form-inline" method="GET">
  27. <input type="hidden" name="_route" value="Install" />
  28. <input type="hidden" name="_task" value="createApp" />
  29. <label>Przygotuj kod źródłowy do aktualizacji na serwerze klienta:</label>
  30. <select id="servers_list" class="form-control" name="licence_id">
  31. <?php foreach ($serversList as $srv) : ?>
  32. <option value="<?php echo $srv->ID; ?>">[<?php echo $srv->ID; ?>] <?php echo $srv->domain; ?></option>
  33. <?php endforeach; ?>
  34. </select>
  35. <button type="submit" id="fldSbmtBtn" class="btn btn-primary" autocomplete="off">
  36. Generuj
  37. </button>
  38. <div id="servers_list_react"></div>
  39. </form>
  40. </div>
  41. </div>
  42. <script type="text/javascript">
  43. jQuery(document).ready(function () {
  44. jQuery('#fldSbmtBtn').on('click', function () {
  45. jQuery(this).text(jQuery(this).text() + '...').attr('disabled', 'disabled');
  46. jQuery(this).parent().submit();
  47. })
  48. });
  49. </script>
  50. <?php
  51. echo UI::h('script', ['src'=>"static/vendor.js", 'type'=>"text/javascript"]);
  52. // echo UI::h('script', ['src'=>"https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js", 'type'=>"text/javascript"]);
  53. // echo UI::h('script', ['src'=>"https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js", 'type'=>"text/javascript"]);
  54. // echo UI::h('script', ['src'=>"https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap-typeahead/0.10.4/react-bootstrap-typeahead.js", 'type'=>"text/javascript"]);
  55. $jsonServersList = array_values(array_map(
  56. function ($srv) {
  57. return [
  58. 'id' => $srv->ID,
  59. 'label' => "{$srv->domain} [{$srv->ID}]"
  60. ];
  61. },
  62. $serversList
  63. ));
  64. echo UI::h('script', ['type'=>"text/javascript"], "
  65. (function(global){
  66. if (!global.p5VendorJs) { console.warn('Brak p5VendorJs'); return; }
  67. if (!global.p5VendorJs.React) { console.warn('Brak p5VendorJs.React'); return; }
  68. if (!global.p5VendorJs.ReactDOM) { console.warn('Brak p5VendorJs.ReactDOM'); return; }
  69. if (!global.p5VendorJs.Typeahead) { console.warn('Brak p5VendorJs.Typeahead'); return; }
  70. const React = global.p5VendorJs.React;
  71. const ReactDOM = global.p5VendorJs.ReactDOM;
  72. const Typeahead = global.p5VendorJs.Typeahead;
  73. var options = ".json_encode($jsonServersList).";
  74. var selected = [];
  75. var onInputChange = function (query) {
  76. // console.log('onInputChange:: query', query);
  77. }
  78. var onChange = function (value) {
  79. // console.log('onChange:: value', value);
  80. if (value.length > 0) {
  81. var id = value[0]['id'];
  82. if (id > 0) {
  83. document.getElementById('servers_list').value = id;
  84. }
  85. }
  86. }
  87. ReactDOM.render(
  88. React.createElement(Typeahead, {
  89. options: options,
  90. emptyLabel: 'Brak danych',
  91. placeholder: 'Wybierz serwer',
  92. selected: selected,
  93. // onInputChange: onInputChange,
  94. onChange: onChange,
  95. }, null),
  96. document.getElementById('servers_list_react')
  97. );
  98. })(window);
  99. ");
  100. }
  101. public function createAppAction() {
  102. session_write_close();
  103. $args = array();
  104. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  105. UI::gora();
  106. UI::menu();
  107. UI::setTitleJsTag("Install");
  108. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  109. try {
  110. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  111. $this->validateAppLicenceInfo($appLicenceInfo);
  112. } catch (Exception $e) {
  113. $this->_endWithException($e);
  114. }
  115. // $this->generateApp($appLicenceInfo->installPath, $appLicenceInfo->domains);
  116. //DBG::_(true, true, "appLicenceInfo", $appLicenceInfo, __CLASS__, __FUNCTION__, __LINE__);
  117. if ('_generateEncryptedSource' === V::get('_postTask', '', $_POST)) {
  118. echo '<div class="container">';
  119. echo '<h4>' . "Generowanie..." . '</h4>';
  120. echo '<div style="border:1px solid silver; max-height:400px; overflow-y:scroll">';
  121. try {
  122. $this->validateAppLicenceInfo($appLicenceInfo);
  123. $this->generateApp($appLicenceInfo->installPath, $appLicenceInfo->domains);
  124. } catch (Exception $e) {
  125. echo '</div></div>';// .container/ scroll
  126. $this->_endWithException($e);
  127. }
  128. echo '</div>';// .container
  129. UI::alert('success', "<strong>Gotowe</strong> Aplikacja znajduje się w katalogu {$appLicenceInfo->installFolderName}");
  130. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  131. }
  132. if ('newGenerateApp' === V::get('_postTask', '', $_POST)) {
  133. $this->newGenerateApp($appLicenceInfo);
  134. }
  135. if ('updateAndSendToRemoteTestDir' === V::get('_postTask', '', $_POST)) {
  136. echo '<details><summary style="cursor:pointer">aktualizuj werjsę, szyfruj i wyślij do testowego katalogu na serwerze</summary>';
  137. try {
  138. $idLicence = V::get('licence_id', 0, $_POST, 'int');
  139. $appLicenceInfo = $this->getAppLicenceInfo($idLicence);
  140. $this->validateAppLicenceInfo($appLicenceInfo);
  141. $this->gitResetHard($appLicenceInfo->installPath, $appLicenceInfo->projects);
  142. flush();
  143. $this->_encodeSource($appLicenceInfo->installPath, $appLicenceInfo->domains);
  144. flush();
  145. $this->_sendToRemoteTestDir($appLicenceInfo);
  146. } catch (Exception $e) {
  147. DBG::log($e);
  148. UI::alert('danger', $e->getMessage());
  149. }
  150. echo '</details>';
  151. $testDirUrl = "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/";
  152. UI::alert('info', UI::h('p', [], [
  153. "testowy katalog zaktualizowany - ",
  154. UI::h('a', [ 'href' => $testDirUrl, 'target' => "_blank" ], $testDirUrl),
  155. ]));
  156. flush();
  157. }
  158. // echo UI::hButtonPost("TODO: Generuj z p5.git", [
  159. // 'class' => "btn btn-md btn-primary",
  160. // 'data' => [
  161. // '_postTask' => "newGenerateApp",
  162. // 'licence_id' => $appLicenceInfo->ID,
  163. // ],
  164. // ]);
  165. echo UI::h('div', [ 'class' => "jumbotron" ], [
  166. UI::h('div', [ 'class' => "container" ], [
  167. UI::h('h3', [], "Generowanie aplikacji dla licencji {$appLicenceInfo->ID}"),
  168. UI::h('p', [], "Licencja dla domen: " . implode(', ', $appLicenceInfo->domains)),
  169. UI::h('p', [], "Katalog z zakodowanymi plikami: {$appLicenceInfo->installFolderName}"),
  170. UI::hButtonPost("Generuj", [
  171. 'class' => "btn btn-primary",
  172. 'data' => [
  173. '_postTask' => '_generateEncryptedSource',
  174. 'licence_id' => $appLicenceInfo->ID,
  175. ]
  176. ]),
  177. (!$appLicenceInfo->installFolderGitExists)
  178. ? UI::h('div', [ 'class' => "alert alert-info" ], "Katalog nie istnieje - wygeneruj aplikację")
  179. : UI::h('div', [ 'class' => "alert alert-info", 'style' => "margin-top:10px" ], [
  180. UI::h('p', [], "Katalog istnieje i zawiera już repozytorium git: "),
  181. UI::h('p', [], [
  182. UI::hButtonPost("aktualizuj werjsę, szyfruj i wyślij do testowego katalogu na serwerze", [
  183. 'class' => "btn btn-xs btn-primary",
  184. 'data' => [
  185. '_postTask' => "updateAndSendToRemoteTestDir",
  186. 'licence_id' => $appLicenceInfo->ID,
  187. ],
  188. ]),
  189. ]),
  190. UI::h('p', [ 'style' => "margin-left:20px" ], [
  191. UI::h('a', [
  192. 'href' => "index.php?_route=Install&_task=gitResetHard&licence_id={$appLicenceInfo->ID}",
  193. 'target' => "_blank",
  194. 'class' => "btn btn-xs btn-default"
  195. ], "aktualizuj werjsę</a> (git reset --hard, git pull, set SE/VERSION - tak samo co 'rm -rf; git clone', ale szybciej)"),
  196. ]),
  197. UI::h('p', [ 'style' => "margin-left:20px" ], [
  198. UI::h('a', [
  199. 'href' => "index.php?_route=Install&_task=encodeSource&licence_id={$appLicenceInfo->ID}",
  200. 'target' => "_blank",
  201. 'class' => "btn btn-xs btn-default"
  202. ], "encode files"),
  203. ]),
  204. UI::h('p', [ 'style' => "margin-left:20px" ], [
  205. UI::h('a', [
  206. 'href' => "index.php?_route=Install&_task=sendToRemoteTestDir&licence_id={$appLicenceInfo->ID}",
  207. 'target' => "_blank",
  208. 'class' => "btn btn-xs btn-default"
  209. ], "send encoded files to remote server test folder (generates ssh key if not set)"),
  210. ]),
  211. UI::h('p', [ 'style' => "margin-top:30px" ], [
  212. "Test online: ",
  213. UI::h('a', [
  214. 'target' => "_blank",
  215. 'href' => "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/"
  216. ], "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/"),
  217. ]),
  218. "<br> - ",
  219. UI::h('a', [
  220. 'href' => "index.php?_route=Install&_task=upgradeRemoteFromTestDir&licence_id={$appLicenceInfo->ID}",
  221. 'onclick' => "return confirm('Uruchomić aktualizację SE na https://{$appLicenceInfo->mainServer}/SE/?')",
  222. 'target' => "_blank",
  223. 'class' => "btn btn-xs btn-warning"
  224. ], "UPGRADE Production folder from uploaded dir: ~/se.encrypted.upgrade/"),
  225. ]),
  226. ]),
  227. ]);
  228. ?>
  229. <script type="text/javascript">
  230. jQuery(document).ready(function () {
  231. jQuery('#fldSbmtBtn').on('click', function () {
  232. jQuery(this).text(jQuery(this).text() + '...').attr('disabled', 'disabled');
  233. jQuery(this).parent().submit();
  234. })
  235. });
  236. </script>
  237. <?php
  238. UI::dol();
  239. }
  240. public function gitResetHardAction() {
  241. session_write_close();
  242. $args = array();
  243. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  244. UI::gora();
  245. UI::menu();
  246. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  247. try {
  248. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  249. $this->validateAppLicenceInfo($appLicenceInfo);
  250. UI::startContainer();
  251. $this->gitResetHard($appLicenceInfo->installPath, $appLicenceInfo->projects);
  252. UI::endContainer();
  253. } catch (Exception $e) {
  254. $this->_endWithException($e);
  255. }
  256. UI::dol();
  257. }
  258. public function gitResetHard($installPath, $projects = []) {
  259. if (empty($installPath)) throw new Exception("Install path not found");
  260. $cmds = array();
  261. $cmds[] = "git reset --hard";
  262. $cmds[] = "git pull";
  263. $cmds[] = "echo `git show-ref --head|head -1|head -c 8` > SE/VERSION ";
  264. $hasError = false;
  265. foreach ($cmds as $cmd) {
  266. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  267. if (0 !== $ret) $hasError = true;
  268. DBG::nicePrint($out, "cmd: `{$cmd}` (return:{$ret})");
  269. }
  270. foreach ($projects as $projectName) {
  271. $cmd = "ls -l SE/projects/{$projectName} | wc -l";
  272. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  273. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  274. if (!empty($out) && '0' !== trim($out[0])) {
  275. // $cmd = "git submodule update SE/projects/{$projectName}";
  276. $cmd = "cd SE/projects/{$projectName} && git reset --hard"; // revert encode source - checkout to last commit (need update)
  277. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  278. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  279. }
  280. $cmd = "git submodule update --init SE/projects/{$projectName}"; // checkout to current commit
  281. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  282. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  283. }
  284. if (!$hasError) {
  285. UI::alert('success', "OK");
  286. } else {
  287. UI::alert('danger', "errors");
  288. }
  289. }
  290. public function encodeSourceAction() {
  291. session_write_close();
  292. $args = array();
  293. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  294. UI::gora();
  295. UI::menu();
  296. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  297. try {
  298. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  299. $this->validateAppLicenceInfo($appLicenceInfo);
  300. $this->_encodeSource($appLicenceInfo->installPath, $appLicenceInfo->domains);
  301. } catch (Exception $e) {
  302. $this->_endWithException($e);
  303. }
  304. UI::dol();
  305. }
  306. public function _encodeSource($installPath, $domains) {
  307. UI::startContainer();
  308. $this->encodeSourceFiles($installPath, $domains, $dbg = true);
  309. // try {
  310. // $this->encodeSourceFiles($appLicenceInfo->installPath, $appLicenceInfo->domains, $dbg = false);
  311. // UI::alert('success', "OK");
  312. // } catch (Exception $e) {
  313. // UI::alert('danger', $e->getMessage());
  314. // }
  315. UI::endContainer();
  316. }
  317. // @usage: Router::getRoute('Install')->encodeSourceFiles($installPath = '/path_to_git_repo', $domains = [ 'domain.com', 'localhost' ], $dbg = false);
  318. public function encodeSourceFiles($installPath, $domains, $dbg = false) {
  319. if (empty($installPath)) throw new Exception("Install path not found");
  320. if (empty($domains)) throw new Exception("Domains not found");
  321. $phpVersionsForSgencoder = '--phpversion 5.5 --phpversion 5.6';// encode for PHP 5.x (currently supported PHP 5.0-5.6)
  322. if ('1' == V::get('DBG_ENCODER_HELP', '', $_REQUEST)) {// encoder help
  323. $cmd = "cd {$installPath}/SE && /Applications/SourceGuardian.app/Contents/MacOS/sgencoder --help ";
  324. $out = ''; $ret = '';
  325. exec($cmd, $out, $ret);
  326. DBG::nicePrint($out, "cmd: `{$cmd}` (return:{$ret})");
  327. exit;
  328. }
  329. $domainEncodePhpFiles = [
  330. 'ant.php',
  331. 'api.php',
  332. 'budynki.php',
  333. 'index-ajax.php',
  334. 'index.php',
  335. 'procesy5.php',
  336. 'session-expire.php',
  337. 'test-sync.php',
  338. 'wfs-data.php',
  339. 'wfs-qgis.php',
  340. 'wfs.php',
  341. ];
  342. $cmd = "find . -name '*.php' ";
  343. $out = ''; $ret = '';
  344. exec("cd {$installPath}/SE && {$cmd}", $out, $ret);
  345. if ($dbg) DBG::nicePrint($out, "cmd: `{$cmd}` (return:{$ret})");
  346. else DBG::log($out, 'array', "cmd: `{$cmd}` (return:{$ret})");
  347. if (0 !== $ret) throw new Exception("Error at find php files");
  348. if (empty($out)) throw new Exception("No php files found");
  349. $allPhpFiles = array_map(function ($phpFilePath) {
  350. return ('./' == substr($phpFilePath, 0, 2))? substr($phpFilePath, 2) : $phpFilePath;
  351. }, $out);
  352. $freeEncodePhpFiles = array_filter($allPhpFiles, function ($phpFilePath) use ($domainEncodePhpFiles) {
  353. if ('se-lib/Vendor/' === substr($phpFilePath, 0, strlen('se-lib/Vendor/'))) return false; // SKIP se-lib/Vendor/*
  354. if ('.ini.php' === substr($phpFilePath, -1 * strlen('.ini.php'))) return false; // SKIP *.ini.php
  355. return (!in_array($phpFilePath, $domainEncodePhpFiles));
  356. });
  357. DBG::log($freeEncodePhpFiles, 'array', "\$freeEncodePhpFiles");
  358. if (empty($freeEncodePhpFiles)) throw new Exception("No php files to encode");
  359. $cmdTempl = "cd {$installPath}/SE && /Applications/SourceGuardian.app/Contents/MacOS/sgencoder {$phpVersionsForSgencoder} -b- ";
  360. $cmdDomainEncodeDomainsTempl = " --domain " . implode(" --domain ", array_merge($domains, ['localhost']));
  361. $cmdDomainEncodeFilesTempl = " " . implode(" ", $domainEncodePhpFiles);
  362. $cmdFreeEncodeFilesTempl = " " . implode(" ", $freeEncodePhpFiles);
  363. $cmds = [
  364. $cmdTempl . $cmdDomainEncodeDomainsTempl . $cmdDomainEncodeFilesTempl,
  365. $cmdTempl . $cmdFreeEncodeFilesTempl,
  366. ];
  367. $returnValues = [];
  368. foreach ($cmds as $cmd) {
  369. $out = ''; $ret = '';
  370. exec($cmd, $out, $ret);
  371. $encoderSummaryLine = end($out);
  372. $returnValues[] = $encoderSummaryLine;
  373. if ($dbg) {
  374. DBG::nicePrint([$cmd], "cmd");
  375. DBG::nicePrint($out, "return: '{$ret}'");
  376. // DBG::nicePrint([$encoderSummaryLine], "cmd last line");
  377. }
  378. else DBG::log([$cmd, $out], 'array', "cmd return:'{$ret}'");
  379. // if (0 !== $ret) throw new Exception("Error at encode files");
  380. if (empty($out)) throw new Exception("No output for encode files command");
  381. }
  382. $statusInfo = array_reduce($returnValues, function ($ret, $encoderSummaryLine) {
  383. DBG::log([$ret, $encoderSummaryLine], 'array', "DBG reduce [\$ret, \$encoderSummaryLine]");
  384. $matches = [];
  385. preg_match_all('/(\d+) files, (\d+) processed, (\d+) errors/', $encoderSummaryLine, $matches, PREG_SET_ORDER, 0);
  386. return [
  387. 'files' => $ret['files'] + (int)$matches[0][1],
  388. 'processed' => $ret['processed'] + (int)$matches[0][2],
  389. 'errors' => $ret['errors'] + (int)$matches[0][3],
  390. ];
  391. }, [
  392. 'files' => 0,
  393. 'processed' => 0,
  394. 'errors' => 0,
  395. ]);
  396. if ($statusInfo['errors'] === 0 && $statusInfo['files'] > 0) {
  397. if ($dbg) UI::alert('success', "{$statusInfo['files']} files, {$statusInfo['processed']} processed, {$statusInfo['errors']} errors");
  398. } else {
  399. if ($dbg) UI::alert('danger', "{$statusInfo['files']} files, {$statusInfo['processed']} processed, {$statusInfo['errors']} errors");
  400. else throw new Exception("{$statusInfo['files']} files, {$statusInfo['processed']} processed, {$statusInfo['errors']} errors");
  401. }
  402. }
  403. public function getAppLicenceInfo($idLicence) {
  404. $idLicence = intval($idLicence);
  405. if (empty($idLicence)) throw new Exception("Nie wybrano serwera/licencji.");
  406. //DBG::_(true, true, 'idLicence', $idLicence, __CLASS__, __FUNCTION__, __LINE__);
  407. $appLicenceInfo = (object)$this->fetchAppLicenceInfo($idLicence);
  408. $appLicenceInfo->domains = $this->fetchDomainsByLicenceId($idLicence);
  409. $installRootPath = '/Library/Server/Web/Data/Sites/Default/PLIKI/SES_PROCESY5_A';
  410. $appLicenceInfo->installFolderName = "{$idLicence}_upgrade_SE_source_encrypted";
  411. $appLicenceInfo->installPath = "{$installRootPath}/{$appLicenceInfo->installFolderName}";
  412. //DBG::_(true, true, 'appLicenceInfo', $appLicenceInfo, __CLASS__, __FUNCTION__, __LINE__);
  413. if (empty($appLicenceInfo->domains)) throw new Exception("Domains not found."); // TODO: mv to validate
  414. $appLicenceInfo->installFolderExists = file_exists("{$appLicenceInfo->installPath}/SE");
  415. $appLicenceInfo->installFolderGitExists = file_exists("{$appLicenceInfo->installPath}/.git");
  416. $appLicenceInfo->projects = []; // TODO: get from db
  417. if (79 == $idLicence) { // bravecom.procesy5.pl
  418. $appLicenceInfo->projects = [ 'bravecare' ];
  419. } else if (80 == $idLicence) { // bravecom.yellowgroup.pl
  420. $appLicenceInfo->projects = [ 'bocian' ];
  421. } else if (81 == $idLicence) { // bocian.procesy5.pl
  422. $appLicenceInfo->projects = [ 'bocian' ];
  423. } else if (67 == $idLicence) { // bocian.procesy5.pl
  424. $appLicenceInfo->projects = [ 'bocian' ];
  425. }
  426. return $appLicenceInfo;
  427. }
  428. public function validateAppLicenceInfo($appLicenceInfo) {
  429. if (empty($appLicenceInfo->ID)) throw new Exception("Nie wybrano serwera/licencji.");
  430. if (empty($appLicenceInfo->domains)) throw new Exception("Domains not found");
  431. if (empty($appLicenceInfo->installPath)) throw new Exception("Install path not found");
  432. }
  433. public function generateApp($installPath, $domains, $projects = []) {
  434. $cmds = array();
  435. $cmds[] = "if [ -d {$installPath} ] ; then rm -rf '{$installPath}'; fi";
  436. $cmds[] = "mkdir {$installPath}";
  437. $cmds[] = "cd {$installPath} && git clone --depth 1 ssh://git@biuro.biall-net.pl:2222/plabudda/se.git .";
  438. $cmds[] = "cd {$installPath} && echo `git show-ref --head|head -1|head -c 8` > SE/VERSION ";
  439. foreach ($cmds as $cmd) {
  440. V::exec($cmd, $out, $ret);
  441. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  442. }
  443. foreach ($projects as $projectName) {
  444. $cmd = "ls -l SE/projects/{$projectName} | wc -l";
  445. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  446. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  447. if (!empty($out) && '0' !== trim($out[0])) {
  448. // $cmd = "git submodule update SE/projects/{$projectName}";
  449. $cmd = "cd SE/projects/{$projectName} && git reset --hard"; // revert encode source - checkout to last commit (need update)
  450. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  451. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  452. }
  453. $cmd = "git submodule update --init SE/projects/{$projectName}"; // checkout to current commit
  454. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  455. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  456. }
  457. $this->_encodeSource($installPath, $domains);
  458. // 1763: $exec='cd '.$installer_dir.' && /Applications/SourceGuardian.app/Contents/MacOS/sgencoder -b-
  459. // '.INSTALL_SES_PROCESY_A::get_same_domains_for_install($h->SERVER_ADDRESS_SHORT).'
  460. // -r *.php
  461. // -x superedit-DB_PROCEDURES_CREATE.php
  462. // -x INI.php
  463. // -x .config_base_structure.php
  464. // ';
  465. //
  466. // INSTALL_SES_PROCESY_A::get_same_domains_for_install($h->SERVER_ADDRESS_SHORT):
  467. // $res2=DB::query("select SERVER_ADDRESS_SHORT from SES_PROCESY5_A where SERVER_ADDRESS_IP='".$h->SERVER_ADDRESS_IP."'");
  468. // while($h2=DB::fetch($res2)) {
  469. // $domain[]=' --domain '.$h2->SERVER_ADDRESS_SHORT;
  470. // ssh server@biuro.galeriaprzymorze.eu: PHP 5.5.20
  471. // ssh server@biuro.biall-net.pl
  472. // cd /Users/plabudda/procesy5-install-galeriaprzymorze.eu/
  473. // sudo chown -R server:admin SE/
  474. // /Applications/SourceGuardian.app/Contents/MacOS/sgencoder --phpversion 5.5 -b- --domain galeriaprzymorze.eu -r SE/*.php SE/se-lib/*.php SE/se-lib/*/*.php SE/se-lib/*/*/*.php SE/procesy/*.php SE/odt2xhtml/*.php -x superedit-DB_PROCEDURES_CREATE.php -x INI.php -x .config_base_structure.php
  475. }
  476. public function fetchActiveLicences() {
  477. $activeLic = array();
  478. $sql = "
  479. select l.`ID`
  480. , l.`SERVER_ADDRESS`
  481. , l.`SERVER_ADDRESS_SHORT` as domain -- domain for sgencoder
  482. , l.`SERVER_ADDRESS_IP`
  483. from `SES_PROCESY5_A` l
  484. where 1=1
  485. -- TODO: and l.`A_STATUS` in('NORMAL','WAITING')
  486. order by l.`ID` DESC
  487. ";
  488. $rows = DB::getPDO()->fetchAll($sql);
  489. foreach ($rows as $row) {
  490. $r = (object)$row;
  491. $activeLic[$r->ID] = $r;
  492. }
  493. return $activeLic;
  494. }
  495. public function fetchDomainsByLicenceId($licenceId) {
  496. $domains = array();
  497. $sql = "
  498. select g.`SERVER_ADDRESS_SHORT`, g.`SERVER_ADDRESS`
  499. from `SES_PROCESY5_A` g
  500. where g.`SERVER_ADDRESS_IP`=(select l.`SERVER_ADDRESS_IP`
  501. from `SES_PROCESY5_A` l
  502. where l.`ID`='{$licenceId}'
  503. -- TODO: and l.`A_STATUS` in('NORMAL','WAITING')
  504. )
  505. -- TODO: and g.`A_STATUS` in('NORMAL','WAITING')
  506. ";
  507. $rows = DB::getPDO()->fetchAll($sql);
  508. foreach ($rows as $row) {
  509. $r = (object)$row;
  510. $domains[] = $r->SERVER_ADDRESS_SHORT;
  511. if ($r->SERVER_ADDRESS != $r->SERVER_ADDRESS_SHORT) {
  512. $domains[] = $r->SERVER_ADDRESS;
  513. }
  514. }
  515. return $domains;
  516. }
  517. public function fetchMainServerByLicenceId($licenceId) {
  518. return DB::getPDO()->fetchValue("
  519. select g.`SERVER_ADDRESS`
  520. from `SES_PROCESY5_A` g
  521. where g.`ID`='{$licenceId}'
  522. -- TODO: and g.`A_STATUS` in('NORMAL','WAITING')
  523. ");
  524. }
  525. public function fetchAppLicenceInfo($licenceId) {
  526. $licenceInfo = null;
  527. $sql = "
  528. select g.ID
  529. , g.SERVER_ADDRESS as mainServer
  530. , g.ADMIN_USERNAME as rootLogin
  531. , g.ADMIN_USERNAME_PASSWD as rootPassword
  532. , g.SSH_PORT as sshPort
  533. from SES_PROCESY5_A g
  534. where g.`ID`=:id_licence
  535. -- TODO: and g.A_STATUS in('NORMAL','WAITING')
  536. ";
  537. $all = DB::getPDO()->fetchAll($sql, [ ':id_licence' => $licenceId ]);
  538. if (empty($all)) throw new Exception("Brak licencji o nr '{$licenceId}'");
  539. $licenceInfo = reset($all);
  540. if (!$licenceInfo['sshPort']) $licenceInfo['sshPort'] = 22;
  541. return $licenceInfo;
  542. }
  543. public function _endWithException($e) {
  544. echo UI::h('div', ['class'=>"container"], [
  545. UI::h('div', ['class' => "alert alert-danger"], "#" . $e->getLine() . ": " . $e->getMessage()),
  546. UI::h('p', [], [
  547. "Wróć do ",
  548. UI::h('a', ['href'=>"index.php?_route=Install"], "menu")
  549. ])
  550. ]);
  551. UI::dol();
  552. exit;
  553. }
  554. public function sendToRemoteTestDirAction() {
  555. session_write_close();
  556. $args = array();
  557. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  558. UI::gora();
  559. //UI::menu();
  560. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  561. try {
  562. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  563. $this->validateAppLicenceInfo($appLicenceInfo);
  564. // TODO: if (59 ) => baratosz.sledz - na lokalnym kompie
  565. // bn:~/$ scp -r SE server@192.168.61.153:~/se.encrypted.upgrade
  566. // remote SE.git = '/Users/bartoszsledz/Desktop/production-se'
  567. // remote:~/$ mv SE ~/SE.bup.2017-07-03
  568. // remote:~/$ mv ~/se.encrypted.upgrade/SE SE
  569. // remote:~/$ cp -r ~/SE.bup.2017-07-03/config SE/
  570. // remote:~/$ sudo chown -R bartoszsledz:staff SE/
  571. $this->_sendToRemoteTestDir($appLicenceInfo);
  572. echo "Test online: ";
  573. echo UI::h('a', ['target'=>"_blank", 'href'=>"https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/"], "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/");
  574. } catch (Exception $e) {
  575. $this->_endWithException($e);
  576. }
  577. UI::dol();
  578. }
  579. public function _fetchRemoteHomeDir($appLicenceInfo) {
  580. $this->_assertRsaKeyExists($appLicenceInfo);
  581. $sshHostUsr = "{$appLicenceInfo->rootLogin}@{$appLicenceInfo->mainServer}";
  582. $sshArgs = (22 != $appLicenceInfo->sshPort)? "-p {$appLicenceInfo->sshPort}" : '';
  583. $rsyncSshPort = (22 != $appLicenceInfo->sshPort)? "-e 'ssh -p {$appLicenceInfo->sshPort}'" : '';
  584. if (V::get('DBG_REMOTE', '', $_GET)) {// DBG
  585. $cmd = "echo ~";
  586. V::exec("ssh {$sshArgs} {$sshHostUsr} '{$cmd}'", $out, $ret);
  587. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  588. V::execRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  589. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  590. V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  591. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  592. }
  593. $cmd = "echo ~";
  594. V::exec("ssh {$sshArgs} {$sshHostUsr} '{$cmd}'", $out, $ret);
  595. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  596. if (empty($out) || empty($out[0])) throw new Exception("Cannot fetch remote home dir");
  597. return $out[0];
  598. }
  599. public function _sendToRemoteTestDir($appLicenceInfo) {
  600. $cmd = ''; $out = ''; $ret = '';
  601. $dryRunOnly = (V::get('dry-run', '', $_REQUEST)) ? "--dry-run" : "";
  602. $this->_assertRsaKeyExists($appLicenceInfo);
  603. $sshHostUsr = "{$appLicenceInfo->rootLogin}@{$appLicenceInfo->mainServer}";
  604. $sshArgs = (22 != $appLicenceInfo->sshPort)? "-p {$appLicenceInfo->sshPort}" : '';
  605. $rsyncSshPort = (22 != $appLicenceInfo->sshPort)? "-e 'ssh -p {$appLicenceInfo->sshPort}'" : '';
  606. // $appLicenceInfo->sshPort
  607. /* rsync options:
  608. -a, --archive archive mode; same as -rlptgoD (no -H)
  609. -u, --update skip files that are newer on the receiver
  610. -t, --times preserve times
  611. --delete delete extraneous files from dest dirs
  612. */
  613. $remoteDir = $this->_fetchRemoteHomeDir($appLicenceInfo);
  614. DBG::log($remoteDir, 'array', "remote home dir:");
  615. $cmd = "
  616. ssh {$sshArgs} {$sshHostUsr} '[ ! -d ~/se.encrypted.upgrade ] && mkdir ~/se.encrypted.upgrade || echo 1';
  617. ssh {$sshArgs} {$sshHostUsr} 'rm -rf ~/se.encrypted.upgrade/SE';
  618. ssh {$sshArgs} {$sshHostUsr} 'cp -r /Library/Server/Web/Data/Sites/Default/SE ~/se.encrypted.upgrade/SE';
  619. ssh {$sshArgs} {$sshHostUsr} 'rm -rf ~/se.encrypted.upgrade/SE/config';
  620. rsync --archive --times --delete --compress --one-file-system --omit-dir-times --no-g --no-perms {$dryRunOnly} \
  621. --verbose {$rsyncSshPort} \
  622. --exclude='stuff' \
  623. --exclude='stuff/**' \
  624. --exclude='schema/default_db.instance.xml' \
  625. --exclude='schema/default_db_xml_cache.public' \
  626. --exclude='schema/default_db.instance.xml/**' \
  627. --exclude='schema/default_db_xml_cache.public/**' \
  628. '{$appLicenceInfo->installPath}/SE/' {$sshHostUsr}:~/se.encrypted.upgrade/SE/;
  629. ssh {$sshArgs} {$sshHostUsr} 'cp -r /Library/Server/Web/Data/Sites/Default/SE/config ~/se.encrypted.upgrade/SE/';
  630. ssh {$sshArgs} {$sshHostUsr} 'rm /Library/Server/Web/Data/Sites/Default/se.encrypted.upgrade'
  631. ssh {$sshArgs} {$sshHostUsr} 'ln -s ~/se.encrypted.upgrade/SE /Library/Server/Web/Data/Sites/Default/se.encrypted.upgrade'
  632. ";
  633. V::exec($cmd, $out, $ret);
  634. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  635. if (0 !== $ret) throw new Exception("Cannot run remote command using rsa key! #{$ret}");
  636. }
  637. public function upgradeRemoteFromTestDirAction() {
  638. session_write_close();
  639. $args = array();
  640. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  641. UI::gora();
  642. //UI::menu();
  643. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  644. try {
  645. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  646. $this->validateAppLicenceInfo($appLicenceInfo);
  647. $this->_upgradeRemoteFromTestDir($appLicenceInfo);
  648. echo "Test online: ";
  649. echo UI::h('a', ['target'=>"_blank", 'href'=>"https://{$appLicenceInfo->mainServer}/SE/"], "https://{$appLicenceInfo->mainServer}/SE/");
  650. } catch (Exception $e) {
  651. $this->_endWithException($e);
  652. }
  653. UI::dol();
  654. }
  655. public function _upgradeRemoteFromTestDir($appLicenceInfo) {
  656. $cmd = ''; $out = ''; $ret = '';
  657. $this->_assertRsaKeyExists($appLicenceInfo);
  658. $dateStr = date("Y-m-d_H-i-s");
  659. // $remoteHomeDir = "/Users/{$appLicenceInfo->rootLogin}";// BUG: alias like in ams - login = prezes is alias for arkadiuszbinder
  660. $remoteHomeDir = $this->_fetchRemoteHomeDir($appLicenceInfo);
  661. $cmd = "
  662. rm -rf /Library/Server/Web/Data/Sites/Default/SE.test 2>&1
  663. cp -r {$remoteHomeDir}/se.encrypted.upgrade/SE /Library/Server/Web/Data/Sites/Default/SE.test 2>&1
  664. [ ! -d {$remoteHomeDir}/bup.se.upgrade ] && mkdir {$remoteHomeDir}/bup.se.upgrade || echo 1
  665. [ ! -d {$remoteHomeDir}/bup.se.upgrade ] && exit 1
  666. [ ! -d {$remoteHomeDir}/bup.se.upgrade-testttttt ] && exit 1
  667. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/VERSION ] && echo \"Error: plik VERSION nie istnieje\" || echo \"check VERSION OK\"
  668. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/VERSION ] && exit 1
  669. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/index.php ] && echo \"Error: plik index.php nie istnieje\" || echo \"check index.php OK\"
  670. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/index.php ] && exit 1
  671. [ ! -d /Library/Server/Web/Data/Sites/Default/SE.test/se-lib ] && echo \"Error: plik se-lib nie istnieje\" || echo \"check se-lib OK\"
  672. [ ! -d /Library/Server/Web/Data/Sites/Default/SE.test/se-lib ] && exit 1
  673. exit 0
  674. ";
  675. V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  676. $cmd = "
  677. mv /Library/Server/Web/Data/Sites/Default/SE {$remoteHomeDir}/bup.se.upgrade/bup.{$dateStr} 2>&1
  678. mv /Library/Server/Web/Data/Sites/Default/SE.test /Library/Server/Web/Data/Sites/Default/SE 2>&1
  679. exit 0
  680. ";
  681. V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  682. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  683. if (0 !== $ret) throw new Exception("Cannot run remote command as root! #{$ret}");
  684. // TODO: SE/bash_install_check.php requires $domain!
  685. // $cmd = "/usr/bin/php /Library/Server/Web/Data/Sites/Default/SE/bash_install_check.php {$domain}";
  686. // V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  687. // DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  688. // if (0 !== $ret) throw new Exception("Cannot run remote command as root! #{$ret}");
  689. }
  690. public function _assertRsaKeyExists($appLicenceInfo) {
  691. $cmd = ''; $out = ''; $ret = '';
  692. $cmd = "echo ~ && pwd";// /Library/WebServer
  693. $cmd = "ls -1 ~/.ssh/";
  694. //$cmd = "rm /tmp/id_rsa";
  695. //$cmd = "rm /tmp/id_rsa.pub";
  696. //$cmd = "ssh-keygen -t rsa -N '' -C '_www@biuro.biall-net.pl' -f /tmp/id_rsa";
  697. //$cmd = "ssh-keygen -t rsa -N '' -C '_www@biuro.biall-net.pl' -f /tmp/id_rsa";
  698. V::exec($cmd, $out, $ret);
  699. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  700. if (0 !== $ret) {// no ~/.ssh directory
  701. $rsaKeyPath = "~/.ssh";
  702. $cmds = array();
  703. $cmds[] = "mkdir {$rsaKeyPath}";
  704. $cmds[] = "ssh-keygen -t rsa -N '' -C '_www@biuro.biall-net.pl' -f {$rsaKeyPath}/id_rsa 2>&1";
  705. $cmds[] = "ls -1 $rsaKeyPath";
  706. foreach ($cmds as $cmd) {
  707. V::exec($cmd, $out, $ret);
  708. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  709. if (0 !== $ret) throw new Exception("Error '{$ret}' cmd({$cmd}): " . implode("\n", $out));
  710. }
  711. }
  712. $cmd = "cat ~/.ssh/id_rsa.pub";
  713. V::exec($cmd, $out, $ret);
  714. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  715. if (0 !== $ret || empty($out) || empty($out[0])) throw new Exception("Cannot read rsa public key");
  716. $rsaPubKey = $out[0];
  717. $cmd = 'ls -1a';
  718. $cmd = "
  719. [ ! -d ~/.ssh ] && mkdir ~/.ssh;
  720. [ ! -d ~/.ssh ] && echo 'ERROR ~/.ssh not exists and cannot be created';
  721. [ ! -f ~/.ssh/authorized_keys ] && echo '{$rsaPubKey}' > ~/.ssh/authorized_keys;
  722. [ ! -f ~/.ssh/authorized_keys ] && echo 'ERROR ~/.ssh/authorized_keys not exists and cannot be created';
  723. cat ~/.ssh/authorized_keys| grep '{$rsaPubKey}' && echo 'OK' || echo '{$rsaPubKey}' >> ~/.ssh/authorized_keys;
  724. chmod 600 ~/.ssh/authorized_keys;
  725. ";
  726. V::execRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  727. DBG::_(true, true, "remote cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  728. //$cmd = "ssh server@{$appLicenceInfo->mainServer} 'ls -1 .ssh/'";
  729. //$cmd = "ssh -i ~/.ssh/id_rsa server@{$appLicenceInfo->mainServer} 'ls -1'";
  730. $sshPort = (22 != $appLicenceInfo->sshPort)? "-p {$appLicenceInfo->sshPort}" : '';
  731. $cmd = "ssh {$sshPort} {$appLicenceInfo->rootLogin}@{$appLicenceInfo->mainServer} 'ls -1'";
  732. V::exec($cmd, $out, $ret);
  733. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  734. if (0 !== $ret) throw new Exception("Cannot run remote command using rsa key! #{$ret}");
  735. }
  736. public function newGenerateApp($appLicenceInfo) {
  737. if (empty($appLicenceInfo->ID)) throw new Exception("Nie wybrano serwera/licencji.");
  738. if (empty($appLicenceInfo->domains)) throw new Exception("Domains not found");
  739. $installPath = $appLicenceInfo->installPath;
  740. if (empty($installPath)) throw new Exception("Install path not found");
  741. $installPath .= '-p5';
  742. $cmds = array();
  743. $cmds[] = "if [ -d {$installPath} ] ; then rm -rf '{$installPath}'; fi";
  744. $cmds[] = "mkdir {$installPath}";
  745. $cmds[] = "cd {$installPath} && git clone --depth 1 ssh://git@biuro.biall-net.pl:2222/p5/p5.git .";
  746. $cmds[] = "cd {$installPath} && echo `git show-ref --head|head -1|head -c 8` > SE/VERSION ";
  747. // TODO: fetch from DB
  748. {
  749. foreach ($appLicenceInfo->projects as $projectName) {
  750. $cmds[] = "cd {$installPath} && git submodule update --init SE/projects/{$projectName}";
  751. }
  752. }
  753. foreach ($cmds as $cmd) {
  754. $out = ''; $ret = '';
  755. exec($cmd, $out, $ret);
  756. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  757. }
  758. // $this->_encodeSource($appLicenceInfo->installPath, $appLicenceInfo->domains);
  759. }
  760. }