WordPress.org

Make WordPress Core

Ticket #17491: is_email_new.patch

File is_email_new.patch, 8.1 KB (added by arena, 6 months ago)

is_email_new.patch

  • formatting.php

     
    32423242}
    32433243
    32443244/**
    3245  * Verifies that an email is valid.
    3246  *
    3247  * Does not grok i18n domains. Not RFC compliant.
    3248  *
    3249  * @since 0.71
    3250  *
    3251  * @param string $email      Email address to verify.
    3252  * @param bool   $deprecated Deprecated.
    3253  * @return string|bool Either false or the valid email address.
    3254  */
     3245* Verifies that an email is valid.
     3246*
     3247* @since 0.71
     3248*
     3249* @param string $email      Email address to verify.
     3250* @param bool   $deprecated Deprecated.
     3251* @return string|bool Either false or the valid email address.
     3252*/
    32553253function is_email( $email, $deprecated = false ) {
    32563254        if ( ! empty( $deprecated ) ) {
    32573255                _deprecated_argument( __FUNCTION__, '3.0.0' );
    32583256        }
    32593257
    3260         // Test for the minimum length the email can be
    3261         if ( strlen( $email ) < 6 ) {
    3262                 /**
    3263                  * Filters whether an email address is valid.
    3264                  *
    3265                  * This filter is evaluated under several different contexts, such as 'email_too_short',
    3266                  * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits',
    3267                  * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context.
    3268                  *
    3269                  * @since 2.8.0
    3270                  *
    3271                  * @param bool   $is_email Whether the email address has passed the is_email() checks. Default false.
    3272                  * @param string $email    The email address being checked.
    3273                  * @param string $context  Context under which the email was tested.
    3274                  */
    3275                 return apply_filters( 'is_email', false, $email, 'email_too_short' );
     3258        switch( true ) {
     3259                case ( !is_email_basics( $email ) ) :
     3260                        return apply_filters( 'is_email', false, $email );
     3261                break;
     3262                case ( is_email_rfc822(  $email ) ) :
     3263                break;
     3264                case ( is_email_rfc2822( $email ) ) :
     3265                break;
     3266                default :
     3267                        return apply_filters( 'is_email', false, $email );
     3268                break;
    32763269        }
     3270        return $email;
     3271}
    32773272
    3278         // Test for an @ character after the first position
    3279         if ( strpos( $email, '@', 1 ) === false ) {
    3280                 /** This filter is documented in wp-includes/formatting.php */
    3281                 return apply_filters( 'is_email', false, $email, 'email_no_at' );
    3282         }
     3273/**
     3274* Verifies that email fits with basics.
     3275*
     3276*     the format of an email address is : local-part@domain-part
     3277*         the local  part may be up to 64 characters long and the domain may have a maximum of 255 characters.
     3278*         the domain part is a list of dot-separated DNS labels, each label being limited to a length of 63 characters
     3279*
     3280* @param string $email
     3281*/
     3282function is_email_basics( $email ) {
     3283        $parts = explode( '@', $email );
    32833284
    3284         // Split out the local and domain parts
    3285         list( $local, $domain ) = explode( '@', $email, 2 );
     3285        $domain_part = array_pop( $parts );
     3286        if ( is_numeric( $domain_part )   ) return false;
     3287        if ( strlen( $domain_part ) > 255 ) return false;
    32863288
    3287         // LOCAL PART
    3288         // Test for invalid characters
    3289         if ( ! preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) {
    3290                 /** This filter is documented in wp-includes/formatting.php */
    3291                 return apply_filters( 'is_email', false, $email, 'local_invalid_chars' );
    3292         }
     3289        $local_part  = implode( '@', $parts );
     3290        if ( strlen( $local_part ) > 64 ) return false;
    32933291
    3294         // DOMAIN PART
    3295         // Test for sequences of periods
    3296         if ( preg_match( '/\.{2,}/', $domain ) ) {
    3297                 /** This filter is documented in wp-includes/formatting.php */
    3298                 return apply_filters( 'is_email', false, $email, 'domain_period_sequence' );
     3292        $dots = explode( '.', $domain_part );
     3293        foreach( $dots as $dot ) {
     3294                if ( strlen( $dot ) > 63 ) return false;
    32993295        }
     3296        return true;
     3297}
    33003298
    3301         // Test for leading and trailing periods and whitespace
    3302         if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) {
    3303                 /** This filter is documented in wp-includes/formatting.php */
    3304                 return apply_filters( 'is_email', false, $email, 'domain_period_limits' );
    3305         }
     3299/**
     3300*  Validates whether the value is a valid e-mail address.
     3301*       In general, this validates e-mail addresses against the syntax in RFC 822,
     3302*    with the exceptions that comments and whitespace folding and dotless domain names are not supported.
     3303*  [php.net]
     3304*
     3305* @param string $email
     3306*/
     3307function is_email_rfc822( $email ) {
    33063308
    3307         // Split the domain into subs
    3308         $subs = explode( '.', $domain );
     3309        if ( ! defined( 'FILTER_VALIDATE_EMAIL' ) ) return false;
     3310        if ( ! function_exists( 'filter_var' ) ) return false;
     3311        return ( filter_var( $email, FILTER_VALIDATE_EMAIL ) );
     3312}
    33093313
    3310         // Assume the domain will have at least two subs
    3311         if ( 2 > count( $subs ) ) {
    3312                 /** This filter is documented in wp-includes/formatting.php */
    3313                 return apply_filters( 'is_email', false, $email, 'domain_no_periods' );
    3314         }
     3314/**
     3315* Defines and applies the grammar to use for validation, implements the RFC 2822 (and friends) ABNF grammar definitions.
     3316* code from swiftmailer v5 https://github.com/swiftmailer/swiftmailer/tree/5.x
     3317*
     3318* @author     Fabien Potencier
     3319* @author     Chris Corbyn
     3320*
     3321* @param string $email
     3322*/
     3323function is_email_rfc2822( $email ) {
     3324        return ( preg_match( '/^' . is_email_rfc2822_grammar() . '$/D', $email ) );
     3325}
    33153326
    3316         // Loop through each sub
    3317         foreach ( $subs as $sub ) {
    3318                 // Test for leading and trailing hyphens and whitespace
    3319                 if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) {
    3320                         /** This filter is documented in wp-includes/formatting.php */
    3321                         return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );
    3322                 }
     3327function is_email_rfc2822_grammar() {
     3328        /*** Refer to RFC 2822 for ABNF grammar ***/
     3329               
     3330        //All basic building blocks
     3331        $g['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]';
     3332        $g['WSP'] = '[ \t]';
     3333        $g['CRLF'] = '(?:\r\n)';
     3334        $g['FWS'] = '(?:(?:' . $g['WSP'] . '*' . $g['CRLF'] . ')?' . $g['WSP'] . ')';
     3335        $g['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]';
     3336        $g['quoted-pair'] = '(?:\\\\' . $g['text'] . ')';
     3337        $g['ctext'] = '(?:' . $g['NO-WS-CTL'] . '|[\x21-\x27\x2A-\x5B\x5D-\x7E])';
     3338        //Uses recursive PCRE (?1) --
     3339        $g['ccontent'] = '(?:' . $g['ctext'] . '|' . $g['quoted-pair'] . '|(?1))';
     3340        $g['comment'] = '(\((?:' . $g['FWS'] . '|' . $g['ccontent']. ')*' . $g['FWS'] . '?\))';
     3341        $g['CFWS'] = '(?:(?:' . $g['FWS'] . '?' . $g['comment'] . ')*(?:(?:' . $g['FWS'] . '?' . $g['comment'] . ')|' . $g['FWS'] . '))';
     3342        $g['qtext'] = '(?:' . $g['NO-WS-CTL'] . '|[\x21\x23-\x5B\x5D-\x7E])';
     3343        $g['qcontent'] = '(?:' . $g['qtext'] . '|' . $g['quoted-pair'] . ')';
     3344        $g['quoted-string'] = '(?:' . $g['CFWS'] . '?"' . '(' . $g['FWS'] . '?' . $g['qcontent'] . ')*' . $g['FWS'] . '?"' . $g['CFWS'] . '?)';
     3345        $g['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]';
     3346        $g['atom'] = '(?:' . $g['CFWS'] . '?' . $g['atext'] . '+' . $g['CFWS'] . '?)';
     3347        $g['dot-atom-text'] = '(?:' . $g['atext'] . '+' . '(\.' . $g['atext'] . '+)*)';
     3348        $g['dot-atom'] = '(?:' . $g['CFWS'] . '?' . $g['dot-atom-text'] . '+' . $g['CFWS'] . '?)';
     3349        $g['word'] = '(?:' . $g['atom'] . '|' . $g['quoted-string'] . ')';
     3350        $g['phrase'] = '(?:' . $g['word'] . '+?)';
     3351        $g['no-fold-quote'] = '(?:"(?:' . $g['qtext'] . '|' . $g['quoted-pair'] . ')*")';
     3352        $g['dtext'] = '(?:' . $g['NO-WS-CTL'] . '|[\x21-\x5A\x5E-\x7E])';
     3353        $g['no-fold-literal'] = '(?:\[(?:' . $g['dtext'] . '|' . $g['quoted-pair'] . ')*\])';
    33233354
    3324                 // Test for invalid characters
    3325                 if ( ! preg_match( '/^[a-z0-9-]+$/i', $sub ) ) {
    3326                         /** This filter is documented in wp-includes/formatting.php */
    3327                         return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' );
    3328                 }
    3329         }
     3355        //Message IDs
     3356        $g['id-left'] = '(?:' . $g['dot-atom-text'] . '|' . $g['no-fold-quote'] . ')';
     3357        $g['id-right'] = '(?:' . $g['dot-atom-text'] . '|' . $g['no-fold-literal'] . ')';
    33303358
    3331         // Congratulations your email made it!
    3332         /** This filter is documented in wp-includes/formatting.php */
    3333         return apply_filters( 'is_email', $email, $email, null );
     3359        //Addresses, mailboxes and paths
     3360        $g['local-part'] = '(?:' . $g['dot-atom'] . '|' . $g['quoted-string'] . ')';
     3361        $g['dcontent'] = '(?:' . $g['dtext'] . '|' . $g['quoted-pair'] . ')';
     3362        $g['domain-literal'] = '(?:' . $g['CFWS'] . '?\[(' . $g['FWS'] . '?' . $g['dcontent'] . ')*?' . $g['FWS'] . '?\]' . $g['CFWS'] . '?)';
     3363        $g['domain'] = '(?:' . $g['dot-atom'] . '|' . $g['domain-literal'] . ')';
     3364
     3365        return '(?:' . $g['local-part'] . '@' . $g['domain'] . ')';
    33343366}
    33353367
    33363368/**