PageRenderTime 37ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/app/controllers/Utils.php

https://github.com/BabelZilla/WTS
PHP | 600 lines | 512 code | 57 blank | 31 comment | 148 complexity | 11e0856a6a2ec1e14983fdd0613ec02a MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, GPL-2.0
  1. <?php
  2. class Utils
  3. {
  4. public static function RecursiveDelete($strFilePath)
  5. {
  6. if (strstr($strFilePath, '/*')) {
  7. $strFilePath = str_replace('/*', '', $strFilePath);
  8. if ($hndDir = opendir($strFilePath)) {
  9. while (($strFileName = readdir($hndDir)) !== false) {
  10. if ($strFileName == '.' || $strFileName == '..') {
  11. continue;
  12. }
  13. self::RecursiveDelete($strFilePath . '/' . $strFileName);
  14. }
  15. closedir($hndDir);
  16. } else {
  17. throw new Exception(sprintf(
  18. 'Can\'t open directory %s for reading, maybe %s doesn\'t have execute permissions on it.',
  19. $strFilePath,
  20. get_current_user()
  21. ));
  22. }
  23. } else {
  24. if (is_dir($strFilePath) && !is_link($strFilePath)) {
  25. if ($hndDir = opendir($strFilePath)) {
  26. while (($strFileName = readdir($hndDir)) !== false) {
  27. if ($strFileName == '.' || $strFileName == '..') {
  28. continue;
  29. }
  30. self::RecursiveDelete($strFilePath . '/' . $strFileName);
  31. }
  32. closedir($hndDir);
  33. } else {
  34. throw new Exception(sprintf(
  35. 'Can\'t open directory %s for reading, maybe %s doesn\'t have execute permissions on it.',
  36. $strFilePath,
  37. get_current_user()
  38. ));
  39. }
  40. if (!@rmdir($strFilePath)) {
  41. if (file_exists($strFilePath . '/..') && is_writable($strFilePath . '/..')) {
  42. $strError = sprintf('Maybe "%s" is not empty.', realpath($strFilePath . '/..'));
  43. } elseif (file_exists($strFilePath . '/..') && !is_writable($strFilePath . '/..')) {
  44. $strError = sprintf('Parent directory, "%s", is not writable.', realpath($strFilePath . '/..'));
  45. } else {
  46. $strError = 'Unknown error.';
  47. }
  48. throw new Exception(sprintf('Could not delete directory %s: %s', $strFilePath, $strError));
  49. return false;
  50. } else {
  51. return true;
  52. }
  53. }
  54. if ((file_exists($strFilePath) || is_link($strFilePath)) && !@unlink($strFilePath)) {
  55. if (!is_writable($strFilePath)) {
  56. $strError = sprintf(
  57. '"%s" is only writable by "%s".',
  58. realpath($strFilePath . '/..'),
  59. fileowner(realpath($strFilePath . '/..'))
  60. );
  61. } else {
  62. $strError = 'Unknown error.';
  63. }
  64. throw new Exception(sprintf('Could not delete file %s: %s', $strFilePath, $strError));
  65. return false;
  66. } else {
  67. return true;
  68. }
  69. }
  70. }
  71. public static function Chmod($strFilePath, $intFileMode = 0666)
  72. {
  73. if (!@chmod($strFilePath, $intFileMode)) {
  74. /**
  75. * If it's writable, we don't care if chmod failed, it's probably due to selinux
  76. */
  77. if (!is_writable($strFilePath)) {
  78. $strError = sprintf('"%s" is not writable by "%s".', $strFilePath, fileowner($strFilePath));
  79. throw new Exception(sprintf('Could not chmod file %s: %s', $strFilePath, $strError));
  80. }
  81. return false;
  82. } else {
  83. return true;
  84. }
  85. }
  86. public static function RecursiveChmod(
  87. $strFilePath,
  88. $intFileMode = 0666,
  89. $intDirMode = 0777,
  90. $blnKeepExecutableFiles = true
  91. )
  92. {
  93. if (is_dir($strFilePath) && !is_link($strFilePath)) {
  94. if ($hndDir = opendir($strFilePath)) {
  95. while (($strFileName = readdir($hndDir)) !== false) {
  96. if ($strFileName == '.' || $strFileName == '..') {
  97. continue;
  98. }
  99. self::RecursiveChmod($strFilePath . '/' . $strFileName, $intFileMode, $intDirMode);
  100. }
  101. closedir($hndDir);
  102. } else {
  103. throw new Exception(sprintf(
  104. 'Can\'t open directory %s for reading, maybe %s doesn\'t have execute permissions on it.',
  105. $strFilePath,
  106. fileowner($strFilePath)
  107. ));
  108. }
  109. if (!@chmod($strFilePath, $intDirMode)) {
  110. /**
  111. * If it's writable, we don't care if chmod failed, it's probably due to selinux
  112. */
  113. if (!is_writable($strFilePath)) {
  114. $strError = sprintf('"%s" is only writable by "%s".', $strFilePath, fileowner($strFilePath));
  115. throw new Exception(sprintf('Could not chmod file %s: %s', $strFilePath, $strError));
  116. }
  117. return false;
  118. } else {
  119. return true;
  120. }
  121. }
  122. if (is_file($strFilePath) && !is_link($strFilePath)) {
  123. if ($blnKeepExecutableFiles && is_executable($strFilePath)) {
  124. $intFileMode = 0777;
  125. }
  126. if (!@chmod($strFilePath, $intFileMode)) {
  127. /**
  128. * If it's writable, we don't care if chmod failed, it's probably due to selinux
  129. */
  130. if (!is_writable($strFilePath)) {
  131. $strError = sprintf('"%s" is only writable by "%s".', $strFilePath, fileowner($strFilePath));
  132. throw new Exception(sprintf('Could not chmod file %s: %s', $strFilePath, $strError));
  133. }
  134. return false;
  135. } else {
  136. return true;
  137. }
  138. } else /**
  139. * ignore symlinks and other non-regular files
  140. */ {
  141. return true;
  142. }
  143. }
  144. public static function RecursiveCopy($source, $target)
  145. {
  146. if (is_dir($source)) {
  147. if (!file_exists($target) && !@mkdir($target, 0777, true)) {
  148. if (is_writable($target)) {
  149. throw new Exception(
  150. sprintf(
  151. 'Could not create directory %s. The parent directory has owner %s and permissions %s',
  152. $target,
  153. fileowner('.'),
  154. fileperms('.')
  155. )
  156. );
  157. } else {
  158. throw new Exception(
  159. sprintf(
  160. 'Could not create directory %s. The parent directory is only writable by %s',
  161. $target,
  162. fileowner($target)
  163. )
  164. );
  165. }
  166. }
  167. $d = dir($source);
  168. while (false !== ($entry = $d->read())) {
  169. if ($entry == '.' || $entry == '..') {
  170. continue;
  171. }
  172. $Entry = $source . '/' . $entry;
  173. if (is_dir($Entry)) {
  174. self::RecursiveCopy($Entry, $target . '/' . $entry);
  175. continue;
  176. }
  177. if (!@copy($Entry, $target . '/' . $entry)) {
  178. if (file_exists($target) && !is_writable($target)) {
  179. throw new Exception(
  180. sprintf(
  181. 'Could not overwrite %s. The target file exists with owner %s, but I am %s',
  182. $source,
  183. $target,
  184. fileowner($target),
  185. get_current_user()
  186. )
  187. );
  188. } elseif (!is_writable(dirname($target))) {
  189. throw new Exception(
  190. sprintf(
  191. 'Could not copy %s to %s. The directory %s is only writable by %s',
  192. $source,
  193. $target,
  194. dirname($target),
  195. fileowner(dirname($target))
  196. )
  197. );
  198. } else {
  199. throw new Exception(sprintf('Could not copy %s to %s. Unknown error.', $source, $target));
  200. }
  201. }
  202. }
  203. $d->close();
  204. } else {
  205. if (!@copy($source, $target)) {
  206. if (file_exists($target) && !is_writable($target)) {
  207. throw new Exception(
  208. sprintf(
  209. 'Could not overwrite %s. The target file exists with owner %s, but I am %s',
  210. $source,
  211. $target,
  212. fileowner($target),
  213. get_current_user()
  214. )
  215. );
  216. } elseif (!is_writable(dirname($target))) {
  217. throw new Exception(
  218. sprintf(
  219. 'Could not copy %s to %s. The directory %s is only writable by %s',
  220. $source,
  221. $target,
  222. dirname($target),
  223. get_current_user()
  224. )
  225. );
  226. } else {
  227. throw new Exception(sprintf('Could not copy %s to %s. Unknown error.', $source, $target));
  228. }
  229. }
  230. }
  231. }
  232. public static function copyDirectory($sourceDir, $targetDir)
  233. {
  234. if (!file_exists($sourceDir)) {
  235. return false;
  236. }
  237. if (!is_dir($sourceDir)) {
  238. return copy($sourceDir, $targetDir);
  239. }
  240. if (!mkdir($targetDir)) {
  241. return false;
  242. }
  243. foreach (scandir($sourceDir) as $item) {
  244. if ($item == '.' || $item == '..') {
  245. continue;
  246. }
  247. if (!self::copyDirectory(
  248. $sourceDir . DIRECTORY_SEPARATOR . $item,
  249. $targetDir . DIRECTORY_SEPARATOR . $item
  250. )
  251. ) {
  252. return false;
  253. }
  254. }
  255. return true;
  256. }
  257. public static function recurse_copy($src, $dst)
  258. {
  259. $dir = opendir($src);
  260. @mkdir($dst);
  261. while (false !== ($file = readdir($dir))) {
  262. if (($file != '.') && ($file != '..')) {
  263. if (is_dir($src . '/' . $file)) {
  264. self::recurse_copy($src . '/' . $file, $dst . '/' . $file);
  265. } else {
  266. copy($src . '/' . $file, $dst . '/' . $file);
  267. }
  268. }
  269. }
  270. closedir($dir);
  271. }
  272. public static function CountFileLines($strFile)
  273. {
  274. if ($hndFile = fopen($strFile, 'r')) {
  275. $intLines = 0;
  276. while (fgets($hndFile)) {
  277. $intLines++;
  278. }
  279. fclose($hndFile);
  280. return $intLines;
  281. } else {
  282. return false;
  283. }
  284. }
  285. public static function SearchDirectoryByName($strPathToStartFrom, $strDirectoryName, $blnCaseSensitive = false)
  286. {
  287. $arrSearchResult = self::ListDirectory($strPathToStartFrom, null, null, null, true);
  288. $arrFoundDirectory = array();
  289. if (is_array($arrSearchResult)) {
  290. foreach ($arrSearchResult as $intIndex => $strPath) {
  291. if (trim($strPath) == trim($strPathToStartFrom)) {
  292. continue;
  293. }
  294. if ($blnCaseSensitive && is_dir($strPath) && trim($strDirectoryName) == trim(basename($strPath))) {
  295. $arrFoundDirectory[] = $strPath;
  296. }
  297. if (!$blnCaseSensitive && is_dir($strPath) && strtolower(trim($strDirectoryName)) == strtolower(
  298. trim(basename($strPath))
  299. )
  300. ) {
  301. $arrFoundDirectory[] = $strPath;
  302. }
  303. }
  304. } else {
  305. return false;
  306. }
  307. if (count($arrFoundDirectory) > 0) {
  308. return $arrFoundDirectory;
  309. } else {
  310. return false;
  311. }
  312. }
  313. public static function ListDirectory(
  314. $strDir = '.',
  315. $strIncludePattern = null,
  316. $strExcludePattern = null,
  317. $strExcludePath = null,
  318. $blnIncludeDirectories = false
  319. )
  320. {
  321. $arrFiles = array();
  322. if (is_dir($strDir)) {
  323. $hndFile = opendir($strDir);
  324. if ($blnIncludeDirectories) {
  325. $blnContinue = false;
  326. if (!is_null($strIncludePattern) && !preg_match($strIncludePattern, $strDir)) {
  327. $blnContinue = true;
  328. }
  329. if (!$blnContinue && !is_null($strExcludePattern) && preg_match($strExcludePattern, $strDir)) {
  330. $blnContinue = true;
  331. }
  332. if (!$blnContinue) {
  333. array_push(
  334. $arrFiles,
  335. (!is_null($strExcludePath)) ? str_replace($strExcludePath, '', $strDir) : $strDir
  336. );
  337. }
  338. }
  339. while (($strFile = readdir($hndFile)) !== false) {
  340. // loop through the files, skipping . and .., and recursing if necessary
  341. if (strcmp($strFile, '.') == 0 || strcmp($strFile, '..') == 0) {
  342. continue;
  343. }
  344. $strFilePath = $strDir . '/' . $strFile;
  345. if (is_dir($strFilePath)) {
  346. $arrFiles = array_merge(
  347. $arrFiles,
  348. self::ListDirectory(
  349. $strFilePath,
  350. $strIncludePattern,
  351. $strExcludePattern,
  352. $strExcludePath,
  353. $blnIncludeDirectories
  354. )
  355. );
  356. } else {
  357. if ($strIncludePattern && !preg_match($strIncludePattern, $strFilePath)) {
  358. continue;
  359. }
  360. if ($strExcludePattern && preg_match($strExcludePattern, $strFilePath)) {
  361. continue;
  362. }
  363. if ($strExcludePath) {
  364. array_push($arrFiles, str_replace($strExcludePath, '', $strFilePath));
  365. continue;
  366. }
  367. array_push($arrFiles, $strFilePath);
  368. }
  369. }
  370. closedir($hndFile);
  371. } else {
  372. // false if the function was called with an invalid non-directory argument
  373. $arrFiles = false;
  374. }
  375. return $arrFiles;
  376. }
  377. public static function IsProcessRunning($strOperation, $intProjectId)
  378. {
  379. $strSearchCmd = sprintf(
  380. 'egrep -e "php.*--%s.*--project %d.*--translation-lang %s"',
  381. $strOperation,
  382. $intProjectId,
  383. QApplication::$TargetLanguage->LanguageCode
  384. );
  385. $strPsFindCmd = 'ps aux | ' . $strSearchCmd;
  386. $arrCmdLines = explode("\n", `$strPsFindCmd`);
  387. if (is_array($arrCmdLines)) {
  388. foreach ($arrCmdLines as $strCmdLine) {
  389. if (preg_match("/(\S{1,})(\s{1,})(\d{1,})/", $strCmdLine, $arrMatches)) {
  390. if (strstr($strCmdLine, 'egrep') || $arrMatches[3] == 0) {
  391. continue;
  392. } else {
  393. return $arrMatches[3];
  394. }
  395. } else {
  396. return false;
  397. }
  398. }
  399. }
  400. /**
  401. * If exec functions are disabled, return false, surely no process is running in background
  402. */
  403. return false;
  404. }
  405. /**
  406. *
  407. * A better version of exec()
  408. * @param string $strCommand The command to run
  409. * @param array $arrOutput An array where you'll get the output
  410. * @param array $arrError An array where you'll get the errors
  411. * @param integer $intRetVal The return value of the command
  412. * @param boolean $blnInBackground Whether to launch the command in background
  413. * @param array $env Associative array with environment variables
  414. * @param string $cwd The directory to switch to before running the command
  415. * @param boolean $blnLogErrors Whether to log the errors in the database
  416. *
  417. * @return boolean
  418. */
  419. public static function Exec(
  420. $strCommand,
  421. &$arrOutput,
  422. &$arrError,
  423. &$intRetVal,
  424. $blnInBackground = false,
  425. $env = null,
  426. $cwd = null,
  427. $blnLogErrors = true
  428. )
  429. {
  430. $process = proc_open(
  431. $strCommand . (($blnInBackground) ? ' &' : ''),
  432. array(
  433. 1 => array("pipe", 'w'),
  434. 2 => array("pipe", 'w')
  435. ),
  436. $pipes,
  437. $cwd,
  438. $env
  439. );
  440. if (!$blnInBackground) {
  441. if (is_resource($process)) {
  442. $arrOutput = explode("\n", stream_get_contents($pipes[1]));
  443. fclose($pipes[1]);
  444. $arrError = explode("\n", stream_get_contents($pipes[2]));
  445. fclose($pipes[2]);
  446. // It is important that you close any pipes before calling
  447. // proc_close in order to avoid a deadlock
  448. $intRetVal = proc_close($process);
  449. if ($intRetVal != 0 && $blnLogErrors) {
  450. NarroLogger::LogError(
  451. sprintf(
  452. 'Running "%s" in "%s" returned %d',
  453. $strCommand,
  454. is_null($cwd) ? getcwd() : $cwd,
  455. $intRetVal
  456. )
  457. );
  458. foreach ($arrOutput as $strOutput) {
  459. NarroLogger::LogInfo($strOutput);
  460. }
  461. foreach ($arrError as $strOutput) {
  462. NarroLogger::LogError($strOutput);
  463. }
  464. return false;
  465. }
  466. NarroLogger::LogDebug(sprintf('Running "%s" in "%s"', $strCommand, is_null($cwd) ? getcwd() : $cwd));
  467. return true;
  468. } else {
  469. return false;
  470. }
  471. } else {
  472. if (is_resource($process)) {
  473. return true;
  474. } else {
  475. return false;
  476. }
  477. }
  478. }
  479. public static function CanExec($strCommand)
  480. {
  481. $intRetCode = 0;
  482. exec($strCommand, $arrOutput, $intRetCode);
  483. return ($intRetCode == 0);
  484. }
  485. public static function rsearch($folder, $pattern)
  486. {
  487. $dir = new RecursiveDirectoryIterator($folder);
  488. $ite = new RecursiveIteratorIterator($dir);
  489. $files = new RegexIterator($ite, $pattern, RegexIterator::GET_MATCH);
  490. $fileList = array();
  491. foreach ($files as $file) {
  492. $fileList = array_merge($fileList, $file);
  493. }
  494. return $fileList;
  495. }
  496. public static function rglob($pattern, $flags = 0, $path = '')
  497. {
  498. if (!$path && ($dir = dirname($pattern)) != '.') {
  499. if ($dir == '\\' || $dir == '/') {
  500. $dir = '';
  501. }
  502. return rglob(basename($pattern), $flags, $dir . '/');
  503. }
  504. $paths = glob($path . '*', GLOB_ONLYDIR | GLOB_NOSORT);
  505. $files = glob($path . $pattern, $flags);
  506. foreach ($paths as $p) {
  507. $files = array_merge($files, self::rglob($pattern, $flags, $p . '/'));
  508. }
  509. return $files;
  510. }
  511. public function globr($sDir, $sPattern, $nFlags = null)
  512. {
  513. $sDir = escapeshellcmd($sDir);
  514. // Get the list of all matching files currently in the
  515. // directory.
  516. $aFiles = glob("$sDir/$sPattern", $nFlags);
  517. // Then get a list of all directories in this directory, and
  518. // run ourselves on the resulting array. This is the
  519. // recursion step, which will not execute if there are no
  520. // directories.
  521. if (glob("$sDir/*", GLOB_ONLYDIR)) {
  522. foreach (glob("$sDir/*", GLOB_ONLYDIR) as $sSubDir) {
  523. $aSubFiles = $this->globr($sSubDir, $sPattern, $nFlags);
  524. $aFiles = array_merge($aFiles, $aSubFiles);
  525. }
  526. }
  527. // The array we return contains the files we found, and the
  528. // files all of our children found.
  529. return $aFiles;
  530. }
  531. public static function utf8_urldecode($str)
  532. {
  533. $str = preg_replace("/%u([0-9a-f]{3,4})/i", "&#x\\1;", urldecode($str));
  534. return html_entity_decode($str, null, 'UTF-8');;
  535. }
  536. }