Make WordPress Core

Changeset 33309


Ignore:
Timestamp:
07/17/2015 06:37:40 AM (9 years ago)
Author:
pento
Message:

WPDB: Remove some of the complexities in ::strip_invalid_text() associated with switching character sets between queries. Instead of trying to dynamically change connection character sets, we now rely on the value of ::charset. This also fixes the case where queries were being blocked when DB_CHARSET was utf8, but the column character set was non-utf8.

Merge of [33308] to the 4.2 branch.

Fixes #32165.

Location:
branches/4.2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/4.2/src/wp-includes/wp-db.php

    r33277 r33309  
    26762676            foreach ( $data as $col => $value ) {
    26772677                if ( ! empty( $value['db'] ) ) {
    2678                     if ( ! isset( $queries[ $value['charset'] ] ) ) {
    2679                         $queries[ $value['charset'] ] = array();
    2680                     }
    2681 
    26822678                    // We're going to need to truncate by characters or bytes, depending on the length value we have.
    26832679                    if ( 'byte' === $value['length']['type'] ) {
    2684                         // Split the CONVERT() calls by charset, so we can make sure the connection is right
    2685                         $queries[ $value['charset'] ][ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING binary ), %.0f ) USING {$value['charset']} )", $value['value'], $value['length']['length'] );
     2680                        // Using binary causes LEFT() to truncate by bytes.
     2681                        $charset = 'binary';
    26862682                    } else {
    2687                         $queries[ $value['charset'] ][ $col ] = $this->prepare( "LEFT( CONVERT( %s USING {$value['charset']} ), %.0f )", $value['value'], $value['length']['length'] );
     2683                        $charset = $value['charset'];
    26882684                    }
     2685
     2686                    $queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), %.0f ) USING {$this->charset} )", $value['value'], $value['length']['length'] );
    26892687
    26902688                    unset( $data[ $col ]['db'] );
     
    26922690            }
    26932691
    2694             $connection_charset = $this->charset;
    2695             foreach ( $queries as $charset => $query ) {
     2692            $sql = array();
     2693            foreach ( $queries as $column => $query ) {
    26962694                if ( ! $query ) {
    26972695                    continue;
    26982696                }
    26992697
    2700                 // Change the charset to match the string(s) we're converting
    2701                 if ( $charset !== $connection_charset ) {
    2702                     $connection_charset = $charset;
    2703                     $this->set_charset( $this->dbh, $charset );
    2704                 }
    2705 
    2706                 $this->check_current_query = false;
    2707 
    2708                 $sql = array();
    2709                 foreach ( $query as $column => $column_query ) {
    2710                     $sql[] = $column_query . " AS x_$column";
    2711                 }
    2712 
    2713                 $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
    2714                 if ( ! $row ) {
    2715                     $this->set_charset( $this->dbh, $connection_charset );
    2716                     return new WP_Error( 'wpdb_strip_invalid_text_failure' );
    2717                 }
    2718 
    2719                 foreach ( array_keys( $query ) as $column ) {
    2720                     $data[ $column ]['value'] = $row["x_$column"];
    2721                 }
    2722             }
    2723 
    2724             // Don't forget to change the charset back!
    2725             if ( $connection_charset !== $this->charset ) {
    2726                 $this->set_charset( $this->dbh );
     2698                $sql[] = $query . " AS x_$column";
     2699            }
     2700
     2701            $this->check_current_query = false;
     2702            $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
     2703            if ( ! $row ) {
     2704                return new WP_Error( 'wpdb_strip_invalid_text_failure' );
     2705            }
     2706
     2707            foreach ( array_keys( $data ) as $column ) {
     2708                $data[ $column ]['value'] = $row["x_$column"];
    27272709            }
    27282710        }
  • branches/4.2/tests/phpunit/tests/db/charset.php

    r32377 r33309  
    244244                'expected' => str_repeat( "\xcc\xe3", 5 ),
    245245                'length'   => array( 'type' => 'byte', 'length' => 10 ),
     246            ),
     247            'ujis_with_utf8_connection' => array(
     248                'charset'            => 'ujis',
     249                'connection_charset' => 'utf8',
     250                'value'              => '自動下書き',
     251                'expected'           => '自動下書き',
     252                'length'             => array( 'type' => 'byte', 'length' => 100 ),
     253            ),
     254            'ujis_with_utf8_connection_char_length' => array(
     255                'charset'            => 'ujis',
     256                'connection_charset' => 'utf8',
     257                'value'              => '自動下書き',
     258                'expected'           => '自動下書',
     259                'length'             => array( 'type' => 'char', 'length' => 4 ),
     260            ),
     261            'ujis_with_utf8_connection_byte_length' => array(
     262                'charset'            => 'ujis',
     263                'connection_charset' => 'utf8',
     264                'value'              => '自動下書き',
     265                'expected'           => '自動',
     266                'length'             => array( 'type' => 'byte', 'length' => 6 ),
    246267            ),
    247268            'false' => array(
     
    290311            $expected = $field;
    291312            $expected['value'] = $expected['expected'];
    292             unset( $expected['expected'], $field['expected'] );
     313            unset( $expected['expected'], $field['expected'], $expected['connection_charset'] );
    293314
    294315            // We're keeping track of these for our multiple-field test.
     
    304325        }
    305326
    306         // Time for our test of multiple fields at once.
    307         $data_provider[] = array( $multiple, $multiple_expected, 'multiple fields/charsets' );
    308 
    309327        return $data_provider;
    310328    }
     
    319337        }
    320338
     339        $charset = self::$_wpdb->charset;
     340        if ( isset( $data[0]['connection_charset'] ) ) {
     341            $new_charset = $data[0]['connection_charset'];
     342            unset( $data[0]['connection_charset'] );
     343        } else {
     344            $new_charset = $data[0]['charset'];
     345        }
     346
     347        self::$_wpdb->charset = $new_charset;
     348        self::$_wpdb->set_charset( self::$_wpdb->dbh, $new_charset );
     349
    321350        $actual = self::$_wpdb->strip_invalid_text( $data );
     351
     352        self::$_wpdb->charset = $charset;
     353        self::$_wpdb->set_charset( self::$_wpdb->dbh, $charset );
     354
    322355        $this->assertSame( $expected, $actual, $message );
    323356    }
Note: See TracChangeset for help on using the changeset viewer.