$this->charset = DB_CHARSET;
}
- if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) )
- || ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) ) {
+ if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) || empty( $this->dbh ) ) {
return;
}
public function get_var( $query = null, $x = 0, $y = 0 ) {
$this->func_call = "\$db->get_var(\"$query\", $x, $y)";
- if ( $this->check_safe_collation( $query ) ) {
+ if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
$this->check_current_query = false;
}
public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
- if ( $this->check_safe_collation( $query ) ) {
+ if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
$this->check_current_query = false;
}
* @return array Database query result. Array indexed from 0 by SQL result row number.
*/
public function get_col( $query = null , $x = 0 ) {
- if ( $this->check_safe_collation( $query ) ) {
+ if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
$this->check_current_query = false;
}
public function get_results( $query = null, $output = OBJECT ) {
$this->func_call = "\$db->get_results(\"$query\", $output)";
- if ( $this->check_safe_collation( $query ) ) {
+ if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
$this->check_current_query = false;
}
if ( is_array( $value['length'] ) ) {
$length = $value['length']['length'];
+ $truncate_by_byte_length = 'byte' === $value['length']['type'];
} else {
$length = false;
+ // Since we have no length, we'll never truncate.
+ // Initialize the variable to false. true would take us
+ // through an unnecessary (for this case) codepath below.
+ $truncate_by_byte_length = false;
}
// There's no charset to work with.
continue;
}
- $truncate_by_byte_length = 'byte' === $value['length']['type'];
-
$needs_validation = true;
if (
// latin1 can store any byte sequence
$queries = array();
foreach ( $data as $col => $value ) {
if ( ! empty( $value['db'] ) ) {
- if ( ! isset( $queries[ $value['charset'] ] ) ) {
- $queries[ $value['charset'] ] = array();
- }
-
// We're going to need to truncate by characters or bytes, depending on the length value we have.
if ( 'byte' === $value['length']['type'] ) {
- // Split the CONVERT() calls by charset, so we can make sure the connection is right
- $queries[ $value['charset'] ][ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING binary ), %d ) USING {$value['charset']} )", $value['value'], $value['length']['length'] );
+ // Using binary causes LEFT() to truncate by bytes.
+ $charset = 'binary';
} else {
- $queries[ $value['charset'] ][ $col ] = $this->prepare( "LEFT( CONVERT( %s USING {$value['charset']} ), %d )", $value['value'], $value['length']['length'] );
+ $charset = $value['charset'];
+ }
+
+ if ( is_array( $value['length'] ) ) {
+ $queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), %.0f ) USING {$this->charset} )", $value['value'], $value['length']['length'] );
+ } else if ( 'binary' !== $charset ) {
+ // If we don't have a length, there's no need to convert binary - it will always return the same result.
+ $queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING {$this->charset} )", $value['value'] );
}
unset( $data[ $col ]['db'] );
}
}
- $connection_charset = $this->charset;
- foreach ( $queries as $charset => $query ) {
+ $sql = array();
+ foreach ( $queries as $column => $query ) {
if ( ! $query ) {
continue;
}
- // Change the charset to match the string(s) we're converting
- if ( $charset !== $connection_charset ) {
- $connection_charset = $charset;
- $this->set_charset( $this->dbh, $charset );
- }
-
- $this->check_current_query = false;
-
- $sql = array();
- foreach ( $query as $column => $column_query ) {
- $sql[] = $column_query . " AS x_$column";
- }
+ $sql[] = $query . " AS x_$column";
+ }
- $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
- if ( ! $row ) {
- $this->set_charset( $this->dbh, $connection_charset );
- return new WP_Error( 'wpdb_strip_invalid_text_failure' );
- }
+ $this->check_current_query = false;
+ $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
+ if ( ! $row ) {
+ return new WP_Error( 'wpdb_strip_invalid_text_failure' );
+ }
- foreach ( array_keys( $query ) as $column ) {
+ foreach ( array_keys( $data ) as $column ) {
+ if ( isset( $row["x_$column"] ) ) {
$data[ $column ]['value'] = $row["x_$column"];
}
}
-
- // Don't forget to change the charset back!
- if ( $connection_charset !== $this->charset ) {
- $this->set_charset( $this->dbh );
- }
}
return $data;
// Allow (select...) union [...] style queries. Use the first query's table name.
$query = ltrim( $query, "\r\n\t (" );
- /*
- * Strip everything between parentheses except nested selects and use only 1,000
- * chars of the query.
- */
- $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', substr( $query, 0, 1000 ) );
+ // Strip everything between parentheses except nested selects.
+ $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query );
// Quickly match most common queries.
if ( preg_match( '/^\s*(?:'