Skip to content

Commit bea2bf1

Browse files
committed
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.
Fixes #32165. git-svn-id: https://develop.svn.wordpress.org/trunk@33308 602fd350-edb4-49c9-b593-d223f7449a82
1 parent ce14a75 commit bea2bf1

2 files changed

Lines changed: 52 additions & 37 deletions

File tree

src/wp-includes/wp-db.php

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2710,55 +2710,37 @@ protected function strip_invalid_text( $data ) {
27102710
$queries = array();
27112711
foreach ( $data as $col => $value ) {
27122712
if ( ! empty( $value['db'] ) ) {
2713-
if ( ! isset( $queries[ $value['charset'] ] ) ) {
2714-
$queries[ $value['charset'] ] = array();
2715-
}
2716-
27172713
// We're going to need to truncate by characters or bytes, depending on the length value we have.
27182714
if ( 'byte' === $value['length']['type'] ) {
2719-
// Split the CONVERT() calls by charset, so we can make sure the connection is right
2720-
$queries[ $value['charset'] ][ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING binary ), %.0f ) USING {$value['charset']} )", $value['value'], $value['length']['length'] );
2715+
// Using binary causes LEFT() to truncate by bytes.
2716+
$charset = 'binary';
27212717
} else {
2722-
$queries[ $value['charset'] ][ $col ] = $this->prepare( "LEFT( CONVERT( %s USING {$value['charset']} ), %.0f )", $value['value'], $value['length']['length'] );
2718+
$charset = $value['charset'];
27232719
}
27242720

2721+
$queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), %.0f ) USING {$this->charset} )", $value['value'], $value['length']['length'] );
2722+
27252723
unset( $data[ $col ]['db'] );
27262724
}
27272725
}
27282726

2729-
$connection_charset = $this->charset;
2730-
foreach ( $queries as $charset => $query ) {
2727+
$sql = array();
2728+
foreach ( $queries as $column => $query ) {
27312729
if ( ! $query ) {
27322730
continue;
27332731
}
27342732

2735-
// Change the charset to match the string(s) we're converting
2736-
if ( $charset !== $connection_charset ) {
2737-
$connection_charset = $charset;
2738-
$this->set_charset( $this->dbh, $charset );
2739-
}
2740-
2741-
$this->check_current_query = false;
2742-
2743-
$sql = array();
2744-
foreach ( $query as $column => $column_query ) {
2745-
$sql[] = $column_query . " AS x_$column";
2746-
}
2747-
2748-
$row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
2749-
if ( ! $row ) {
2750-
$this->set_charset( $this->dbh, $connection_charset );
2751-
return new WP_Error( 'wpdb_strip_invalid_text_failure' );
2752-
}
2733+
$sql[] = $query . " AS x_$column";
2734+
}
27532735

2754-
foreach ( array_keys( $query ) as $column ) {
2755-
$data[ $column ]['value'] = $row["x_$column"];
2756-
}
2736+
$this->check_current_query = false;
2737+
$row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
2738+
if ( ! $row ) {
2739+
return new WP_Error( 'wpdb_strip_invalid_text_failure' );
27572740
}
27582741

2759-
// Don't forget to change the charset back!
2760-
if ( $connection_charset !== $this->charset ) {
2761-
$this->set_charset( $this->dbh );
2742+
foreach ( array_keys( $data ) as $column ) {
2743+
$data[ $column ]['value'] = $row["x_$column"];
27622744
}
27632745
}
27642746

tests/phpunit/tests/db/charset.php

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,27 @@ function data_strip_invalid_text() {
244244
'expected' => str_repeat( "\xcc\xe3", 5 ),
245245
'length' => array( 'type' => 'byte', 'length' => 10 ),
246246
),
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 ),
267+
),
247268
'false' => array(
248269
// false is a column with no character set (ie, a number column)
249270
'charset' => false,
@@ -289,7 +310,7 @@ function data_strip_invalid_text() {
289310
foreach ( $fields as $test_case => $field ) {
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.
295316
$multiple[] = $field;
@@ -303,9 +324,6 @@ function data_strip_invalid_text() {
303324
$data_provider[] = array( $data, $expected, $test_case );
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
}
311329

@@ -318,7 +336,22 @@ function test_strip_invalid_text( $data, $expected, $message ) {
318336
$this->markTestSkipped( 'This test fails in PHP 5.2 on Windows. See https://core.trac.wordpress.org/ticket/31262' );
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
}
324357

0 commit comments

Comments
 (0)