diff --git a/.github/exclude_list b/.github/exclude_list new file mode 100644 index 0000000..4e34f7c --- /dev/null +++ b/.github/exclude_list @@ -0,0 +1,8 @@ +node_modules/ +src/ +package.json +package-lock.json +ruleset.xml +webpack.config.js +*scss/ +.git* diff --git a/.github/workflows/wordpress-plugin-deploy.yml b/.github/workflows/wordpress-plugin-deploy.yml index 2767768..e48b48a 100644 --- a/.github/workflows/wordpress-plugin-deploy.yml +++ b/.github/workflows/wordpress-plugin-deploy.yml @@ -15,9 +15,21 @@ jobs: - name: npm build run: npm run build - name: WordPress Plugin Deploy - uses: 10up/action-wordpress-plugin-deploy@master + uses: 10up/action-wordpress-plugin-deploy@stable with: generate-zip: true env: SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} SVN_USERNAME: ${{ secrets.SVN_USERNAME }} + # Create artifacts + - uses: actions/upload-artifact@v4 + with: + name: ${{ github.event.repository.name }}.zip + path: ${{ github.event.repository.name }}.zip + # Create release + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v2 + with: + files: ${{ github.event.repository.name }}.zip + name: Release ${{ github.ref_name }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0332e3f..00f9460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.10.6 +* Fixed: Detection for unknown embeds +* Fixed: Detection for Maps Marker Pro + ## 1.10.5 * Improved: Renamed Twitter to X * Fixed: Check for matching provider diff --git a/SECURITY.md b/SECURITY.md index 51bddf9..508f459 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,10 +4,10 @@ We usually only support the latest major version. -| Version | Supported | -| ------- | ------------------ | -| 1.9.x | :white_check_mark: | -| < 1.9 | :x: | +| Version | Supported | +| -------- | ------------------ | +| 1.10.x | :white_check_mark: | +| < 1.10 | :x: | ## How can I report security bugs? diff --git a/embed-privacy.php b/embed-privacy.php index d1d6d1d..4902a5d 100644 --- a/embed-privacy.php +++ b/embed-privacy.php @@ -5,7 +5,7 @@ Plugin Name: Embed Privacy Plugin URL: https://epiph.yt/en/embed-privacy/ Description: Embed Privacy prevents from loading external embeds directly and lets the user control which one should be loaded. -Version: 1.10.5 +Version: 1.10.6 Author: Epiphyt Author URI: https://epiph.yt/en/ License: GPL2 @@ -30,7 +30,7 @@ */ \defined( 'ABSPATH' ) || exit; -\define( 'EMBED_PRIVACY_VERSION', '1.10.5' ); +\define( 'EMBED_PRIVACY_VERSION', '1.10.6' ); if ( ! \defined( 'EPI_EMBED_PRIVACY_BASE' ) ) { \define( 'EPI_EMBED_PRIVACY_BASE', \WP_PLUGIN_DIR . '/embed-privacy/' ); diff --git a/inc/class-embed-privacy.php b/inc/class-embed-privacy.php index 186991b..f91354e 100644 --- a/inc/class-embed-privacy.php +++ b/inc/class-embed-privacy.php @@ -766,6 +766,25 @@ public function is_theme( $name ) { return Theme::is( $name ); } + /** + * Get the WP_Filesystem object + * + * @return \WP_Filesystem_Direct WP_Filesystem object + */ + public static function get_wp_filesystem() { + /** @var \WP_Filesystem_Direct $wp_filesystem */ + global $wp_filesystem; + + // initialize the WP filesystem if not exists + if ( empty( $wp_filesystem ) ) { + require_once \ABSPATH . 'wp-admin/includes/file.php'; + + \WP_Filesystem(); + } + + return $wp_filesystem; + } + /** * Load the translation files. */ diff --git a/inc/class-migration.php b/inc/class-migration.php index b2efc14..589b783 100644 --- a/inc/class-migration.php +++ b/inc/class-migration.php @@ -29,7 +29,7 @@ class Migration { * @var string Current migration version * @since 1.2.2 */ - private $version = '1.10.5'; + private $version = '1.10.6'; /** * Migration constructor. @@ -80,7 +80,7 @@ private function add_embed( array $embed ) { * @since 1.5.0 */ private function create_thumbnails_dir() { - $directory = Thumbnails::get_instance()->get_directory(); + $directory = Thumbnail::get_directory(); if ( empty( $directory['base_dir'] ) ) { return; @@ -189,32 +189,40 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->update_option( 'migration_count', (int) $this->get_option( 'migration_count' ) + 1 ); // load textdomain early for migrations \load_plugin_textdomain( 'embed-privacy', false, \dirname( \plugin_basename( Embed_Privacy::get_instance()->plugin_file ) ) . '/languages' ); - // make sure all default embed providers are avalable and translated + // make sure all default embed providers are available and translated $this->register_default_embed_providers(); switch ( $version ) { case $this->version: // most recent version, do nothing break; + case '1.10.5': + $this->migrate_1_10_6(); + break; case '1.8.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); break; case '1.7.3': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); break; case '1.7.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_3(); break; case '1.6.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_3(); $this->migrate_1_7_0(); break; case '1.5.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_3(); @@ -222,6 +230,7 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->migrate_1_6_0(); break; case '1.4.7': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_0(); @@ -229,6 +238,7 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->migrate_1_5_0(); break; case '1.4.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_0(); @@ -237,6 +247,7 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->migrate_1_4_7(); break; case '1.3.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_0(); @@ -245,6 +256,7 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->migrate_1_4_0(); break; case '1.2.2': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_0(); @@ -254,6 +266,7 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->migrate_1_3_0(); break; case '1.2.1': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_0(); @@ -264,6 +277,7 @@ public function migrate( $deprecated = null, $deprecated2 = null ) { $this->migrate_1_2_2(); break; case '1.2.0': + $this->migrate_1_10_6(); $this->migrate_1_10_5(); $this->migrate_1_8_0(); $this->migrate_1_7_0(); @@ -521,9 +535,9 @@ private function migrate_1_5_0() { 'regex_default' => '', ], /* translators: embed provider */ - 'post_content' => \sprintf( \__( 'Click here to display content from %s.', 'embed-privacy' ), \_x( 'Maps Marker', 'embed provider', 'embed-privacy' ) ), + 'post_content' => \sprintf( \__( 'Click here to display content from %s.', 'embed-privacy' ), \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ) ), 'post_status' => 'publish', - 'post_title' => \_x( 'Maps Marker', 'embed provider', 'embed-privacy' ), + 'post_title' => \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ), 'post_type' => 'epi_embed', ] ); $this->create_thumbnails_dir(); @@ -645,7 +659,7 @@ private function migrate_1_7_3() { // move thumbnail if ( \file_exists( $old_dir . '/' . $filename ) ) { - \rename( $old_dir . '/' . $filename, $new_dir . '/' . $filename ); + Embed_Privacy::get_wp_filesystem()->move( $old_dir . '/' . $filename, $new_dir . '/' . $filename ); } } } @@ -654,13 +668,9 @@ private function migrate_1_7_3() { $posts = \get_posts( $post_args ); } - // remove old directory if it's empty + // remove old directory if ( ! ( new FilesystemIterator( $old_dir ) )->valid() ) { - \rmdir( $old_dir ); - - if ( ! ( new FilesystemIterator( \dirname( $old_dir ) ) )->valid() ) { - \rmdir( \dirname( $old_dir ) ); - } + Embed_Privacy::get_wp_filesystem()->rmdir( $old_dir, true ); } } } @@ -726,6 +736,41 @@ private function migrate_1_10_5() { } } + /** + * Migrations for version 1.10.6. + * + * @since 1.10.6 + * + * - Rename Maps Marker to Maps Marker Pro + */ + private function migrate_1_10_6() { + $maps_marker_provider = \get_posts( [ + 'meta_key' => 'is_system', + 'meta_value' => 'yes', + 'name' => 'maps-marker', + 'no_found_rows' => true, + 'post_type' => 'epi_embed', + 'update_post_term_cache' => false, + ] ); + $maps_marker_provider = \reset( $maps_marker_provider ); + + if ( $maps_marker_provider instanceof WP_Post ) { + $maps_marker_pro_provider = [ + 'ID' => $maps_marker_provider->ID, + 'post_name' => \sanitize_title( \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ) ), + 'post_title' => \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ), + ]; + + /* translators: embed provider */ + if ( $maps_marker_provider->post_content === \sprintf( \__( 'Click here to display content from %s.', 'embed-privacy' ), \_x( 'Maps Marker', 'embed provider', 'embed-privacy' ) ) ) { + /* translators: embed provider */ + $maps_marker_pro_provider['post_content'] = \sprintf( \__( 'Click here to display content from %s.', 'embed-privacy' ), \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ) ); + } + + \wp_update_post( $maps_marker_pro_provider ); + } + } + /** * Register default embed providers. */ @@ -906,9 +951,9 @@ public function register_default_embed_providers() { 'regex_default' => '', ], /* translators: embed provider */ - 'post_content' => \sprintf( \__( 'Click here to display content from %s.', 'embed-privacy' ), \_x( 'Maps Marker', 'embed provider', 'embed-privacy' ) ), + 'post_content' => \sprintf( \__( 'Click here to display content from %s.', 'embed-privacy' ), \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ) ), 'post_status' => 'publish', - 'post_title' => \_x( 'Maps Marker', 'embed provider', 'embed-privacy' ), + 'post_title' => \_x( 'Maps Marker Pro', 'embed provider', 'embed-privacy' ), 'post_type' => 'epi_embed', ], [ diff --git a/inc/data/class-replacer.php b/inc/data/class-replacer.php index 8765cd2..0824f78 100644 --- a/inc/data/class-replacer.php +++ b/inc/data/class-replacer.php @@ -195,7 +195,7 @@ public static function replace_oembed( $output, $url, array $attributes ) { return X::get_local_tweet( $output ); } - $output = $replacement->get( $attributes ); + $output = $replacement->get( $attributes, $provider ); if ( $provider->is( 'youtube' ) ) { // replace youtube.com with youtube-nocookie.com diff --git a/inc/embed/class-replacement.php b/inc/embed/class-replacement.php index d4ac172..c32a555 100644 --- a/inc/embed/class-replacement.php +++ b/inc/embed/class-replacement.php @@ -51,10 +51,11 @@ public function __construct( $content, $url = '' ) { /** * Get the content with an overlay. * - * @param array $attributes Embed attributes + * @param array $attributes Embed attributes + * @param \epiphyt\Embed_Privacy\embed\Provider|null $provider Embed provider * @return string Content with embeds replaced by an overlay */ - public function get( array $attributes = [] ) { + public function get( array $attributes = [], $provider = null ) { /** * Filter the content after it has been replaced with an overlay. * @@ -87,14 +88,14 @@ public function get( array $attributes = [] ) { ) { $attributes['check_always_active'] = true; - foreach ( $this->get_providers() as $provider ) { + if ( $provider instanceof Provider ) { $this->provider = $provider; - $new_content = $this->replace_content( $content, $attributes ); - - if ( $new_content !== $content ) { - Embed_Privacy::get_instance()->has_embed = true; - Embed_Privacy::get_instance()->frontend->print_assets(); - $content = $new_content; + $content = $this->replace( $content, $attributes ); + } + else { + foreach ( $this->get_providers() as $provider ) { + $this->provider = $provider; + $content = $this->replace( $content, $attributes ); } } @@ -157,6 +158,25 @@ public function get_providers() { return $this->providers; } + /** + * Replace content with an overlay and print assets. + * + * @param string $content Content to replace embeds in + * @param array $attributes Additional attributes + * @return string Replaced content + */ + private function replace( $content, array $attributes ) { + $new_content = $this->replace_content( $content, $attributes ); + + if ( $new_content !== $content ) { + Embed_Privacy::get_instance()->has_embed = true; + Embed_Privacy::get_instance()->frontend->print_assets(); + $content = $new_content; + } + + return $content; + } + /** * Replace embedded content with an overlay. * @@ -164,7 +184,7 @@ public function get_providers() { * @param array $attributes Additional attributes * @return string Updated content */ - private function replace_content( $content, $attributes ) { + private function replace_content( $content, array $attributes ) { if ( empty( $content ) ) { return $content; } @@ -433,27 +453,13 @@ private function set_provider( $content, $url = '' ) { $content, Replacer::extend_pattern( $provider->get_pattern(), $provider ) ) - && ( ! empty( $url ) && ! $provider->is_matching( $url ) ) + && ( empty( $url ) || ! $provider->is_matching( $url ) ) ) { continue; } $current_provider = $provider; - // support unknown oEmbed provider - // see https://github.com/epiphyt/embed-privacy/issues/89 - if ( $current_provider === null && ! empty( $url ) ) { - $parsed_url = \wp_parse_url( $url ); - $provider = isset( $parsed_url['host'] ) ? $parsed_url['host'] : ''; - $current_provider = new Provider(); - $current_provider->set_name( $provider ); - $current_provider->set_title( $provider ); - } - - if ( $current_provider === null ) { - $current_provider = new Provider(); - } - /** * Filter the overlay provider. * @@ -465,5 +471,25 @@ private function set_provider( $content, $url = '' ) { */ $this->providers[] = \apply_filters( 'embed_privacy_overlay_provider', $current_provider, $content, $url ); } + + // support unknown oEmbed provider + // see https://github.com/epiphyt/embed-privacy/issues/89 + if ( $current_provider === null && ! empty( $url ) ) { + $parsed_url = \wp_parse_url( $url ); + $provider = isset( $parsed_url['host'] ) ? $parsed_url['host'] : ''; + $current_provider = new Provider(); + $current_provider->set_name( $provider ); + $current_provider->set_title( $provider ); + } + + // unknown embeds + if ( $current_provider === null ) { + $current_provider = new Provider(); + } + + /** + * This filter is documented in inc/embed/class-replacement.php. + */ + $this->providers[] = \apply_filters( 'embed_privacy_overlay_provider', $current_provider, $content, $url ); } } diff --git a/inc/integration/class-maps-marker.php b/inc/integration/class-maps-marker.php index 8ee81b4..6d30c2d 100644 --- a/inc/integration/class-maps-marker.php +++ b/inc/integration/class-maps-marker.php @@ -2,8 +2,8 @@ namespace epiphyt\Embed_Privacy\integration; use DOMDocument; +use epiphyt\Embed_Privacy\data\Providers; use epiphyt\Embed_Privacy\data\Replacer; -use epiphyt\Embed_Privacy\embed\Provider; use epiphyt\Embed_Privacy\Embed_Privacy; /** @@ -94,14 +94,8 @@ public static function replace( $output, $tag ) { * @return \epiphyt\Embed_Privacy\embed\Provider|null Updated provider */ public static function set_provider( $provider, $content ) { - if ( - ! $provider - && ( \str_contains( $content, 'maps-marker-pro' ) || \str_contains( $content, '[mapsmarker' ) ) - ) { - $provider = new Provider(); - $provider->set_name( 'maps-marker-pro' ); - $provider->set_pattern( '/maps-marker-pro|^\[mapsmarker/' ); - $provider->set_title( \__( 'Maps Marker Pro', 'embed-privacy' ) ); + if ( \str_contains( $content, 'maps-marker-pro' ) || \str_contains( $content, '[mapsmarker' ) ) { + $provider = Providers::get_instance()->get_by_name( 'maps-marker-pro' ); } return $provider; diff --git a/readme.txt b/readme.txt index cf6436c..d45d567 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: epiphyt, kittmedia, krafit Tags: oembed, privacy, gutenberg, iframes, performance Requires at least: 5.9 -Stable tag: 1.10.5 +Stable tag: 1.10.6 Tested up to: 6.6 Requires PHP: 5.6 License: GPL2 @@ -145,6 +145,10 @@ You can report security bugs through the Patchstack Vulnerability Disclosure Pro == Changelog == += 1.10.6 = +* Fixed: Detection for unknown embeds +* Fixed: Detection for Maps Marker Pro + = 1.10.5 = * Improved: Renamed Twitter to X * Fixed: Check for matching provider diff --git a/uninstall.php b/uninstall.php index fb44ab3..3a00a2d 100644 --- a/uninstall.php +++ b/uninstall.php @@ -1,9 +1,8 @@ $meta_value ) { + foreach ( \array_keys( $metadata ) as $meta_key ) { if ( ! \str_contains( $meta_key, 'embed_privacy_thumbnail_' ) ) { continue; } @@ -119,7 +118,7 @@ function delete_data() { // delete thumbnail directory delete_directory( Thumbnail::get_directory()['base_dir'] ); // delete old thumbnail directory - delete_directory( WP_CONTENT_DIR . '/uploads/embed-privacy' ); + delete_directory( \WP_CONTENT_DIR . '/uploads/embed-privacy' ); } /** @@ -134,17 +133,7 @@ function delete_directory( $directory ) { return; } - $iterator = new RecursiveDirectoryIterator( $directory, RecursiveDirectoryIterator::SKIP_DOTS ); - $files = new RecursiveIteratorIterator( $iterator, RecursiveIteratorIterator::CHILD_FIRST ); + require_once __DIR__ . '/inc/class-embed-privacy.php'; - foreach ( $files as $file ) { - if ( $file->isDir() ) { - \rmdir( $file->getRealPath() ); - } - else { - \unlink( $file->getRealPath() ); - } - } - - \rmdir( $directory ); + Embed_Privacy::get_wp_filesystem()->rmdir( $directory, true ); }