/content/plugins/w3-total-cache/Util_File.php

https://gitlab.com/karlen/ayo_wp · PHP · 418 lines · 266 code · 62 blank · 90 comment · 67 complexity · daea97e1e8d9277ca346b73f3b1ef5fe MD5 · raw file

  1. <?php
  2. namespace W3TC;
  3. class Util_File {
  4. /**
  5. * Recursive creates directory
  6. *
  7. * @param string $path
  8. * @param integer $mask
  9. * @param string $curr_path
  10. * @return boolean
  11. */
  12. static public function mkdir( $path, $mask = 0777, $curr_path = '' ) {
  13. $path = Util_Environment::realpath( $path );
  14. $path = trim( $path, '/' );
  15. $dirs = explode( '/', $path );
  16. foreach ( $dirs as $dir ) {
  17. if ( $dir == '' ) {
  18. return false;
  19. }
  20. $curr_path .= ( $curr_path == '' ? '' : '/' ) . $dir;
  21. if ( !@is_dir( $curr_path ) ) {
  22. if ( !@mkdir( $curr_path, $mask ) ) {
  23. return false;
  24. }
  25. }
  26. }
  27. return true;
  28. }
  29. /**
  30. * Recursive creates directory from some directory
  31. * Does not try to create directory before from
  32. *
  33. * @param string $path
  34. * @param string $from_path
  35. * @param integer $mask
  36. * @return boolean
  37. */
  38. static public function mkdir_from( $path, $from_path = '', $mask = 0777 ) {
  39. $path = Util_Environment::realpath( $path );
  40. $from_path = Util_Environment::realpath( $from_path );
  41. if ( substr( $path, 0, strlen( $from_path ) ) != $from_path )
  42. return false;
  43. $path = substr( $path, strlen( $from_path ) );
  44. $path = trim( $path, '/' );
  45. $dirs = explode( '/', $path );
  46. $curr_path = $from_path;
  47. foreach ( $dirs as $dir ) {
  48. if ( $dir == '' ) {
  49. return false;
  50. }
  51. $curr_path .= ( $curr_path == '' ? '' : '/' ) . $dir;
  52. if ( !@is_dir( $curr_path ) ) {
  53. if ( !@mkdir( $curr_path, $mask ) ) {
  54. return false;
  55. }
  56. }
  57. }
  58. return true;
  59. }
  60. /**
  61. * Recursive remove dir
  62. *
  63. * @param string $path
  64. * @param array $exclude
  65. * @param bool $remove
  66. * @return void
  67. */
  68. static public function rmdir( $path, $exclude = array(), $remove = true ) {
  69. $dir = @opendir( $path );
  70. if ( $dir ) {
  71. while ( ( $entry = @readdir( $dir ) ) !== false ) {
  72. if ( $entry == '.' || $entry == '..' ) {
  73. continue;
  74. }
  75. foreach ( $exclude as $mask ) {
  76. if ( fnmatch( $mask, basename( $entry ) ) ) {
  77. continue 2;
  78. }
  79. }
  80. $full_path = $path . DIRECTORY_SEPARATOR . $entry;
  81. if ( @is_dir( $full_path ) ) {
  82. Util_File::rmdir( $full_path, $exclude );
  83. } else {
  84. @unlink( $full_path );
  85. }
  86. }
  87. @closedir( $dir );
  88. if ( $remove ) {
  89. @rmdir( $path );
  90. }
  91. }
  92. }
  93. /**
  94. * Recursive empty dir
  95. *
  96. * @param string $path
  97. * @param array $exclude
  98. * @return void
  99. */
  100. static public function emptydir( $path, $exclude = array() ) {
  101. Util_File::rmdir( $path, $exclude, false );
  102. }
  103. /**
  104. * Check if file is write-able
  105. *
  106. * @param string $file
  107. * @return boolean
  108. */
  109. static public function is_writable( $file ) {
  110. $exists = file_exists( $file );
  111. $fp = @fopen( $file, 'a' );
  112. if ( $fp ) {
  113. fclose( $fp );
  114. if ( !$exists ) {
  115. @unlink( $file );
  116. }
  117. return true;
  118. }
  119. return false;
  120. }
  121. /**
  122. * Cehck if dir is write-able
  123. *
  124. * @param string $dir
  125. * @return boolean
  126. */
  127. static public function is_writable_dir( $dir ) {
  128. $file = $dir . '/' . uniqid( mt_rand() ) . '.tmp';
  129. return Util_File::is_writable( $file );
  130. }
  131. /**
  132. * Returns dirname of path
  133. *
  134. * @param string $path
  135. * @return string
  136. */
  137. static public function dirname( $path ) {
  138. $dirname = dirname( $path );
  139. if ( $dirname == '.' || $dirname == '/' || $dirname == '\\' ) {
  140. $dirname = '';
  141. }
  142. return $dirname;
  143. }
  144. static public function make_relative_path( $filename, $base_dir ) {
  145. $filename = Util_Environment::realpath( $filename );
  146. $base_dir = Util_Environment::realpath( $base_dir );
  147. $filename_parts = explode( '/', trim( $filename, '/' ) );
  148. $base_dir_parts = explode( '/', trim( $base_dir, '/' ) );
  149. // count number of equal path parts
  150. for ( $equal_number = 0;;$equal_number++ ) {
  151. if ( $equal_number >= count( $filename_parts ) ||
  152. $equal_number >= count( $base_dir_parts ) )
  153. break;
  154. if ( $filename_parts[$equal_number] != $base_dir_parts[$equal_number] )
  155. break;
  156. }
  157. $relative_dir = str_repeat( '../', count( $base_dir_parts ) - $equal_number );
  158. $relative_dir .= implode( '/', array_slice( $filename_parts, $equal_number ) );
  159. return $relative_dir;
  160. }
  161. /**
  162. * Returns open basedirs
  163. *
  164. * @return array
  165. */
  166. static public function get_open_basedirs() {
  167. $open_basedir_ini = ini_get( 'open_basedir' );
  168. $open_basedirs = ( W3TC_WIN ? preg_split( '~[;,]~', $open_basedir_ini ) : explode( ':', $open_basedir_ini ) );
  169. $result = array();
  170. foreach ( $open_basedirs as $open_basedir ) {
  171. $open_basedir = trim( $open_basedir );
  172. if ( !empty( $open_basedir ) && $open_basedir != '' ) {
  173. $result[] = Util_Environment::realpath( $open_basedir );
  174. }
  175. }
  176. return $result;
  177. }
  178. /**
  179. * Checks if path is restricted by open_basedir
  180. *
  181. * @param string $path
  182. * @return boolean
  183. */
  184. static public function check_open_basedir( $path ) {
  185. $path = Util_Environment::realpath( $path );
  186. $open_basedirs = Util_File::get_open_basedirs();
  187. if ( !count( $open_basedirs ) ) {
  188. return true;
  189. }
  190. foreach ( $open_basedirs as $open_basedir ) {
  191. if ( strstr( $path, $open_basedir ) !== false ) {
  192. return true;
  193. }
  194. }
  195. return false;
  196. }
  197. static public function get_file_permissions( $file ) {
  198. if ( function_exists( 'fileperms' ) && $fileperms = @fileperms( $file ) ) {
  199. $fileperms = 0777 & $fileperms;
  200. } else {
  201. clearstatcache();
  202. $stat=@stat( $file );
  203. if ( $stat )
  204. $fileperms = 0777 & $stat['mode'];
  205. else
  206. $fileperms = 0;
  207. }
  208. return $fileperms;
  209. }
  210. static public function get_file_owner( $file = '' ) {
  211. $fileowner = $filegroup = 'unknown';
  212. if ( $file ) {
  213. if ( function_exists( 'fileowner' ) && function_exists( 'fileowner' ) ) {
  214. $fileowner = @fileowner( $file );
  215. $filegroup = @filegroup( $file );
  216. if ( function_exists( 'posix_getpwuid' ) && function_exists( 'posix_getgrgid' ) ) {
  217. $fileowner = @posix_getpwuid( $fileowner );
  218. $fileowner = $fileowner['name'];
  219. $filegroup = @posix_getgrgid( $filegroup );
  220. $filegroup = $filegroup['name'];
  221. }
  222. }
  223. } else {
  224. if ( function_exists( 'getmyuid' ) && function_exists( 'getmygid' ) ) {
  225. $fileowner = @getmyuid();
  226. $filegroup = @getmygid();
  227. if ( function_exists( 'posix_getpwuid' ) && function_exists( 'posix_getgrgid' ) ) {
  228. $fileowner = @posix_getpwuid( $fileowner );
  229. $fileowner = $fileowner['name'];
  230. $filegroup = @posix_getgrgid( $filegroup );
  231. $filegroup = $filegroup['name'];
  232. }
  233. }
  234. }
  235. return $fileowner . ':' . $filegroup;
  236. }
  237. /**
  238. * Creates W3TC_CACHE_TMP_DIR dir if required
  239. *
  240. * @throws Exception
  241. * @return string
  242. */
  243. static public function create_tmp_dir() {
  244. if ( !is_dir( W3TC_CACHE_TMP_DIR ) || !is_writable( W3TC_CACHE_TMP_DIR ) ) {
  245. Util_File::mkdir_from( W3TC_CACHE_TMP_DIR, W3TC_CACHE_DIR );
  246. if ( !is_dir( W3TC_CACHE_TMP_DIR ) || !is_writable( W3TC_CACHE_TMP_DIR ) ) {
  247. throw new \Exception( 'Can\'t create folder <strong>' .
  248. W3TC_CACHE_TMP_DIR . '</strong>' );
  249. }
  250. }
  251. return W3TC_CACHE_TMP_DIR;
  252. }
  253. /**
  254. * Atomically writes file inside W3TC_CACHE_DIR dir
  255. *
  256. * @param unknown $filename
  257. * @param unknown $content
  258. * @throws Exception
  259. * @return void
  260. */
  261. static public function file_put_contents_atomic( $filename, $content ) {
  262. Util_File::create_tmp_dir();
  263. $temp = tempnam( W3TC_CACHE_TMP_DIR, 'temp' );
  264. try {
  265. if ( !( $f = @fopen( $temp, 'wb' ) ) ) {
  266. if ( file_exists( $temp ) )
  267. @unlink( $temp );
  268. throw new \Exception( 'Can\'t write to temporary file <strong>' .
  269. $temp . '</strong>' );
  270. }
  271. fwrite( $f, $content );
  272. fclose( $f );
  273. if ( !@rename( $temp, $filename ) ) {
  274. @unlink( $filename );
  275. if ( !@rename( $temp, $filename ) ) {
  276. Util_File::mkdir_from( dirname( $filename ), W3TC_CACHE_DIR );
  277. if ( !@rename( $temp, $filename ) ) {
  278. throw new \Exception( 'Can\'t write to file <strong>' .
  279. $filename . '</strong>' );
  280. }
  281. }
  282. }
  283. $chmod = 0644;
  284. if ( defined( 'FS_CHMOD_FILE' ) )
  285. $chmod = FS_CHMOD_FILE;
  286. @chmod( $filename, $chmod );
  287. } catch ( \Exception $ex ) {
  288. if ( file_exists( $temp ) )
  289. @unlink( $temp );
  290. throw $ex;
  291. }
  292. }
  293. /**
  294. * Takes a W3TC settings array and formats it to a PHP String
  295. *
  296. * @param unknown $data
  297. * @return string
  298. */
  299. static public function format_data_as_settings_file( $data ) {
  300. $config = "<?php\r\n\r\nreturn array(\r\n";
  301. foreach ( $data as $key => $value )
  302. $config .= Util_File::format_array_entry_as_settings_file_entry( 1, $key, $value );
  303. $config .= ");";
  304. return $config;
  305. }
  306. /**
  307. * Writes array item to file
  308. *
  309. * @param int $tabs
  310. * @param string $key
  311. * @param mixed $value
  312. * @return string
  313. */
  314. static public function format_array_entry_as_settings_file_entry( $tabs, $key, $value ) {
  315. $item = str_repeat( "\t", $tabs );
  316. if ( is_numeric( $key ) && (string)(int)$key === (string)$key ) {
  317. $item .= sprintf( "%d => ", $key );
  318. } else {
  319. $item .= sprintf( "'%s' => ", addcslashes( $key, "'\\" ) );
  320. }
  321. switch ( gettype( $value ) ) {
  322. case 'object':
  323. case 'array':
  324. $item .= "array(\r\n";
  325. foreach ( (array)$value as $k => $v ) {
  326. $item .= Util_File::format_array_entry_as_settings_file_entry( $tabs + 1, $k, $v );
  327. }
  328. $item .= sprintf( "%s),\r\n", str_repeat( "\t", $tabs ) );
  329. return $item;
  330. case 'integer':
  331. $data = (string)$value;
  332. break;
  333. case 'double':
  334. $data = (string)$value;
  335. break;
  336. case 'boolean':
  337. $data = ( $value ? 'true' : 'false' );
  338. break;
  339. case 'NULL':
  340. $data = 'null';
  341. break;
  342. default:
  343. case 'string':
  344. $data = "'" . addcslashes( $value, "'\\" ) . "'";
  345. break;
  346. }
  347. $item .= $data . ",\r\n";
  348. return $item;
  349. }
  350. }