ath_data = explode( DIRECTORY_SEPARATOR, plugin_basename( $file_path ) ); if ( '' !== $path_data[0] ) { $plugin_slug = $path_data[0]; } else { return false; } $active = false; foreach ( $this->get_plugins() as $slug => $data ) { if ( $plugin_slug === $slug || 0 === strpos( $slug, $plugin_slug ) ) { $active = is_multisite() ? is_plugin_active_for_network( $slug ) : is_plugin_active( $slug ); break; } } return $active; } /** * Get plugin header from any file of the plugin. * * @param string $file_path Absolute file path to the plugin file. * * @return array Return plugin details as array. */ public function get_plugin_headers( $file_path ): array { $plugin_directory = $this->get_plugin_directory_name( $file_path ); return get_plugins( DIRECTORY_SEPARATOR . $plugin_directory ); } /** * Get plugin directory name. * * @param string $file_path Absolute file path to the plugin file. * * @return string Return plugin directory name. */ public function get_plugin_directory_name( $file_path ): string { return (string) strtok( plugin_basename( $file_path ), '/' ); } /** * Get plugin relative path. * * @param string $file_path Absolute file path to the plugin file. * * @return string Return plugin relative path. */ public function get_plugin_relative_path( $file_path ): string { // Normalize the directory separators for cross-platform compatibility. $normalized_path = str_replace( '\\', '/', plugin_basename( $file_path ) ); // Initialize strtok. strtok( $normalized_path, '/' ); // Now fetch the next token, if available, otherwise return an empty string. return (string) strtok( '' ); } /** * Get plugin absolute path. * * @param string $slug Plugin slug. * * @return string */ public function get_abs_plugin_path_by_slug( string $slug = '' ): string { if ( defined( 'WP_PLUGIN_DIR' ) ) { return wp_normalize_path( WP_PLUGIN_DIR ) . DIRECTORY_SEPARATOR . $slug; } return wp_normalize_path( WP_CONTENT_DIR ) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $slug; } /** * Check file exists at wp.org svn. * * @param string $url URL of the file. * * @return boolean Return true for file exists else false. */ private function is_origin_file_exists( $url ): bool { $result = wp_remote_head( $url ); if ( ! is_wp_error( $result ) ) { $http_status_code = wp_remote_retrieve_response_code( $result ); return 200 === $http_status_code; } return false; } /** * Generates the URL for a specific version of a plugin file. * * @param string $directory_name The name of the directory. * @param string $version The version of the file. * @param string $file_path The path of the file. * * @return string The URL of the versioned file. */ private function get_version_url( string $directory_name, string $version, string $file_path ): string { return sprintf( $this->url_plugin_vcs, $directory_name, $version, $file_path ); } /** * Generate the URL for the trunk of a plugin based on the directory name and file path. * * @param string $directory_name The name of the directory. * @param string $file_path The path of the file. * * @return string The URL of the trunk of the plugin. */ private function get_trunk_url( string $directory_name, string $file_path ): string { return sprintf( $this->url_plugin_vcs_trunk, $directory_name, $file_path ); } /** * Generate the URL for a file based on the directory name, version, and file path. * * @param string $directory_name The name of the directory. * @param string $version The version of the file. * @param string $file_path The path of the file. * * @return string The URL of the file. */ private function get_file_url( string $directory_name, string $version, string $file_path ): string { // First try to use the version number provided. $file_url = $this->get_version_url( $directory_name, $version, $file_path ); if ( $this->is_origin_file_exists( $file_url ) ) { return $file_url; } // If that does not exist, try to use the version number with a `.0` suffix. $file_url = $this->get_version_url( $directory_name, $version . '.0', $file_path ); if ( $this->is_origin_file_exists( $file_url ) ) { return $file_url; } // If all else fails, use the trunk of the plugin. return $this->get_trunk_url( $directory_name, $file_path ); } /** * Retrieves the content of a URL by downloading it and reading the contents of the downloaded file. * * @param string $url The URL to download the content from. * * @return string|WP_Error The content of the URL if successful, otherwise a WP_Error object. */ private function get_url_content( $url ) { global $wp_filesystem; // Initialize the WP filesystem, no more using 'file-put-contents' function. if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) { require_once ABSPATH . '/wp-admin/includes/file.php'; WP_Filesystem(); } if ( ! function_exists( 'download_url' ) ) { $ds = DIRECTORY_SEPARATOR; require_once ABSPATH . 'wp-admin' . $ds . 'includes' . $ds . 'file.php'; } $tmp = download_url( $url ); if ( is_wp_error( $tmp ) ) { return $tmp; } $content = $wp_filesystem->get_contents( $tmp ); wp_delete_file( $tmp ); return $content; } /** * Quarantine a plugin. * * @param string $parent_action Parent action. * * @return array|WP_Error */ public function quarantine( string $parent_action ) { if ( ! class_exists( 'WP_Defender\Controller\Quarantine' ) ) { return new WP_Error( 'DEFENDER_PRO_ONLY_FEATURE', defender_quarantine_pro_only() ); } $quarantine_component = wd_di()->get( Quarantine_Component::class ); return $quarantine_component->quarantine_file( $this->owner, $parent_action ); } /** * Detect if the plugin file is quarantinable. * * @param string $file_path File path. * * @return bool Return true if file is in wp.org plugin else false. */ private function is_quarantinable( $file_path ): bool { return $this->is_likely_wporg_slug( $this->get_plugin_directory_name( $file_path ) ); } }