WordPress.org

Make WordPress Core

Changeset 31614


Ignore:
Timestamp:
03/05/2015 02:38:59 AM (5 years ago)
Author:
boonebgorges
Message:

In wp_get_attachment_url(), convert to HTTPS when possible.

wp_get_attachment_url(), via wp_upload_dir(), uses 'siteurl' to generate
attachment URLs. When a site is SSL-optional on the front end - ie, 'siteurl'
is non-HTTPS, but SSL is available - a number of situations can arise where
non-HTTPS attachment URLs cause browser mixed-content warnings:

a) SSL is forced in the admin and wp_get_attachment_url() is used to generate the <img> tag for an inserted image. In these cases, the post content will contain non-HTTPS. Viewing/editing this post in the Dashboard will result in non-HTTPS images being served in an SSL environment.
b) wp_get_attachment_url() is used in a theme to generate an <img> src attribute on a public page. When viewing that page over SSL, the images will have HTTP URLs.

This changeset switches attachment URLs to HTTPS when it's determined that the
host supports SSL. This happens when 'siteurl' is non-SSL, but the current page
request *is* over SSL, and the host of the current request matches the host of
the URL being generated.

Props joemcgill, boonebgorges.
Fixes #15928.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/post.php

    r31575 r31614  
    49814981    }
    49824982
     4983    /*
     4984     * If currently on SSL, prefer HTTPS URLs when we know they're supported by the domain
     4985     * (which is to say, when they share the domain name of the current SSL page).
     4986     */
     4987    if ( is_ssl() && 'https' !== substr( $url, 0, 5 ) && parse_url( $url, PHP_URL_HOST ) === $_SERVER['HTTP_HOST'] ) {
     4988        $url = set_url_scheme( $url, 'https' );
     4989    }
     4990
    49834991    /**
    49844992     * Filter the attachment URL.
  • trunk/tests/phpunit/tests/post/attachments.php

    r29745 r31614  
    279279    }
    280280
     281    /**
     282     * @ticket 15928
     283     */
     284    public function test_wp_get_attachment_url_should_not_force_https_when_current_page_is_non_ssl_and_siteurl_is_non_ssl() {
     285        $siteurl = get_option( 'siteurl' );
     286        update_option( 'siteurl', set_url_scheme( $siteurl, 'http' ) );
     287
     288        $filename = DIR_TESTDATA . '/images/test-image.jpg';
     289        $contents = file_get_contents( $filename );
     290
     291        $upload = wp_upload_bits( basename( $filename ), null, $contents );
     292        $this->assertTrue( empty( $upload['error'] ) );
     293
     294        // Set attachment ID.
     295        $attachment_id = $this->_make_attachment( $upload );
     296
     297        // Save server data for cleanup.
     298        $is_ssl = is_ssl();
     299        $_SERVER['HTTPS'] = 'off';
     300
     301        $url = wp_get_attachment_url( $attachment_id );
     302        $this->assertSame( set_url_scheme( $url, 'http' ), $url );
     303
     304        // Cleanup.
     305        $_SERVER['HTTPS'] = $is_ssl ? 'on' : 'off';
     306    }
     307
     308    /**
     309     * @ticket 15928
     310     *
     311     * This situation (current request is non-SSL but siteurl is https) should never arise.
     312     */
     313    public function test_wp_get_attachment_url_should_not_force_https_when_current_page_is_non_ssl_and_siteurl_is_ssl() {
     314        $siteurl = get_option( 'siteurl' );
     315        update_option( 'siteurl', set_url_scheme( $siteurl, 'https' ) );
     316
     317        $filename = DIR_TESTDATA . '/images/test-image.jpg';
     318        $contents = file_get_contents( $filename );
     319
     320        $upload = wp_upload_bits( basename( $filename ), null, $contents );
     321        $this->assertTrue( empty( $upload['error'] ) );
     322
     323        // Set attachment ID.
     324        $attachment_id = $this->_make_attachment( $upload );
     325
     326        // Save server data for cleanup.
     327        $is_ssl = is_ssl();
     328        $_SERVER['HTTPS'] = 'off';
     329
     330        $url = wp_get_attachment_url( $attachment_id );
     331        $this->assertSame( set_url_scheme( $url, 'http' ), $url );
     332
     333        // Cleanup.
     334        $_SERVER['HTTPS'] = $is_ssl ? 'on' : 'off';
     335    }
     336
     337    /**
     338     * @ticket 15928
     339     *
     340     * Canonical siteurl is non-SSL, but SSL support is available/optional.
     341     */
     342    public function test_wp_get_attachment_url_should_force_https_with_https_on_same_host_when_siteurl_is_non_ssl_but_ssl_is_available() {
     343        $siteurl = get_option( 'siteurl' );
     344        update_option( 'siteurl', set_url_scheme( $siteurl, 'http' ) );
     345
     346        $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
     347        $contents = file_get_contents( $filename );
     348
     349        $upload = wp_upload_bits( basename( $filename ), null, $contents );
     350        $this->assertTrue( empty( $upload['error'] ) );
     351
     352        // Set attachment ID
     353        $attachment_id = $this->_make_attachment( $upload );
     354
     355        // Save server data for cleanup
     356        $is_ssl = is_ssl();
     357        $http_host = $_SERVER['HTTP_HOST'];
     358
     359        $_SERVER['HTTPS'] = 'on';
     360
     361        // Verify that server host matches the host of wp_upload_dir().
     362        $upload_dir = wp_upload_dir();
     363        $_SERVER['HTTP_HOST'] = parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
     364
     365        // Test that wp_get_attachemt_url returns with https scheme.
     366        $url = wp_get_attachment_url( $attachment_id );
     367        $this->assertSame( set_url_scheme( $url, 'https' ), $url );
     368
     369        // Cleanup.
     370        $_SERVER['HTTPS'] = $is_ssl ? 'on' : 'off';
     371        $_SERVER['HTTP_HOST'] = $http_host;
     372    }
     373
     374    /**
     375     * @ticket 15928
     376     */
     377    public function test_wp_get_attachment_url_with_https_on_same_host_when_siteurl_is_https() {
     378        $siteurl = get_option( 'siteurl' );
     379        update_option( 'siteurl', set_url_scheme( $siteurl, 'https' ) );
     380
     381        $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
     382        $contents = file_get_contents( $filename );
     383
     384        $upload = wp_upload_bits( basename( $filename ), null, $contents );
     385        $this->assertTrue( empty( $upload['error'] ) );
     386
     387        // Set attachment ID.
     388        $attachment_id = $this->_make_attachment( $upload );
     389
     390        // Save server data for cleanup.
     391        $is_ssl = is_ssl();
     392        $http_host = $_SERVER['HTTP_HOST'];
     393
     394        $_SERVER['HTTPS'] = 'on';
     395
     396        // Verify that server host matches the host of wp_upload_dir().
     397        $upload_dir = wp_upload_dir();
     398        $_SERVER['HTTP_HOST'] = parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
     399
     400        // Test that wp_get_attachemt_url returns with https scheme.
     401        $url = wp_get_attachment_url( $attachment_id );
     402        $this->assertSame( set_url_scheme( $url, 'https' ), $url );
     403
     404        // Cleanup.
     405        $_SERVER['HTTPS'] = $is_ssl ? 'on' : 'off';
     406        $_SERVER['HTTP_HOST'] = $http_host;
     407    }
     408
     409    /**
     410    * @ticket 15928
     411    */
     412    public function test_wp_get_attachment_url_should_not_force_https_when_https_is_on_but_url_has_a_different_domain() {
     413        $siteurl = get_option( 'siteurl' );
     414        update_option( 'siteurl', set_url_scheme( $siteurl, 'https' ) );
     415
     416        $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
     417        $contents = file_get_contents( $filename );
     418
     419        $upload = wp_upload_bits( basename( $filename ), null, $contents );
     420        $this->assertTrue( empty( $upload['error'] ) );
     421
     422        // Set attachment ID
     423        $attachment_id = $this->_make_attachment( $upload );
     424
     425        // Save server data for cleanup.
     426        $is_ssl = is_ssl();
     427        $http_host = $_SERVER['HTTP_HOST'];
     428
     429        $_SERVER['HTTPS'] = 'on';
     430
     431        // Set server host to something random.
     432        $_SERVER['HTTP_HOST'] = 'some.otherhostname.com';
     433
     434        $url = wp_get_attachment_url( $attachment_id );
     435        $this->assertSame( set_url_scheme( $url, 'http' ), $url );
     436
     437        // Cleanup.
     438        $_SERVER['HTTPS'] = $is_ssl ? 'on' : 'off';
     439        $_SERVER['HTTP_HOST'] = $http_host;
     440    }
     441
    281442}
Note: See TracChangeset for help on using the changeset viewer.