| @@ -1,113 +1,157 @@ | ||
| 1 | 1 | <?php |
| 2 | + | |
| 2 | 3 | namespace WPIDE\App\Services\Storage; |
| 3 | 4 | |
| 5 | +use WPIDE\App\Classes\Freemius; | |
| 6 | +use const WPIDE\Constants\DIR; | |
| 4 | 7 | use const WPIDE\Constants\CONTENT_DIR; |
| 5 | -use const WPIDE\Constants\DIR; | |
| 6 | -use const WPIDE\Constants\UPLOADS_DIR; | |
| 7 | - | |
| 8 | +use const WPIDE\Constants\FATAL_ERROR_DROPIN; | |
| 9 | +use const WPIDE\Constants\IMAGE_DATA_DIR; | |
| 10 | +use const WPIDE\Constants\TMP_DIR; | |
| 11 | +use const WPIDE\Constants\WP_PATH; | |
| 8 | 12 | use WPIDE\App\AppConfig; |
| 9 | 13 | use WPIDE\App\Services\Storage\Adapters\WPFileSystem; |
| 10 | -use League\Flysystem\Adapter\Local; | |
| 11 | - | |
| 14 | +use WPIDE\App\Services\Storage\Adapters\DefaultFileSystem; | |
| 12 | 15 | class LocalFileSystem { |
| 13 | - | |
| 14 | - public static function load($root = null): Filesystem | |
| 15 | - { | |
| 16 | - | |
| 16 | + public static function load( $root = null ) : Filesystem { | |
| 17 | 17 | $fs = new Filesystem(); |
| 18 | - $fs->init(self::getConfig($root)); | |
| 19 | - | |
| 18 | + $fs->init( self::getConfig( $root ) ); | |
| 20 | 19 | return $fs; |
| 21 | 20 | } |
| 22 | 21 | |
| 23 | - public static function getConfig($root = null, $excluded = []): array | |
| 24 | - { | |
| 25 | - if(empty($root)) { | |
| 26 | - $root = apply_filters('wpide_filesystem_root', AppConfig::get('file.root')); | |
| 22 | + public static function getConfig( $root = null ) : array { | |
| 23 | + if ( empty( $root ) ) { | |
| 24 | + $root = self::getRootDir(); | |
| 27 | 25 | } |
| 28 | - | |
| 29 | - if(!str_contains($root, CONTENT_DIR)) { | |
| 30 | - $root = CONTENT_DIR.$root; | |
| 26 | + if ( !str_contains( $root, WP_PATH ) ) { | |
| 27 | + $root = WP_PATH . $root; | |
| 31 | 28 | } |
| 32 | - | |
| 29 | + $root .= '/'; | |
| 30 | + $root = wp_normalize_path( $root ); | |
| 31 | + $excluded = [ | |
| 32 | + 'dirs' => LocalFileSystem::excludedDirs(), | |
| 33 | + 'files' => LocalFileSystem::excludedFiles(), | |
| 34 | + ]; | |
| 33 | 35 | return [ |
| 34 | - 'root' => $root, | |
| 35 | - 'separator' => '/', | |
| 36 | - 'excluded_dirs' => !empty($excluded['dirs']) ? $excluded['dirs'] : [], | |
| 37 | - 'excluded_files' => !empty($excluded['files']) ? $excluded['files'] : [], | |
| 38 | - 'config' => [], | |
| 39 | - 'adapter' => function() use($root){ | |
| 40 | - | |
| 36 | + 'root' => $root, | |
| 37 | + 'separator' => '/', | |
| 38 | + 'excluded_dirs' => ( !empty( $excluded['dirs'] ) ? $excluded['dirs'] : [] ), | |
| 39 | + 'excluded_files' => ( !empty( $excluded['files'] ) ? $excluded['files'] : [] ), | |
| 40 | + 'config' => [], | |
| 41 | + 'adapter' => function () use($root) { | |
| 41 | 42 | $permissions = [ |
| 42 | 43 | 'file' => [ |
| 43 | - 'public' => defined( 'FS_CHMOD_FILE' ) ? FS_CHMOD_FILE : (fileperms( ABSPATH . 'index.php' ) ? 0644 : 0777), | |
| 44 | + 'public' => ( defined( 'FS_CHMOD_FILE' ) ? FS_CHMOD_FILE : (( fileperms( WP_PATH . '/index.php' ) ? 0644 : 0777 )) ), | |
| 44 | 45 | 'private' => 0600, |
| 45 | 46 | ], |
| 46 | - 'dir' => [ | |
| 47 | - 'public' => defined( 'FS_CHMOD_DIR' ) ? FS_CHMOD_DIR : (fileperms( ABSPATH ) ? 0755 : 0777), | |
| 47 | + 'dir' => [ | |
| 48 | + 'public' => ( defined( 'FS_CHMOD_DIR' ) ? FS_CHMOD_DIR : (( fileperms( WP_PATH ) ? 0755 : 0777 )) ), | |
| 48 | 49 | 'private' => 0700, |
| 49 | 50 | ], |
| 50 | 51 | ]; |
| 51 | - | |
| 52 | - $use_wp_filesystem = false; | |
| 53 | - $credentials = null; | |
| 54 | - | |
| 52 | + global $wp_filesystem; | |
| 53 | + $use_wp_filesystem = false; | |
| 55 | 54 | // Try and use WP filesystem |
| 56 | - if(function_exists('request_filesystem_credentials')) { | |
| 55 | + if ( function_exists( 'request_filesystem_credentials' ) ) { | |
| 56 | + if ( defined( 'FS_METHOD' ) ) { | |
| 57 | + if ( !defined( 'WPIDE_FS_METHOD_FORCED_ELSEWHERE' ) ) { | |
| 58 | + define( 'WPIDE_FS_METHOD_FORCED_ELSEWHERE', FS_METHOD ); | |
| 59 | + } | |
| 60 | + } else { | |
| 61 | + define( 'FS_METHOD', 'direct' ); | |
| 62 | + } | |
| 57 | 63 | ob_start(); |
| 58 | - $credentials = request_filesystem_credentials('', '', false, false); | |
| 64 | + $credentials = request_filesystem_credentials( '', FS_METHOD ); | |
| 59 | 65 | ob_end_clean(); |
| 60 | - $use_wp_filesystem = true; | |
| 66 | + $use_wp_filesystem = !empty( $wp_filesystem ) && wp_filesystem( $credentials ) === true; | |
| 61 | 67 | } |
| 62 | - | |
| 63 | - if ( $use_wp_filesystem && wp_filesystem( $credentials ) ) { | |
| 64 | - global $wp_filesystem; | |
| 65 | - return new WPFileSystem($root, $wp_filesystem, 1, $permissions ); | |
| 66 | - }else{ | |
| 67 | - return new Local($root, LOCK_EX, 1, $permissions ); | |
| 68 | + if ( $use_wp_filesystem ) { | |
| 69 | + return new WPFileSystem( | |
| 70 | + $root, | |
| 71 | + $wp_filesystem, | |
| 72 | + 1, | |
| 73 | + $permissions | |
| 74 | + ); | |
| 75 | + } else { | |
| 76 | + return new DefaultFileSystem( | |
| 77 | + $root, | |
| 78 | + LOCK_EX, | |
| 79 | + 1, | |
| 80 | + $permissions | |
| 81 | + ); | |
| 68 | 82 | } |
| 69 | - | |
| 70 | - } | |
| 83 | + }, | |
| 71 | 84 | ]; |
| 72 | 85 | } |
| 73 | 86 | |
| 87 | + public static function getRootDir() { | |
| 88 | + return AppConfig::get( 'file.root', '/' ); | |
| 89 | + } | |
| 74 | 90 | |
| 75 | - public static function excludedDirs(): array | |
| 76 | - { | |
| 77 | - $user_excluded_dirs = array_filter(AppConfig::get('file.filter_entries', []), function($entry) { | |
| 91 | + public static function advancedModeEnabled() : bool { | |
| 92 | + $advanced_mode = (bool) AppConfig::get( 'file.advanced_mode', false ); | |
| 93 | + if ( $advanced_mode ) { | |
| 94 | + AppConfig::update( 'file.advanced_mode', false ); | |
| 95 | + } | |
| 96 | + $rootDefault = AppConfig::getField( 'file.root.default' ); | |
| 97 | + if ( self::isRootExcluded() ) { | |
| 98 | + AppConfig::update( 'file.root', $rootDefault ); | |
| 99 | + } | |
| 100 | + return false; | |
| 101 | + } | |
| 78 | 102 | |
| 79 | - return substr($entry , -1) === '/'; | |
| 80 | - }); | |
| 103 | + public static function excludedEntries( $type ) : array { | |
| 104 | + $entries = AppConfig::get( 'file.filter_entries', [] ); | |
| 105 | + $entries = ( is_array( $entries ) ? $entries : [] ); | |
| 106 | + return array_filter( $entries, function ( $entry ) use($type) { | |
| 107 | + if ( $type === 'dir' ) { | |
| 108 | + return substr( $entry, -1 ) === '/'; | |
| 109 | + } else { | |
| 110 | + return substr( $entry, -1 ) !== '/'; | |
| 111 | + } | |
| 112 | + } ); | |
| 113 | + } | |
| 81 | 114 | |
| 82 | - return array_merge( | |
| 83 | - [ | |
| 115 | + public static function excludedDirs( $forceSafeMode = false ) : array { | |
| 116 | + $user_excluded_dirs = self::excludedEntries( 'dir' ); | |
| 117 | + $user_excluded_dirs = array_merge( [IMAGE_DATA_DIR, TMP_DIR], $user_excluded_dirs ); | |
| 118 | + if ( $forceSafeMode || !self::advancedModeEnabled() ) { | |
| 119 | + $user_excluded_dirs = array_merge( [ | |
| 84 | 120 | DIR, |
| 85 | - UPLOADS_DIR, | |
| 86 | - ABSPATH . 'wp-admin/', | |
| 87 | - ABSPATH . 'wp-includes/' | |
| 88 | - ], | |
| 89 | - $user_excluded_dirs | |
| 90 | - ); | |
| 121 | + rtrim( DIR, '/' ) . '-pro/', | |
| 122 | + wp_normalize_path( WP_PLUGIN_DIR . '/wpide/' ), | |
| 123 | + wp_normalize_path( WP_PLUGIN_DIR . '/wpide-pro/' ), | |
| 124 | + wp_normalize_path( WP_PATH . '/wp-admin/' ), | |
| 125 | + wp_normalize_path( WP_PATH . '/wp-includes/' ) | |
| 126 | + ], $user_excluded_dirs ); | |
| 127 | + } | |
| 128 | + return $user_excluded_dirs; | |
| 91 | 129 | } |
| 92 | 130 | |
| 93 | - public static function excludedFiles(): array | |
| 94 | - { | |
| 131 | + public static function excludedFiles( $forceSafeMode = false ) : array { | |
| 132 | + $user_excluded_files = self::excludedEntries( 'file' ); | |
| 133 | + $user_excluded_files = array_merge( [CONTENT_DIR . '/' . FATAL_ERROR_DROPIN], $user_excluded_files ); | |
| 134 | + if ( $forceSafeMode || !self::advancedModeEnabled() ) { | |
| 135 | + $user_excluded_files = array_merge( [wp_normalize_path( WP_PATH . '/wp-*.php' ), wp_normalize_path( WP_PATH . '/index.php' ), wp_normalize_path( WP_PATH . '/xmlrpc.php' )], $user_excluded_files ); | |
| 136 | + } | |
| 137 | + return $user_excluded_files; | |
| 138 | + } | |
| 95 | 139 | |
| 96 | - $user_excluded_files = array_filter(AppConfig::get('file.filter_entries', []), function($entry) { | |
| 140 | + public static function isDirExcluded( $path ) : bool { | |
| 141 | + if ( $path !== '/' ) { | |
| 142 | + $path = wp_normalize_path( WP_PATH . '/' . $path . '/' ); | |
| 143 | + foreach ( self::excludedDirs( true ) as $excluded ) { | |
| 144 | + if ( str_contains( $path, $excluded ) ) { | |
| 145 | + return true; | |
| 146 | + } | |
| 147 | + } | |
| 148 | + } | |
| 149 | + return false; | |
| 150 | + } | |
| 97 | 151 | |
| 98 | - return substr($entry , -1) !== '/'; | |
| 99 | - }); | |
| 100 | - | |
| 101 | - return array_merge( | |
| 102 | - [ | |
| 103 | - ABSPATH . '!wp-config.php', | |
| 104 | - ABSPATH . 'wp-*.php', | |
| 105 | - ABSPATH . 'index.php', | |
| 106 | - ABSPATH . 'xmlrpc.php', | |
| 107 | - CONTENT_DIR.'/fatal-error-handler.php', | |
| 108 | - ], | |
| 109 | - $user_excluded_files | |
| 110 | - ); | |
| 152 | + public static function isRootExcluded() : bool { | |
| 153 | + $root = self::getRootDir(); | |
| 154 | + return self::isDirExcluded( $root ); | |
| 111 | 155 | } |
| 112 | 156 | |
| 113 | -} | |
| 157 | +} | |