Skip to content

Commit

Permalink
Merge pull request #930 from Codeinwp/fix/image_import_non_ascii
Browse files Browse the repository at this point in the history
Fix/image import non ascii
  • Loading branch information
vytisbulkevicius authored May 30, 2024
2 parents 958e2b2 + 0f8d13c commit 8355268
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ cypress/videos/*
cypress/screenshots/*
cypress/integration/localhost*
cypress/fixtures
cypress.env.json
cypress.env.json
.phpunit.result.cache
55 changes: 53 additions & 2 deletions includes/admin/feedzy-rss-feeds-import.php
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,55 @@ private function get_file_type_by_url( $url ) {
return $content_type;
}

/**
* Will escape the provided URL and convert it to ASCII.
*
* @param string $url The URL to convert.
*
* @return string
*/
private function convert_url_to_ascii( $url ) {
$parts = wp_parse_url( $url );
if ( empty( $parts ) ) {
return esc_url( $url );
}

$scheme = '';
if ( isset( $parts['scheme'] ) ) {
$scheme = $parts['scheme'] . '://';
}

$host = '';
if ( isset( $parts['scheme'] ) ) {
$host = idn_to_ascii( $parts['host'], IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46 );
}

$url = $scheme . $host;
if ( isset( $parts['port'] ) ) {
$url .= ':' . $parts['port'];
}
if ( isset( $parts['path'] ) ) {
$ascii_path = '';
$path = $parts['path'];
$len = strlen( $path );
for ( $i = 0; $i < $len; $i++ ) {
if ( preg_match( '/^[A-Za-z0-9\/?=+%_.~-]$/', $path[ $i ] ) ) {
$ascii_path .= $path[ $i ];
} else {
$ascii_path .= rawurlencode( $path[ $i ] );
}
}
$url .= $ascii_path;
}
if ( isset( $parts['query'] ) ) {
$url .= '?' . $parts['query'];
}
if ( isset( $parts['fragment'] ) ) {
$url .= '#' . $parts['fragment'];
}
return esc_url( $url );
}

/**
* Downloads and sets a post featured image if possible.
*
Expand All @@ -2029,8 +2078,10 @@ private function try_save_featured_image( $img_source_url, $post_id, $post_title

if ( ! $id ) {

// We escape the URL to ensure that valid URLs are passed by the filter.
if ( filter_var( esc_url( $img_source_url ), FILTER_VALIDATE_URL ) === false ) {
// We escape the URL to ensure that valid URLs are passed by the filter. We also convert the URL parts to ASCII.
// This is necessary because FILTER_VALIDATE_URL only validates against ASCII URLs.
$escaped_url = $this->convert_url_to_ascii( $img_source_url );
if ( filter_var( $escaped_url, FILTER_VALIDATE_URL ) === false ) {
$import_errors[] = 'Invalid Featured Image URL: ' . $img_source_url;
return false;
}
Expand Down
19 changes: 19 additions & 0 deletions tests/test-image-import.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,23 @@ public function test_image_import_url() {
$this->assertFalse( $response );
$this->assertTrue( empty( $import_errors ) );
}

public function test_import_image_special_characters() {
$feedzy = new Feedzy_Rss_Feeds_Import( 'feedzy-rss-feeds', '1.2.0' );

$reflector = new ReflectionClass( $feedzy );
$try_save_featured_image = $reflector->getMethod( 'try_save_featured_image' );
$try_save_featured_image->setAccessible( true );

$import_errors = array();
$import_info = array();

$arguments = array( 'https://example.com/path_to_image/çöp.jpg?itok=ZYU_ihPB', 0, 'Post Title', &$import_errors, &$import_info, array() );
$response = $try_save_featured_image->invokeArgs( $feedzy, $arguments );

// expected response is false because the image does not exist, but the URL is valid so no $import_errors should be set.
$this->assertFalse( $response );
$this->assertTrue( empty( $import_errors ) );

}
}

0 comments on commit 8355268

Please sign in to comment.