WordPress.org

Make WordPress Core

Ticket #21212: 21212.2.diff

File 21212.2.diff, 6.5 KB (added by pento, 5 years ago)
  • src/wp-admin/includes/upgrade.php

     
    513513        if ( $wp_current_db_version < 29630 )
    514514                upgrade_400();
    515515
     516        if ( $wp_current_db_version < 30134 )
     517                upgrade_420();
     518
    516519        maybe_disable_link_manager();
    517520
    518521        maybe_disable_automattic_widgets();
     
    14001403}
    14011404
    14021405/**
     1406 * Execute changes made in WordPress 4.2.0.
     1407 *
     1408 * @since 4.2.0
     1409 */
     1410function upgrade_420() {
     1411        global $wp_current_db_version, $wpdb;
     1412        if ( $wp_current_db_version < 30134 && $wpdb->charset === 'utf8mb4') {
     1413                if ( is_multisite() ) {
     1414                        $tables = $wpdb->tables;
     1415                } else {
     1416                        $tables = array_merge( $wpdb->tables, $wpdb->global_tables );
     1417                }
     1418
     1419                foreach ( $tables as $table ) {
     1420                        $wpdb->query( "ALTER TABLE {$wpdb->$table} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" );
     1421                }
     1422        }
     1423}
     1424
     1425/**
    14031426 * Execute network level changes
    14041427 *
    14051428 * @since 3.0.0
     
    14951518                        update_site_option( 'illegal_names', $illegal_names );
    14961519                }
    14971520        }
     1521
     1522        // 4.2
     1523        if ( $wp_current_db_version < 30134 && $wpdb->charset === 'utf8mb4') {
     1524                $tables = array_merge( $wpdb->ms_global_tables, $wpdb->global_tables );
     1525
     1526                foreach ( $tables as $table ) {
     1527                        $wpdb->query( "ALTER TABLE {$wpdb->$table} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" );
     1528                }
     1529        }
    14981530}
    14991531
    15001532// The functions we use to actually do stuff
  • src/wp-admin/setup-config.php

     
    280280                        case 'DB_HOST'     :
    281281                                $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n";
    282282                                break;
     283                        case 'DB_CHARSET'  :
     284                                if ( 'utf8mb4' === $wpdb->charset || ( ! $wpdb->charset && $wpdb->has_cap( 'utf8mb4' ) ) ) {
     285                                        $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'utf8mb4');\r\n";
     286                                }
     287                                break;
    283288                        case 'AUTH_KEY'         :
    284289                        case 'SECURE_AUTH_KEY'  :
    285290                        case 'LOGGED_IN_KEY'    :
  • src/wp-includes/version.php

     
    1111 *
    1212 * @global int $wp_db_version
    1313 */
    14 $wp_db_version = 30133;
     14$wp_db_version = 30134;
    1515
    1616/**
    1717 * Holds the TinyMCE version
  • src/wp-includes/wp-db.php

     
    624624                        }
    625625                }
    626626
    627                 $this->init_charset();
    628 
    629627                $this->dbuser = $dbuser;
    630628                $this->dbpassword = $dbpassword;
    631629                $this->dbname = $dbname;
     
    727725
    728726                if ( defined( 'DB_CHARSET' ) )
    729727                        $this->charset = DB_CHARSET;
     728
     729                if ( 'utf8' === $this->charset && $this->has_cap( 'utf8mb4' ) ) {
     730                        $this->charset = 'utf8mb4';
     731                }
     732
     733                if ( 'utf8mb4' === $this->charset && ( ! $this->collate || stripos( $this->collate, 'utf8_' ) === 0 ) ) {
     734                        $this->collate = 'utf8mb4_unicode_ci';
     735                }
    730736        }
    731737
    732738        /**
     
    14771483                        return false;
    14781484                } elseif ( $this->dbh ) {
    14791485                        $this->has_connected = true;
     1486
     1487                        $this->init_charset();
    14801488                        $this->set_charset( $this->dbh );
     1489
    14811490                        $this->ready = true;
    14821491                        $this->set_sql_mode();
    14831492                        $this->select( $this->dbname, $this->dbh );
     
    23562365                        'gb2312'  => 'EUC-CN',
    23572366                        'ujis'    => 'EUC-JP',
    23582367                        'utf32'   => 'UTF-32',
    2359                         'utf8mb4' => 'UTF-8',
    23602368                );
    23612369
    23622370                $supported_charsets = array();
     
    23912399                                }
    23922400                        }
    23932401
    2394                         // utf8(mb3) can be handled by regex, which is a bunch faster than a DB lookup.
    2395                         if ( 'utf8' === $charset || 'utf8mb3' === $charset ) {
     2402                        // utf8 can be handled by regex, which is a bunch faster than a DB lookup.
     2403                        if ( 'utf8' === $charset || 'utf8mb3' === $charset || 'utf8mb4' === $charset ) {
    23962404                                $regex = '/
    23972405                                        (
    23982406                                                (?: [\x00-\x7F]                  # single-byte sequences   0xxxxxxx
     
    24002408                                                |   \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
    24012409                                                |   [\xE1-\xEC][\x80-\xBF]{2}
    24022410                                                |   \xED[\x80-\x9F][\x80-\xBF]
    2403                                                 |   [\xEE-\xEF][\x80-\xBF]{2}
    2404                                                 ){1,50}                          # ...one or more times
     2411                                                |   [\xEE-\xEF][\x80-\xBF]{2}';
     2412
     2413                                if ( 'utf8mb4' === $charset) {
     2414                                        $regex .= '
     2415                                                |    \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
     2416                                                |    [\xF1-\xF3][\x80-\xBF]{3}
     2417                                                |    \xF4[\x80-\x8F][\x80-\xBF]{2}
     2418                                        ';
     2419                                }
     2420
     2421                                $regex .= '){1,50}                          # ...one or more times
    24052422                                        )
    24062423                                        | .                                  # anything else
    24072424                                        /x';
     
    25262543                        return $charset;
    25272544                }
    25282545
     2546                if ( $this->posts === $table && 'post_content' === $column && 'utf8' === $charset && function_exists( 'mb_convert_encoding' ) ) {
     2547                        $regex = '/([\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3})/';
     2548                        $matches = array();
     2549                        if ( preg_match_all( $regex, $value, $matches ) ) {
     2550                                error_log( print_r( $matches, true ) );
     2551                                if ( ! empty( $matches[1] ) ) {
     2552                                        foreach( $matches[1] as $emoji ) {
     2553                                                $unpacked = unpack( 'H*', mb_convert_encoding( $emoji, 'UTF-32', 'UTF-8' ) );
     2554                                                if ( isset( $unpacked[1] ) ) {
     2555                                                        $entity = '&#x' . trim( $unpacked[1], '0' ) . ';';
     2556                                                        $value = str_replace( $emoji, $entity, $value );
     2557                                                }
     2558                                        }
     2559                                }
     2560                        }
     2561                }
     2562
    25292563                $data = array(
    25302564                        $column => array(
    25312565                                'value'   => $value,
  • tests/phpunit/tests/db/charset.php

     
    130130        }
    131131
    132132        /**
    133          * @ ticket 21212
     133         * @ticket 21212
    134134         */
    135135        function test_process_fields_failure() {
    136136                global $wpdb;
    137                 $data = array( 'post_content' => "H€llo\xf0\x9f\x98\x88World¢" );
     137                // \xf0\xff\xff\xff is invalid in utf8 and utf8mb4
     138                $data = array( 'post_content' => "H€llo\xf0\xff\xff\xffWorld¢" );
    138139                $this->assertFalse( self::$_wpdb->process_fields( $wpdb->posts, $data, null ) );
    139140        }
    140141
     
    436437         */
    437438        function test_invalid_characters_in_query() {
    438439                global $wpdb;
    439                 $this->assertFalse( $wpdb->query( "INSERT INTO {$wpdb->posts} (post_content) VALUES ('foo\xf0\x9f\x98\x88bar')" ) );
     440                $this->assertFalse( $wpdb->query( "INSERT INTO {$wpdb->posts} (post_content) VALUES ('foo\xf0\xff\xff\xffbar')" ) );
    440441        }
    441442}