/public/wp-content/plugins/better-wp-security/core/lib/class-itsec-lib-directory.php

https://gitlab.com/kath.de/cibedo_cibedo.de · PHP · 265 lines · 116 code · 48 blank · 101 comment · 29 complexity · 0775974023f09386c7845ef87318c423 MD5 · raw file

  1. <?php
  2. /**
  3. * iThemes Security directory library.
  4. *
  5. * Contains the ITSEC_Lib_Directory class.
  6. *
  7. * @package iThemes_Security
  8. */
  9. /**
  10. * iThemes Security Directory Library class.
  11. *
  12. * Utility class for managing directories.
  13. *
  14. * @package iThemes_Security
  15. * @since 1.15.0
  16. */
  17. class ITSEC_Lib_Directory {
  18. /**
  19. * Get a listing of files and subdirectories contained in the supplied directory.
  20. *
  21. * @since 1.15.0
  22. *
  23. * @return array|WP_Error An array of the files and directories on success or a WP_Error object if an error occurs.
  24. */
  25. public static function read( $dir ) {
  26. $callable = array();
  27. if ( ITSEC_Lib_Utility::is_callable_function( 'opendir' ) && ITSEC_Lib_Utility::is_callable_function( 'readdir' ) && ITSEC_Lib_Utility::is_callable_function( 'closedir' ) ) {
  28. $callable[] = 'opendir';
  29. }
  30. if ( ITSEC_Lib_Utility::is_callable_function( 'glob' ) ) {
  31. $callable[] = 'glob';
  32. }
  33. if ( empty( $callable ) ) {
  34. return new WP_Error( 'itsec-lib-directory-read-no-callable-functions', sprintf( __( '%s could not be read. Both the opendir/readdir/closedir and glob functions are disabled on the server.', 'better-wp-security' ), $dir ) );
  35. }
  36. if ( in_array( 'opendir', $callable ) ) {
  37. if ( false !== ( $dh = opendir( $dir ) ) ) {
  38. $files = array();
  39. while ( false !== ( $file = readdir( $dh ) ) ) {
  40. if ( in_array( basename( $file ), array( '.', '..' ) ) ) {
  41. continue;
  42. }
  43. $files[] = "$dir/$file";
  44. }
  45. closedir( $dh );
  46. sort( $files );
  47. return $files;
  48. }
  49. }
  50. if ( ITSEC_Lib_Utility::is_callable_function( 'glob' ) ) {
  51. $visible = glob( "$dir/*" );
  52. $hidden = glob( "$dir/.*" );
  53. if ( false !== $visible || false !== $hidden ) {
  54. if ( false === $visible ) {
  55. $visible = array();
  56. }
  57. if ( false === $hidden ) {
  58. $hidden = array();
  59. }
  60. $files = array_merge( $visible, $hidden );
  61. foreach ( $files as $index => $file ) {
  62. if ( in_array( basename( $file ), array( '.', '..' ) ) ) {
  63. unset( $files[$index] );
  64. }
  65. }
  66. sort( $files );
  67. return $files;
  68. }
  69. }
  70. return new WP_Error( 'itsec-lib-directory-read-cannot-read', sprintf( __( '%s could not be read due to an unknown error.', 'better-wp-security' ), $dir ) );
  71. }
  72. /**
  73. * Determine if the supplied directory exists.
  74. *
  75. * @since 1.15.0
  76. *
  77. * @param string $dir Full path to the directory to test.
  78. * @return bool|WP_Error Boolean true if it exists, false if it does not
  79. */
  80. public static function is_dir( $dir ) {
  81. $dir = rtrim( $dir, '/' );
  82. @clearstatcache( true, $dir );
  83. return @is_dir( $dir );
  84. }
  85. /**
  86. * Create the supplied directory.
  87. *
  88. * @since 1.15.0
  89. *
  90. * @param string $dir Full path to the directory to create.
  91. * @return bool|WP_Error Boolean true if it is created successfully, WP_Error object otherwise.
  92. */
  93. public static function create( $dir ) {
  94. $dir = rtrim( $dir, '/' );
  95. if ( self::is_dir( $dir ) ) {
  96. return true;
  97. }
  98. if ( ITSEC_Lib_File::exists( $dir ) ) {
  99. return new WP_Error( 'itsec-lib-directory-create-file-exists', sprintf( __( 'The directory %s could not be created as a file with that name already exists.', 'better-wp-security' ), $dir ) );
  100. }
  101. if ( ! ITSEC_Lib_Utility::is_callable_function( 'mkdir' ) ) {
  102. return new WP_Error( 'itsec-lib-directory-create-mkdir-is-disabled', sprintf( __( 'The directory %s could not be created as the mkdir() function is disabled. This is a system configuration issue.', 'better-wp-security' ), $dir ) );
  103. }
  104. $parent = dirname( $dir );
  105. while ( ! empty( $parent ) && ( ! self::is_dir( $parent ) ) ) {
  106. $parent = dirname( $parent );
  107. }
  108. if ( empty( $parent ) ) {
  109. return new WP_Error( 'itsec-lib-directory-create-unable-to-find-parent', sprintf( __( 'The directory %s could not be created as an existing parent directory could not be found.', 'better-wp-security' ), $dir ) );
  110. }
  111. $perms = self::get_permissions( $parent );
  112. if ( ! is_int( $perms ) ) {
  113. $perms = 0755;
  114. }
  115. $cached_umask = umask( 0 );
  116. $result = @mkdir( $dir, $perms, true );
  117. umask( $cached_umask );
  118. if ( $result ) {
  119. return true;
  120. }
  121. return new WP_Error( 'itsec-lib-directory-create-failed', sprintf( __( 'The directory %s could not be created due to an unknown error. This could be due to a permissions issue.', 'better-wp-security' ), $dir ) );
  122. }
  123. /**
  124. * Recursively remove the supplied directory.
  125. *
  126. * @since 1.15.0
  127. *
  128. * @return bool|WP_Error Boolean true on success or a WP_Error object if an error occurs.
  129. */
  130. public static function remove( $dir ) {
  131. if ( ! ITSEC_Lib_File::exists( $dir ) ) {
  132. return true;
  133. }
  134. if ( ! ITSEC_Lib_Utility::is_callable_function( 'rmdir' ) ) {
  135. return new WP_Error( 'itsec-lib-directory-remove-rmdir-is-disabled', sprintf( __( 'The directory %s could not be removed as the rmdir() function is disabled. This is a system configuration issue.', 'better-wp-security' ), $dir ) );
  136. }
  137. $files = self::read( $dir );
  138. if ( is_wp_error( $files ) ) {
  139. return new WP_Error( 'itsec-lib-directory-remove-read-error', sprintf( __( 'Unable to remove %1$s due to the following error: %2$s', 'better-wp-security' ), $dir, $files->get_error_message() ) );
  140. }
  141. foreach ( $files as $file ) {
  142. if ( ITSEC_Lib_File::is_file( $file ) ) {
  143. ITSEC_Lib_File::remove( $file );
  144. } else if ( self::is_dir( $file ) ) {
  145. self::remove( $file );
  146. }
  147. }
  148. $result = rmdir( $dir );
  149. @clearstatcache( true, $dir );
  150. if ( $result ) {
  151. return true;
  152. }
  153. return new WP_Error( 'itsec-lib-directory-remove-unknown-error', sprintf( __( 'Unable to remove %s due to an unknown error.', 'better-wp-security' ), $dir ) );
  154. }
  155. /**
  156. * Get file permissions from the requested directory.
  157. *
  158. * If the directory permissions cannot be read, a default value of 0644 will be returned.
  159. *
  160. * @since 1.15.0
  161. *
  162. * @param string $dir Full path to the file to retrieve permissions from.
  163. * @return int|WP_Error The permissions as an int or a WP_Error object if an error occurs.
  164. */
  165. public static function get_permissions( $dir ) {
  166. if ( ! self::is_dir( $dir ) ) {
  167. return new WP_Error( 'itsec-lib-dir-get-permissions-missing-dir', sprintf( __( 'Permissions for the directory %s could not be read as the directory could not be found.', 'better-wp-security' ), $dir ) );
  168. }
  169. if ( ! ITSEC_Lib_Utility::is_callable_function( 'fileperms' ) ) {
  170. return new WP_Error( 'itsec-lib-directory-get-permissions-fileperms-is-disabled', sprintf( __( 'Permissions for the directory %s could not be read as the fileperms() function is disabled. This is a system configuration issue.', 'better-wp-security' ), $dir ) );
  171. }
  172. $dir = rtrim( $dir, '/' );
  173. @clearstatcache( true, $dir );
  174. return fileperms( $dir ) & 0777;
  175. }
  176. /**
  177. * Get default file permissions to use for new files.
  178. *
  179. * @since 1.15.0
  180. * @uses FS_CHMOD_DIR Define that sets default file permissions.
  181. *
  182. * @return int|WP_Error The default permissions as an int or a WP_Error object if an error occurs.
  183. */
  184. public static function get_default_permissions() {
  185. if ( defined( 'FS_CHMOD_DIR' ) ) {
  186. return FS_CHMOD_DIR;
  187. }
  188. $perms = self::get_permissions( ABSPATH );
  189. if ( ! is_wp_error( $perms ) ) {
  190. return $perms;
  191. }
  192. return 0755;
  193. }
  194. /**
  195. * Change directory permissions.
  196. *
  197. * @since 1.15.0
  198. *
  199. * @param string $dir Full path to the directory to change permissions for.
  200. * @param int $perms New permissions to set.
  201. * @return bool|WP_Error Boolean true if successful, false if not successful, or WP_Error if the chmod() function
  202. * is unavailable.
  203. */
  204. public static function chmod( $dir, $perms ) {
  205. return ITSEC_Lib_File::chmod( $dir, $perms );
  206. }
  207. }
  208. require_once( dirname( __FILE__ ) . '/class-itsec-lib-utility.php' );
  209. require_once( dirname( __FILE__ ) . '/class-itsec-lib-file.php' );