Making WordPress.org

Changeset 14602


Ignore:
Timestamp:
11/12/2025 04:43:43 AM (19 hours ago)
Author:
dd32
Message:

Registration: Store a sanitised version of the email (no plus addressing) to ease searches for accounts by email address.

Location:
sites/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/api.wordpress.org/public_html/dotorg/helpscout/profile.php

    r14599 r14602  
    66include __DIR__ . '/common.php';
    77
     8// Include the registration functions.. wporg_sanitize_email_for_search().
     9include_once WP_CONTENT_DIR . '/themes/pub/wporg-login/functions-registration.php';
     10
    811// $request is the validated HelpScout request.
    912$request = get_request();
     
    1215$html = '';
    1316$user = false;
     17
    1418$email = get_user_email_for_email( $request );
    1519
     
    3842    }
    3943
    40     $gmail_dotless = $request->customer->email;
    41     if ( str_ends_with( strtolower( $gmail_dotless ), '@gmail.com' ) ) {
    42         $gmail_dotless = str_replace( '.', '', strstr( $gmail_dotless, '@', true ) ) . '@gmail.com';
    43     }
    44 
    4544    // See if they have a pending user account.
    4645    $records = $wpdb->get_results( $wpdb->prepare(
    47         "SELECT * FROM {$wpdb->base_prefix}user_pending_registrations
    48         WHERE user_email = %s OR user_email = %s OR user_email LIKE %s",
     46        "SELECT * FROM %i
     47        WHERE ( user_email = %s OR user_email_san = %s OR user_email = %s OR user_email_san = %s )",
     48        "{$wpdb->base_prefix}user_pending_registrations",
    4949        $request->customer->email,
    50         $gmail_dotless,
    51         str_replace( '@', '+%@', $wpdb->esc_like( $request->customer->email ) ) // Handle plus addressing.
     50        wporg_sanitize_email_for_search( $request->customer->email ),
     51        $email,
     52        wporg_sanitize_email_for_search( $email )
    5253    ) );
    5354    if ( $records ) {
     
    117118
    118119// response to HS is just HTML to display in the sidebar
     120header( 'Content-Type: application/json; charset=utf-8' );
    119121echo json_encode( array( 'html' => $html ) );
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/admin/class-user-registrations-list-table.php

    r14533 r14602  
    181181            $search_term = wp_unslash( $_GET['s'] );
    182182            $search_like = '%' . $wpdb->esc_like( $search_term ) . '%';
    183 
     183           
    184184            // Limit searches to where they're likely, for performance.
    185185            if ( str_contains( $search_term, '@' ) ) {
     186                $san_search_term = wporg_sanitize_email_for_search( $search_term );
     187                $san_search_like = '%' . $wpdb->esc_like( $san_search_term ) . '%';
     188
    186189                // If it looks like a full email, exact match.
    187190                if ( preg_match( '/^.{3,}@.+[.].+$/', $search_term ) ) {
    188191                    // Looks like an email, so just search the emails.
    189192                    $where .= $wpdb->prepare(
    190                         "AND registrations.user_email = %s",
    191                         $search_term
     193                        "AND ( registrations.user_email = %s OR registrations.user_email_san = %s )",
     194                        $search_term,
     195                        $san_search_term
    192196                    );
    193197                } else {
    194198                    // Otherwise, a wildcard on the email.
    195199                    $where .= $wpdb->prepare(
    196                         "AND registrations.user_email LIKE %s",
    197                         $search_like
     200                        "AND ( registrations.user_email LIKE %s OR registrations.user_email_san LIKE %s )",
     201                        $search_like,
     202                        $san_search_like
    198203                    );
    199204                }
     
    216221                        registrations.user_login LIKE %s OR
    217222                        registrations.user_email LIKE %s OR
     223                        registrations.user_email_san LIKE %s OR
    218224                        registrations.meta LIKE %s OR
    219225                        description.meta_value LIKE %s
    220226                    )",
    221                     $search_like, $search_like, $search_like, $search_like
     227                    $search_like, $search_like, $search_like, $search_like, $search_like
    222228                );
    223229            }
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/functions-registration.php

    r14597 r14602  
    260260    ), ARRAY_A );
    261261
     262    // Try again on the sanitized field..
     263    if ( ! $pending_user && 'user_email' === $field ) {
     264        $who          = wporg_sanitize_email_for_search( $who );
     265        $pending_user = $wpdb->get_row( $wpdb->prepare(
     266            'SELECT * FROM %i WHERE user_email_san = %s LIMIT 1',
     267            "{$wpdb->base_prefix}user_pending_registrations",
     268            $who
     269        ), ARRAY_A );
     270    }
     271
    262272    if ( ! $pending_user ) {
    263273        return false;
     
    276286
    277287/**
    278  * Fetches a pending user record from the database by "inbox", ignoring plus addressing.
    279  */
    280 function wporg_get_pending_user_by_email_wildcard( $email ) {
    281     global $wpdb;
    282 
    283     $email_wildcard = preg_replace( '/[+][^@]+@/i', '+%@', $wpdb->esc_like( $email ) );  // abc+def@ghi => abc+%@ghi
    284     $email_base     = preg_replace( '/[+][^@]+@/i', '@', $email ); // abc+def@ghi => abc@ghi
    285 
    286     $matching_email = $wpdb->get_var( $sql = $wpdb->prepare(
    287         'SELECT `user_email` FROM %i WHERE ( `user_email` = %s OR `user_email` LIKE %s ) LIMIT 1',
    288         "{$wpdb->base_prefix}user_pending_registrations",
    289         $email_base,
    290         $email_wildcard
    291     ) );
    292 
    293     if ( $matching_email ) {
    294         return wporg_get_pending_user( $matching_email );
    295     }
    296 
    297     // If gmail, check to see if there's a match ignoring dots and plus addressing.
    298     if ( str_ends_with( strtolower( $email ), '@gmail.com' ) && substr_count( $email, '.' ) > 1 ) {
    299         $gmail_base = str_replace( '.', '', explode( '@', $email )[0] );
    300         $gmail_base = preg_replace( '/[+].*$/', '', $gmail_base );
    301 
    302         $matching_email = $wpdb->get_var( $sql = $wpdb->prepare(
    303             'SELECT `user_email` FROM %i WHERE `user_email` = %s LIMIT 1',
    304             "{$wpdb->base_prefix}user_pending_registrations",
    305             $gmail_base . '@gmail.com'
    306         ) );
    307 
    308         if ( $matching_email ) {
    309             return wporg_get_pending_user( $matching_email );
    310         }
    311     }
    312 
    313     return false;
    314 }
    315 
    316 /**
    317288 * Update the pending user record, similar to `wp_update_user()` but for the not-yet-created user record.
    318289 */
    319290function wporg_update_pending_user( $pending_user ) {
    320291    global $wpdb;
     292
     293    // Ensure we have the sanitized email for searching purposes.
     294    if ( empty( $pending_user['user_email_san'] ) && ! empty( $pending_user['user_email'] ) ) {
     295        $pending_user['user_email_san'] = wporg_sanitize_email_for_search( $pending_user['user_email'] );
     296    }
    321297
    322298    // Allow altering the user fields.
     
    604580    return false;
    605581}
     582
     583/**
     584 * Sanitize an email into it's canonical form for searching.
     585 *
     586 * @param string $email The email address to sanitize.
     587 * @return string The sanitized email address.
     588 */
     589function wporg_sanitize_email_for_search( $email ) {
     590    $email_san = strtolower( $email );
     591    $email_san = trim( $email_san );
     592
     593    // Remove plus addressing for the sanitized email.
     594    $email_san = preg_replace( '/[+][^@]+@/i', '@', $email_san );
     595
     596    // Filter it when needed.
     597    $email_san = apply_filters( 'wporg_sanitize_email_for_search', $email_san, $email );
     598
     599    return $email_san;
     600}
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/functions-restapi.php

    r14113 r14602  
    114114    // Check we don't have a pending registration for that email.
    115115    $pending = wporg_get_pending_user( $email );
    116 
    117     // And that there's no pending account signups for other emails for that inbox.
    118     if ( ! $pending && str_contains( $email, '+' ) ) {
    119         $pending = wporg_get_pending_user_by_email_wildcard( $email );
    120     }
    121116
    122117    if ( $pending && ! $pending['created'] && ! $pending['cleared'] ) {
Note: See TracChangeset for help on using the changeset viewer.