api.updatemanager.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. <?php
  2. /**
  3. * Performs deploy of database and config files updates
  4. */
  5. class UpdateManager {
  6. /**
  7. * System alter.ini config as key=>value
  8. *
  9. * @var array
  10. */
  11. protected $altCfg = array();
  12. /**
  13. * System binpaths.ini config as key=>value
  14. *
  15. * @var array
  16. */
  17. protected $binPathsCfg = array();
  18. /**
  19. * System mysql.ini config as key=>value
  20. *
  21. * @var array
  22. */
  23. protected $mySqlCfg = array();
  24. /**
  25. * System message helper object placeholder
  26. *
  27. * @var object
  28. */
  29. protected $messages = '';
  30. /**
  31. * Available mysql dumps for apply as release=>filename
  32. *
  33. * @var array
  34. */
  35. protected $allDumps = array();
  36. /**
  37. * Contains available configs updates as release=>configdata
  38. *
  39. * @var array
  40. */
  41. protected $allConfigs = array();
  42. /**
  43. * Contais configs filenames as shortid=>filename
  44. *
  45. * @var array
  46. */
  47. protected $configFileNames = array();
  48. /**
  49. * system sudo path
  50. *
  51. * @var string
  52. */
  53. protected $sudoPath = '/usr/local/bin/sudo';
  54. /**
  55. * Automatic updater full path
  56. *
  57. * @var string
  58. */
  59. protected $atoupdaterPath = '/bin/autowrupdate.sh';
  60. /**
  61. * predefined stuff here
  62. */
  63. const URL_RELEASE_STABLE = 'http://wolfrecorder.com/RELEASE';
  64. const URL_RELEASE_CURRENT = 'http://snaps.wolfrecorder.com/RELEASE';
  65. const DUMPS_PATH = 'content/updates/sql/';
  66. const CONFIGS_PATH = 'content/updates/configs/';
  67. const URL_ME = '?module=update';
  68. const URL_RELNOTES = 'wolfrecorder.com/wiki/doku.php?id=relnotes#section';
  69. const ROUTE_AUTOSYSUPGRADE = 'autosystemupgrade';
  70. const PROUTE_UPGRADEAGREE = 'runsystemupgrade';
  71. const PID_AUTOSYSUPGRADE = 'UPDMGRAUTOUPGRADE';
  72. /**
  73. * Creates new update manager instance
  74. *
  75. * @return void
  76. */
  77. public function __construct() {
  78. $this->loadSystemConfigs();
  79. $this->setOptions();
  80. $this->initMessages();
  81. $this->setConfigFilenames();
  82. $this->loadDumps();
  83. $this->loadConfigs();
  84. $this->ConnectDB();
  85. }
  86. /**
  87. * Loads all required system config files into protected props for further usage
  88. *
  89. * @global object $ubillingConfig
  90. *
  91. * @return void
  92. */
  93. protected function loadSystemConfigs() {
  94. global $ubillingConfig;
  95. $this->altCfg = $ubillingConfig->getAlter();
  96. $this->binPathsCfg = $ubillingConfig->getBinPaths();
  97. $this->mySqlCfg = rcms_parse_ini_file(CONFIG_PATH . 'mysql.ini');
  98. }
  99. /**
  100. * Sets all required options
  101. *
  102. * @return void
  103. */
  104. protected function setOptions() {
  105. if (!empty($this->binPathsCfg['SUDO'])) {
  106. $this->sudoPath = $this->binPathsCfg['SUDO'];
  107. }
  108. if (!empty($this->binPathsCfg['AUTO_UPDATE'])) {
  109. $this->atoupdaterPath = $this->binPathsCfg['AUTO_UPDATE'];
  110. }
  111. }
  112. /**
  113. * Inits system messages helper object instance
  114. *
  115. * @return void
  116. */
  117. protected function initMessages() {
  118. $this->messages = new UbillingMessageHelper();
  119. }
  120. /**
  121. * Loads available mysql dumps filenames into protected prop
  122. *
  123. * @return void
  124. */
  125. protected function loadDumps() {
  126. $dumpsTmp = rcms_scandir(self::DUMPS_PATH, '*.sql');
  127. if (!empty($dumpsTmp)) {
  128. rsort($dumpsTmp);
  129. foreach ($dumpsTmp as $io => $each) {
  130. $release = str_replace('.sql', '', $each);
  131. $this->allDumps[$release] = $each;
  132. }
  133. }
  134. }
  135. /**
  136. * Loads available configs update into protected prop
  137. *
  138. * @return void
  139. */
  140. protected function loadConfigs() {
  141. $configsTmp = rcms_scandir(self::CONFIGS_PATH, '*.ini');
  142. if (!empty($configsTmp)) {
  143. rsort($configsTmp);
  144. foreach ($configsTmp as $io => $each) {
  145. $release = str_replace('.ini', '', $each);
  146. $fileContent = rcms_parse_ini_file(self::CONFIGS_PATH . $each, true);
  147. $this->allConfigs[$release] = $fileContent;
  148. }
  149. }
  150. }
  151. /**
  152. * Sets shortid=>filename with path configs associations array
  153. *
  154. * @return void
  155. */
  156. protected function setConfigFilenames() {
  157. $this->configFileNames = array(
  158. 'yalf' => 'config/yalf.ini',
  159. 'alter' => 'config/alter.ini',
  160. 'binpaths' => 'config/binpaths.ini',
  161. 'ymaps' => 'config/ymaps.ini',
  162. 'mysql' => 'config/mysql.ini',
  163. );
  164. }
  165. /**
  166. * Initialises connection with database server and selects needed db
  167. *
  168. * @param MySQL Connection Id $connection
  169. *
  170. * @return MySQLDB
  171. */
  172. protected function ConnectDB() {
  173. $dbport = (empty($this->mySqlCfg['port']) ? '' : $this->mySqlCfg['port']);
  174. $this->DBConnection = new DbConnect($this->mySqlCfg['server'], $this->mySqlCfg['username'], $this->mySqlCfg['password'], $this->mySqlCfg['db'], true, false, $dbport);
  175. }
  176. /**
  177. * Returns list of files which was updated in some release
  178. *
  179. * @param string $release
  180. *
  181. * @return string
  182. */
  183. protected function getReleaseConfigFiles($release) {
  184. $result = '';
  185. if (isset($this->allConfigs[$release])) {
  186. if (!empty($this->allConfigs[$release])) {
  187. foreach ($this->allConfigs[$release] as $shortid => $data) {
  188. $filename = (isset($this->configFileNames[$shortid])) ? $this->configFileNames[$shortid] : $shortid;
  189. $result .= $filename . ' ';
  190. }
  191. }
  192. }
  193. return($result);
  194. }
  195. /**
  196. * Apply Mysql Dump and returns results
  197. *
  198. * @param string $release
  199. *
  200. * @return string
  201. */
  202. protected function DoSqlDump($release) {
  203. $result = '';
  204. if (!empty($release)) {
  205. $fileName = self::DUMPS_PATH . $this->allDumps[$release];
  206. $file = explode(';', file_get_contents($fileName));
  207. $sql_dumps = array_diff($file, array('')); // Delete empty data Array
  208. $sql_array = array_map('trim', $sql_dumps);
  209. // Open DB connection and set character
  210. $this->DBConnection->open();
  211. $this->DBConnection->query("set character_set_client='" . $this->mySqlCfg['character'] . "'");
  212. $this->DBConnection->query("set character_set_results='" . $this->mySqlCfg['character'] . "'");
  213. $this->DBConnection->query("set collation_connection='" . $this->mySqlCfg['character'] . "_general_ci'");
  214. foreach ($sql_array as $query) {
  215. if (!empty($query)) {
  216. $this->DBConnection->query($query);
  217. if (!$this->DBConnection->error()) {
  218. $result .= $this->messages->getStyledMessage(wf_tag('b', false) . __('Done') . ': ' . wf_tag('b', true) . wf_tag('pre', false) . $query . wf_tag('pre', true), 'success') . wf_tag('br');
  219. } else {
  220. $result .= $this->messages->getStyledMessage(wf_tag('b', false) . __('Error') . ': ' . wf_tag('b', true) . $this->DBConnection->error() . wf_tag('pre', false) . $query . wf_tag('pre', true), 'error') . wf_tag('br');
  221. }
  222. }
  223. }
  224. $this->DBConnection->close();
  225. }
  226. return($result);
  227. }
  228. /**
  229. * Renders list of sql dumps available for applying
  230. *
  231. * @return string
  232. */
  233. public function renderSqlDumpsList() {
  234. $result = '';
  235. if (!empty($this->allDumps)) {
  236. $cells = wf_TableCell(__('WolfRecorder release'));
  237. $cells .= wf_TableCell(__('Details'));
  238. $cells .= wf_TableCell(__('Actions'));
  239. $rows = wf_TableRow($cells, 'row1');
  240. foreach ($this->allDumps as $release => $filename) {
  241. $relnotesUrl = self::URL_RELNOTES . str_replace('.', '', $release);
  242. $relnotesLink = wf_Link('http://' . $relnotesUrl, __('Release notes') . ' ' . $release, false, '', 'target="_BLANK"');
  243. $alertText = __('Are you serious') . ' ' . __('Apply') . ' WolfRecorder ' . $release . '?';
  244. $actLink = wf_JSAlert(self::URL_ME . '&applysql=' . $release, wf_img('skins/icon_restoredb.png', __('Apply')), $alertText);
  245. $cells = wf_TableCell($release);
  246. $cells .= wf_TableCell($relnotesLink);
  247. $cells .= wf_TableCell($actLink);
  248. $rows .= wf_TableRow($cells, 'row5');
  249. }
  250. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  251. } else {
  252. $result = $this->messages->getStyledMessage(__('Nothing found'), 'info');
  253. }
  254. return ($result);
  255. }
  256. /**
  257. * Renders list of available config files updates
  258. *
  259. * @return string
  260. */
  261. public function renderConfigsList() {
  262. $result = '';
  263. if (!empty($this->allConfigs)) {
  264. $cells = wf_TableCell(__('WolfRecorder release'));
  265. $cells .= wf_TableCell(__('Details'));
  266. $cells .= wf_TableCell(__('Files'));
  267. $cells .= wf_TableCell(__('Actions'));
  268. $rows = wf_TableRow($cells, 'row1');
  269. foreach ($this->allConfigs as $release => $filename) {
  270. $relnotesUrl = self::URL_RELNOTES . str_replace('.', '', $release);
  271. $relnotesLink = wf_Link('http://' . $relnotesUrl, __('Release notes') . ' ' . $release, false, '', 'target="_BLANK"');
  272. $alertText = __('Are you serious') . ' ' . __('Apply') . ' WolfRecorder ' . $release . '?';
  273. $actLink = wf_JSAlert(self::URL_ME . '&showconfigs=' . $release, wf_img('skins/icon_addrow.png', __('Apply')), $alertText);
  274. $cells = wf_TableCell($release);
  275. $cells .= wf_TableCell($relnotesLink);
  276. $cells .= wf_TableCell($this->getReleaseConfigFiles($release));
  277. $cells .= wf_TableCell($actLink);
  278. $rows .= wf_TableRow($cells, 'row5');
  279. }
  280. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  281. } else {
  282. $result = $this->messages->getStyledMessage(__('Nothing found'), 'info');
  283. }
  284. return ($result);
  285. }
  286. /**
  287. * Applies mysql dump to current database
  288. *
  289. * @param string $release
  290. *
  291. * @return string
  292. */
  293. public function applyMysqlDump($release) {
  294. $result = '';
  295. $release = trim($release);
  296. $release = vf($release);
  297. if (isset($this->allDumps[$release])) {
  298. if (wf_CheckPost(array('applyconfirm', 'applysqldump'))) {
  299. $result .= $this->messages->getStyledMessage(__('MySQL dump applying result below'), 'info');
  300. $result .= wf_CleanDiv();
  301. log_register('UPDMGR APPLY SQL RELEASE `' . $release . '`');
  302. $result .= $this->DoSqlDump($release);
  303. $result .= wf_BackLink(self::URL_ME);
  304. } else {
  305. if ((!wf_CheckPost(array('applyconfirm'))) AND ( wf_CheckPost(array('applysqldump')))) {
  306. $result .= $this->messages->getStyledMessage(__('You are not mentally prepared for this'), 'error');
  307. $result .= wf_delimiter();
  308. $result .= wf_BackLink(self::URL_ME . '&applysql=' . $release);
  309. } else {
  310. $result .= $this->messages->getStyledMessage(__('Caution: these changes can not be undone.'), 'warning');
  311. $result .= wf_tag('br');
  312. $inputs = __('Apply changes for WolfRecorder release') . ' ' . $release . '?';
  313. $inputs .= wf_tag('br');
  314. $inputs .= wf_tag('br');
  315. $inputs .= wf_HiddenInput('applysqldump', 'true');
  316. $inputs .= wf_CheckInput('applyconfirm', __('I`m ready'), true, false);
  317. $inputs .= wf_tag('br');
  318. $inputs .= wf_Submit(__('Apply'));
  319. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  320. $result .= wf_CleanDiv();
  321. $result .= wf_delimiter();
  322. $result .= wf_BackLink(self::URL_ME);
  323. }
  324. }
  325. } else {
  326. $result = $this->messages->getStyledMessage(__('Wrong release'), 'error');
  327. log_register('UPDMGR FAIL SQL RELEASE `' . $release . '`');
  328. }
  329. return ($result);
  330. }
  331. /**
  332. * Changes access rights for some path to be writable
  333. *
  334. * @param string $path
  335. *
  336. * @return void
  337. */
  338. protected function fixAccessRights($path) {
  339. $command = $this->sudoPath . ' chmod -R 777 ' . $path;
  340. shell_exec($command);
  341. }
  342. /**
  343. * Renders interface and applies new options to some config files
  344. *
  345. * @param string $release
  346. *
  347. * @return string
  348. */
  349. public function applyConfigOptions($release) {
  350. $result = '';
  351. $release = trim($release);
  352. $release = vf($release);
  353. $newOptsCount = 0;
  354. if (isset($this->allConfigs[$release])) {
  355. $releaseData = $this->allConfigs[$release];
  356. if (!empty($releaseData)) {
  357. foreach ($releaseData as $configId => $configOptions) {
  358. @$configName = $this->configFileNames[$configId];
  359. $canUpdate = false;
  360. if (!empty($configName)) {
  361. if (file_exists($configName)) {
  362. $currentConfigOptions = rcms_parse_ini_file($configName);
  363. $result .= $this->messages->getStyledMessage(__('Existing config file') . ': ' . $configName, 'success');
  364. //some logging
  365. if (wf_CheckPost(array('applyconfigoptions', 'applyconfirm'))) {
  366. //Initial line break and update header
  367. $configUpdateHeader = "\n";
  368. $configUpdateHeader .= ';release ' . $release . ' update' . "\n";
  369. if (is_writable($configName)) {
  370. $canUpdate = true;
  371. } else {
  372. $canUpdate = false;
  373. $result .= $this->messages->getStyledMessage(__('Permission denied') . ': ' . $configName . '.', 'error');
  374. $result .= $this->messages->getStyledMessage(__('Trying to set write permissions for') . ' ' . $configName . ' ' . __('to fix this issue') . '.', 'warning');
  375. $this->fixAccessRights($configName);
  376. if (is_writable($configName)) {
  377. $canUpdate = true;
  378. $result .= $this->messages->getStyledMessage(__('Success! Config file') . ' ' . $configName . ' ' . __('now is writable') . '.', 'success');
  379. } else {
  380. $canUpdate = false;
  381. $result .= $this->messages->getStyledMessage(__('Seems like we failed with making this file writable') . '.', 'error');
  382. }
  383. }
  384. //now real put update header
  385. if ($canUpdate) {
  386. file_put_contents($configName, $configUpdateHeader, FILE_APPEND);
  387. log_register('UPDMGR APPLY CONFIG `' . $configId . '` RELEASE `' . $release . '`');
  388. }
  389. }
  390. if (!empty($configOptions)) {
  391. foreach ($configOptions as $optionName => $optionContent) {
  392. if (!isset($currentConfigOptions[$optionName])) {
  393. $newOptsCount++;
  394. $result .= $this->messages->getStyledMessage(__('New option') . ': ' . $optionName . ' ' . __('will be added with value') . ' ' . $optionContent, 'info');
  395. if (wf_CheckPost(array('applyconfigoptions', 'applyconfirm'))) {
  396. $saveOptions = $optionName . '=' . $optionContent . "\n";
  397. if (is_writable($configName)) {
  398. file_put_contents($configName, $saveOptions, FILE_APPEND);
  399. $result .= $this->messages->getStyledMessage(__('Option added') . ': ' . $optionName . '= ' . $optionContent, 'success');
  400. $newOptsCount--;
  401. } else {
  402. $result .= $this->messages->getStyledMessage(__('New option') . ' ' . $optionName . ' ' . __('not created') . '. ' . __('Permission denied') . '.', 'error');
  403. }
  404. }
  405. } else {
  406. $result .= $this->messages->getStyledMessage(__('Option already exists, will be ignored') . ': ' . $optionName, 'warning');
  407. }
  408. }
  409. }
  410. } else {
  411. $result .= $this->messages->getStyledMessage(__('Wrong config path') . ': ' . $configName, 'error');
  412. }
  413. } else {
  414. $result .= $this->messages->getStyledMessage(__('Unknown config') . ': ' . $configId, 'error');
  415. }
  416. }
  417. //confirmation checkbox notice
  418. if ((wf_CheckPost(array('applyconfigoptions'))) AND ( !wf_CheckPost(array('applyconfirm')))) {
  419. $result .= $this->messages->getStyledMessage(__('You are not mentally prepared for this'), 'error');
  420. }
  421. //apply form assembly
  422. if ($newOptsCount > 0) {
  423. $result .= wf_tag('br');
  424. $inputs = __('Apply changes for WolfRecorder release') . ' ' . $release . '?';
  425. $inputs .= wf_tag('br');
  426. $inputs .= wf_tag('br');
  427. $inputs .= wf_HiddenInput('applyconfigoptions', 'true');
  428. $inputs .= wf_CheckInput('applyconfirm', __('I`m ready'), true, false);
  429. $inputs .= wf_tag('br');
  430. $inputs .= wf_Submit(__('Apply'));
  431. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  432. $result .= wf_CleanDiv();
  433. } else {
  434. $result .= $this->messages->getStyledMessage(__('Everything is fine. All required options for release') . ' ' . $release . ' ' . __('is on their places.'), 'success');
  435. }
  436. }
  437. $result .= wf_CleanDiv();
  438. $result .= wf_delimiter();
  439. $result .= wf_BackLink(self::URL_ME);
  440. } else {
  441. $result .= $this->messages->getStyledMessage(__('Wrong release'), 'error');
  442. log_register('UPDMGR FAIL CONF RELEASE `' . $release . '`');
  443. }
  444. return ($result);
  445. }
  446. /**
  447. * Renders current release info data and update check controls
  448. *
  449. * @return string
  450. */
  451. public function renderVersionInfo() {
  452. $currentRelease = wr_getLocalSystemVersion();
  453. $updatechecker = wf_tag('br') . wf_tag('div', false, '', 'style="margin-left: 3%;"');
  454. $updatechecker .= wf_AjaxLink('?module=update&checkupdates=true', wf_img('skins/question.png') . ' ' . __('Check updates'), 'lastrelease', false, 'ubButton') . ' ';
  455. $updatechecker .= wf_tag('div', true);
  456. $updatechecker .= wf_CleanDiv();
  457. $releaseInfo = wf_tag('style') . '#ubajaxloaderanim { margin-left: 3%; margin-top: 10px; }' . wf_tag('style', true);
  458. $releaseInfo .= $updatechecker;
  459. $releaseInfo .= $this->messages->getStyledMessage(__('Current system version') . ': ' . $currentRelease, 'info');
  460. $releaseInfo .= wf_AjaxContainer('lastrelease', '', '');
  461. $releaseInfo .= wf_AjaxLoader();
  462. return ($releaseInfo);
  463. }
  464. /**
  465. * Performs automatic system upgrade
  466. *
  467. * @param string $branch
  468. *
  469. * @return void/string on error
  470. */
  471. public function performAutoUpgrade($branch) {
  472. $result = '';
  473. $updateProcess = new StarDust(self::PID_AUTOSYSUPGRADE);
  474. if ($updateProcess->notRunning()) {
  475. $updateProcess->start();
  476. log_register('UPDMGR AUTOUPGRADE `' . $branch . '` STARTED');
  477. if ($this->sudoPath AND $this->atoupdaterPath) {
  478. if (file_exists($this->atoupdaterPath)) {
  479. $command = $this->sudoPath . ' ' . $this->atoupdaterPath . ' ' . $branch;
  480. $autoUpdaterResult = shell_exec($command);
  481. if (!ispos($autoUpdaterResult, 'SUCCESS')) {
  482. $result .= __('Something went wrong') . ': ' . $autoUpdaterResult;
  483. log_register('UPDMGR AUTOUPGRADE `' . $branch . '` FAILED');
  484. }
  485. } else {
  486. $result .= $this->atoupdaterPath . ' ' . __('not exists');
  487. }
  488. }
  489. log_register('UPDMGR AUTOUPGRADE `' . $branch . '` FINISHED');
  490. $updateProcess->stop();
  491. } else {
  492. $result .= __('System update') . ' ' . __('already running');
  493. }
  494. return($result);
  495. }
  496. }
  497. /**
  498. * Updates deployment routines
  499. */
  500. class UpdateStuff {
  501. /**
  502. * Contains system billing.ini as key=>value
  503. *
  504. * @var array
  505. */
  506. protected $binPathsCfg = array();
  507. /**
  508. * Wget path
  509. *
  510. * @var string
  511. */
  512. protected $wgetPath = '/usr/local/bin/wget';
  513. /**
  514. * Tar archiver path
  515. *
  516. * @var string
  517. */
  518. protected $tarPath = '/usr/bin/tar';
  519. /**
  520. * system sudo path
  521. *
  522. * @var string
  523. */
  524. protected $sudoPath = '/usr/local/bin/sudo';
  525. /**
  526. * Gzip archiver path
  527. *
  528. * @var gzip
  529. */
  530. protected $gzipPath = '/usr/bin/gzip';
  531. public function __construct() {
  532. $this->loadConfig();
  533. $this->setOptions();
  534. }
  535. /**
  536. * Loads all required configs
  537. *
  538. * @global object $ubillingConfig
  539. *
  540. * @return void
  541. */
  542. protected function loadConfig() {
  543. global $ubillingConfig;
  544. $this->binPathsCfg = $ubillingConfig->getBinPaths();
  545. }
  546. /**
  547. * Sets custom paths to required software
  548. *
  549. * @return void
  550. */
  551. protected function setOptions() {
  552. if (isset($this->binPathsCfg['SUDO'])) {
  553. $this->sudoPath = $this->binPathsCfg['SUDO'];
  554. }
  555. if (isset($this->binPathsCfg['WGET_PATH'])) {
  556. $this->wgetPath = $this->binPathsCfg['WGET_PATH'];
  557. }
  558. if (isset($this->binPathsCfg['TAR_PATH'])) {
  559. $this->tarPath = $this->binPathsCfg['TAR_PATH'];
  560. }
  561. if (isset($this->binPathsCfg['GZIP_PATH'])) {
  562. $this->gzipPath = $this->binPathsCfg['GZIP_PATH'];
  563. }
  564. }
  565. /**
  566. * Changes access rights for some directory to be writable
  567. *
  568. * @param string $directory
  569. *
  570. * @return void
  571. */
  572. public function fixAccessRights($directory) {
  573. $command = $this->sudoPath . ' chmod -R 777 ' . $directory;
  574. shell_exec($command);
  575. }
  576. /**
  577. * Downloads file from remote host
  578. *
  579. * @param string $url
  580. * @param string $directory
  581. * @param string $filename
  582. *
  583. * @return void
  584. */
  585. public function downloadRemoteFile($url, $directory, $filename = '') {
  586. if ($filename) {
  587. $wgetOptions = '--output-document=' . $directory . $filename . ' ';
  588. } else {
  589. $wgetOptions = '--directory-prefix=' . $directory . basename($url) . ' ';
  590. }
  591. $wgetOptions .= '--no-check-certificate ';
  592. if (file_exists($directory)) {
  593. if (!is_writable($directory)) {
  594. throw new Exception('DOWNLOAD_DIRECTORY_NOT_WRITABLE');
  595. }
  596. $command = $this->wgetPath . ' ' . $wgetOptions . ' ' . $url;
  597. shell_exec($command);
  598. } else {
  599. throw new Exception('DOWNLOAD_DIRECTORY_NOT_EXISTS');
  600. }
  601. }
  602. /**
  603. * Extracts tar.gz archive to some path
  604. *
  605. * @param string $archivePath
  606. * @param string $extractPath
  607. *
  608. * @return void
  609. */
  610. public function extractTgz($archivePath, $extractPath) {
  611. if (file_exists($archivePath)) {
  612. if (is_readable($archivePath)) {
  613. if (file_exists($extractPath)) {
  614. if (!is_writable($extractPath)) {
  615. $this->fixAccessRights($extractPath);
  616. }
  617. //unpacking archive
  618. $command = $this->tarPath . ' zxvf ' . $archivePath . ' -C ' . $extractPath;
  619. shell_exec($command);
  620. } else {
  621. throw new Exception('EXTRACT_DIRECTORY_NOT_EXISTS');
  622. }
  623. }
  624. }
  625. }
  626. }