WordPress.org

Make WordPress Core


Ignore:
Timestamp:
09/28/2017 05:36:34 AM (4 years ago)
Author:
pento
Message:

Database: Add support for connecting to IPv6 hosts

IPv4 addresses are scarce, overworked, and underpaid. They're ready to retire, but we just won't let them go. If you care about their wellbeing, switch to IPv6 today.

Props schlessera, birgire.
Fixes #41722.

File:
1 edited

Legend:

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

    r41628 r41629  
    14611461            $this->dbh = mysqli_init();
    14621462
    1463             // mysqli_real_connect doesn't support the host param including a port or socket
    1464             // like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file.
    1465             $port = null;
    1466             $socket = null;
    1467             $host = $this->dbhost;
    1468             $port_or_socket = strstr( $host, ':' );
    1469             if ( ! empty( $port_or_socket ) ) {
    1470                 $host = substr( $host, 0, strpos( $host, ':' ) );
    1471                 $port_or_socket = substr( $port_or_socket, 1 );
    1472                 if ( 0 !== strpos( $port_or_socket, '/' ) ) {
    1473                     $port = intval( $port_or_socket );
    1474                     $maybe_socket = strstr( $port_or_socket, ':' );
    1475                     if ( ! empty( $maybe_socket ) ) {
    1476                         $socket = substr( $maybe_socket, 1 );
    1477                     }
    1478                 } else {
    1479                     $socket = $port_or_socket;
    1480                 }
     1463            $host    = $this->dbhost;
     1464            $port    = null;
     1465            $socket  = null;
     1466            $is_ipv6 = false;
     1467           
     1468            if ( $host_data = $this->parse_db_host( $this->dbhost ) ) {
     1469                list( $host, $port, $socket, $is_ipv6 ) = $host_data;
     1470            }
     1471
     1472            /*
     1473             * If using the `mysqlnd` library, the IPv6 address needs to be
     1474             * enclosed in square brackets, whereas it doesn't while using the
     1475             * `libmysqlclient` library.
     1476             * @see https://bugs.php.net/bug.php?id=67563
     1477             */
     1478            if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) {
     1479                $host = "[$host]";
    14811480            }
    14821481
     
    14901489                $this->dbh = null;
    14911490
    1492                 /* It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
     1491                /*
     1492                 * It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
    14931493                 *  - We haven't previously connected, and
    14941494                 *  - WP_USE_EXT_MYSQL isn't set to false, and
     
    15681568
    15691569        return false;
     1570    }
     1571
     1572    /**
     1573     * Parse the DB_HOST setting to interpret it for mysqli_real_connect.
     1574     *
     1575     * mysqli_real_connect doesn't support the host param including a port or
     1576     * socket like mysql_connect does. This duplicates how mysql_connect detects
     1577     * a port and/or socket file.
     1578     *
     1579     * @since 4.9.0
     1580     *
     1581     * @param string $host The DB_HOST setting to parse.
     1582     * @return array|bool Array containing the host, the port, the socket and whether
     1583     *                    it is an IPv6 address, in that order. If $host couldn't be parsed,
     1584     *                    returns false.
     1585     */
     1586    public function parse_db_host( $host ) {
     1587        $port    = null;
     1588        $socket  = null;
     1589        $is_ipv6 = false;
     1590
     1591        // We need to check for an IPv6 address first.
     1592        // An IPv6 address will always contain at least two colons.
     1593        if ( substr_count( $host, ':' ) > 1 ) {
     1594            $pattern = '#^(?:\[)?(?<host>[0-9a-fA-F:]+)(?:\]:(?<port>[\d]+))?(?:/(?<socket>.+))?#';
     1595            $is_ipv6 = true;
     1596        } else {
     1597            // We seem to be dealing with an IPv4 address.
     1598            $pattern = '#^(?<host>[^:/]*)(?::(?<port>[\d]+))?(?::(?<socket>.+))?#';
     1599        }
     1600
     1601        $matches = array();
     1602        $result = preg_match( $pattern, $host, $matches );
     1603
     1604        if ( 1 !== $result ) {
     1605            // Couldn't parse the address, bail.
     1606            return false;
     1607        }
     1608
     1609        foreach ( array( 'host', 'port', 'socket' ) as $component ) {
     1610            if ( array_key_exists( $component, $matches ) ) {
     1611                $$component = $matches[$component];
     1612            }
     1613        }
     1614
     1615        return array( $host, $port, $socket, $is_ipv6 );
    15701616    }
    15711617
Note: See TracChangeset for help on using the changeset viewer.