Making WordPress.org

Changeset 6543


Ignore:
Timestamp:
02/05/2018 07:23:06 PM (9 years ago)
Author:
obenland
Message:

Plugins: Add basic set of plugin checks

Props Ipstenu.
Fixes #2350.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/metabox/class-review-tools.php

    r6287 r6543  
    11<?php
     2/**
     3 * The Plugin Review metabox.
     4 *
     5 * @package WordPressdotorg\Plugin_Directory\Admin\Metabox
     6 */
     7
    28namespace WordPressdotorg\Plugin_Directory\Admin\Metabox;
    39
    … …  
    1016 */
    1117class Review_Tools {
    12         static function display() {
    13                 $post = get_post();
     18        /**
     19         * Contains all flags.
     20         *
     21         * @var array
     22         */
     23        public static $flagged = [
     24                'low'  => [],
     25                'med'  => [],
     26                'high' => [],
     27        ];
     28
     29        /**
     30         * List of commonly abused/misused terms.
     31         *
     32         * @var array
     33         */
     34        public static $reserved_slugs = [
     35                'wordpress',
     36                'woocommerce',
     37                'google',
     38                'youtube',
     39                'twitter',
     40                'facebook',
     41                'yoast',
     42                'jetpack',
     43        ];
     44
     45        /**
     46         * List of restricted plugin slugs.
     47         *
     48         * @var array
     49         */
     50        public static $restricted_slugs = [
     51                // High-value plugin genres due to their popularity, often abused by spammers.
     52                'gallery',
     53                'lightbox',
     54                'sitemap',
     55                'bookmark',
     56                'social',
     57                'cookie',
     58                'slide',
     59                'seo',
     60
     61                // Plugins we generally don't allow.
     62                'autoblog',
     63                'auto-blog',
     64                'booking',
     65                'plugin',
     66                'spinning',
     67                'framework',
     68        ];
     69
     70        /**
     71         * List of suspicious URLs.
     72         *
     73         * @var array
     74         */
     75        public static $weird_urls = [
     76                'blogger',
     77                'blogspot',
     78                'example.com',
     79                'weebly',
     80                'squarespace',
     81                'medium.com',
     82                'yahoo.com',
     83                'mail.com',
     84                'example.org',
     85        ];
     86
     87        /**
     88         * Displays links to plugin assets and automated flags.
     89         */
     90        public static function display() {
     91                $post   = get_post();
     92                $author = get_user_by( 'id', $post->post_author );
     93                $slug   = $post->post_name;
     94
     95                $author_commit = Tools::get_users_write_access_plugins( $author );
     96                // phpcs:ignore WordPress.VIP.RestrictedFunctions.get_posts_get_posts
     97                $author_plugins = get_posts( [
     98                        'author'           => $author->ID,
     99                        'post_type'        => 'plugin',
     100                        'post__not_in'     => [ $post->ID ],
     101                        'suppress_filters' => false,
     102                ] );
    14103
    15104                $zip_files = array();
    … …  
    17106                        $zip_files[ $zip_file->post_date ] = array( wp_get_attachment_url( $zip_file->ID ), $zip_file );
    18107                }
    19                 uksort( $zip_files, function( $a, $b ) {
     108                uksort( $zip_files, function ( $a, $b ) {
    20109                        return strtotime( $a ) < strtotime( $b );
    21110                } );
    22111
    23                 if ( $zip_url = get_post_meta( $post->ID, '_submitted_zip', true ) ) {
     112                $zip_url = get_post_meta( $post->ID, '_submitted_zip', true );
     113                if ( $zip_url ) {
    24114                        // Back-compat only.
    25115                        $zip_files['User provided URL'] = array( $zip_url, null );
    26116                }
    27117
     118                echo '<p><strong>Zip files:</strong></p>';
     119                echo '<ul class="plugin-zip-files">';
    28120                foreach ( $zip_files as $zip_date => $zip ) {
    29121                        list( $zip_url, $zip_file ) = $zip;
    30                         $zip_size                   = ( is_object( $zip_file ) ? size_format( filesize( get_attached_file( $zip_file->ID ) ), 1 ) : __( 'unknown size', 'wporg-plugins' ) );
    31                         printf(
    32                                 '<p>' . __( '<strong>Zip file:</strong> %s', 'wporg-plugins' ) . '</p>',
    33                                 sprintf( '%s <a href="%s">%s</a> (%s)', esc_html( $zip_date ), esc_url( $zip_url ), esc_html( $zip_url ), esc_html( $zip_size ) )
    34                         );
    35                 }
    36 
    37                 if ( 'new' !== $post->post_status && 'pending' !== $post->post_status ) {
    38                         echo "<ul>
    39                                 <li><a href='https://plugins.trac.wordpress.org/log/{$post->post_name}/'>" . __( 'Development Log', 'wporg-plugins' ) . "</a></li>
    40                                 <li><a href='https://plugins.svn.wordpress.org/{$post->post_name}/'>" . __( 'Subversion Repository', 'wporg-plugins' ) . "</a></li>
    41                                 <li><a href='https://plugins.trac.wordpress.org/browser/{$post->post_name}/'>" . __( 'Browse in Trac', 'wporg-plugins' ) . '</a></li>
    42                         </ul>';
    43                 }
    44                 if ( $post->post_excerpt && in_array( $post->post_status, array( 'new', 'pending', 'approved' ) ) ) {
    45                         echo '<p>' . strip_tags( $post->post_excerpt ) . '</p>';
    46                 }
    47 
    48                 add_filter( 'wp_comment_reply', function( $string ) use ( $post ) {
    49                         $author = get_user_by( 'id', $post->post_author );
    50 
     122                        $zip_size                   = is_object( $zip_file ) ? size_format( filesize( get_attached_file( $zip_file->ID ) ), 1 ) : 'unknown size';
     123
     124                        printf( '<li>%s <a href="%s">%s</a> (%s)</li>', esc_html( $zip_date ), esc_url( $zip_url ), esc_html( $zip_url ), esc_html( $zip_size ) );
     125                }
     126                echo '</ul>';
     127
     128                if ( in_array( $post->post_status, [ 'draft', 'pending' ], true ) ) {
     129                        $slug_restricted = [];
     130                        $slug_reserved   = [];
     131
     132                        // String length checks.
     133                        if ( strlen( $slug ) < 5 ) {
     134                                array_push( self::$flagged['med'], 'slug is less than 5 characters' );
     135                        }
     136                        if ( strlen( $slug ) > 50 ) {
     137                                array_push( self::$flagged['med'], 'slug is more than 50 characters' );
     138                        }
     139
     140                        // Check if any term in the restricted/reserved is in the plugin slug.
     141                        $slug_string = str_replace( '-', ' ', $slug );
     142
     143                        foreach ( self::$restricted_slugs as $bad_slug ) {
     144                                if ( false !== stristr( $slug_string, $bad_slug ) ) {
     145                                        array_push( $slug_restricted, $bad_slug );
     146                                }
     147                        }
     148                        foreach ( self::$reserved_slugs as $bad_slug ) {
     149                                if ( false !== stristr( $slug_string, $bad_slug ) ) {
     150                                        array_push( $slug_reserved, $bad_slug );
     151                                }
     152                        }
     153                        if ( ! empty( $slug_restricted ) ) {
     154                                array_push( self::$flagged['med'], 'plugin slug contains restricted term(s): ' . implode( ', ', $slug_restricted ) );
     155                        }
     156                        if ( ! empty( $slug_reserved ) ) {
     157                                array_push( self::$flagged['high'], 'plugin slug contains reserved term(s): ' . implode( ', ', $slug_reserved ) );
     158                        }
     159
     160                        // Check slug usage.
     161                        $plugin_api_usage = intval( get_post_meta( $post->ID, 'active_installs', true ) );
     162                        if ( $plugin_api_usage >= '5000' ) {
     163                                array_push( self::$flagged['high'], 'slug used by more than 5000 users' );
     164                        } elseif ( $plugin_api_usage >= '1000' ) {
     165                                array_push( self::$flagged['med'], 'slug used by 1000-5000 users' );
     166                        } elseif ( $plugin_api_usage >= '500' ) {
     167                                array_push( self::$flagged['low'], 'slug used by 500-1000 users' );
     168                        }
     169
     170                        // User account was registered less than 2 weeks ago (but longer than 3 days) (user is still fairly new).
     171                        $two_weeks_ago  = time() - ( 2 * WEEK_IN_SECONDS );
     172                        $three_days_ago = time() - ( 3 * DAY_IN_SECONDS );
     173                        if ( strtotime( $author->user_registered ) > $two_weeks_ago && strtotime( $author->user_registered ) < $three_days_ago ) {
     174                                array_push( self::$flagged['low'], 'account registered less than 2 weeks ago' );
     175                        }
     176                        if ( strtotime( $author->user_registered ) > $three_days_ago ) {
     177                                array_push( self::$flagged['low'], 'account registered less than 3 days ago' );
     178                        }
     179
     180                        // Username ends in numbers.
     181                        if ( is_numeric( substr( $author->user_login, - 1, 1 ) ) ) {
     182                                array_push( self::$flagged['low'], 'username ends in numbers' );
     183                        }
     184
     185                        // User has no URL.
     186                        if ( empty( $author->user_url ) ) {
     187                                array_push( self::$flagged['low'], 'account has no URL' );
     188                        }
     189
     190                        foreach ( self::$weird_urls as $url ) {
     191                                if ( false !== stripos( $author->user_url, $url ) ) {
     192                                        array_push( self::$flagged['med'], 'account URL contains ' . $url );
     193                                }
     194                                if ( false !== stripos( $author->user_email, $url ) ) {
     195                                        array_push( self::$flagged['med'], 'account email contains ' . $url );
     196                                }
     197                        }
     198
     199                        // Reserved slugs are also often abused domain names (trademark law sucks).
     200                        foreach ( self::$reserved_slugs as $url ) {
     201                                if ( false !== stripos( $author->user_url, $url ) ) {
     202                                        array_push( self::$flagged['high'], 'account URL contains ' . $url );
     203                                }
     204                                if ( false !== stripos( $author->user_email, $url ) ) {
     205                                        array_push( self::$flagged['med'], 'account email contains ' . $url );
     206                                }
     207                        }
     208
     209                        // User Behavior.
     210                        // If FORUM ROLE is blocked.
     211                        if ( defined( 'WPORG_SUPPORT_FORUMS_BLOGID' ) ) {
     212                                $user = new \WP_User( $post->post_author, '', WPORG_SUPPORT_FORUMS_BLOGID );
     213                                if ( ! empty( $user->allcaps['bbp_blocked'] ) ) {
     214                                        array_push( self::$flagged['high'], 'user is blocked' );
     215                                }
     216                        }
     217
     218                        // No plugins.
     219                        if ( empty( $author_commit ) && empty( $author_plugins ) ) {
     220                                array_push( self::$flagged['low'], 'user has no plugins' );
     221                        }
     222
     223                        // Echo flag results (everyone pretty much has at least one).
     224                        echo '<ul class="plugin-flagged">';
     225                        foreach ( self::$flagged as $flag => $reasons ) {
     226                                if ( count( $reasons ) ) {
     227                                        echo '<li class="plugin-flagged-' . esc_attr( $flag ) . '"><strong>' . esc_html( strtoupper( $flag ) ) . ' (' . esc_html( count( $reasons ) ) . '):</strong> ' . esc_html( implode( '; ', $reasons ) ) . '</li>';
     228                                }
     229                        }
     230                        echo '</ul>';
     231                } else {
     232                        ?>
     233                        <ul>
     234                                <li><a href='https://plugins.trac.wordpress.org/log/<?php echo esc_attr( $post->post_name ); ?>/'>Development Log</a></li>
     235                                <li><a href='https://plugins.svn.wordpress.org/<?php echo esc_attr( $post->post_name ); ?>/'>Subversion Repository</a></li>
     236                                <li><a href='https://plugins.trac.wordpress.org/browser/<?php echo esc_attr( $post->post_name ); ?>/'>Browse in Trac</a></li>
     237                        </ul>
     238                        <?php
     239                }
     240
     241                add_filter( 'wp_comment_reply', function ( $string ) use ( $post, $author ) {
    51242                        $committers = Tools::get_plugin_committers( $post->post_name );
    52243                        $committers = array_map( function ( $user_login ) {
    … …  
    70261                        ?>
    71262                        <form id="contact-author" class="contact-author" method="POST" action="https://supportpress.wordpress.org/plugins/thread-new.php">
    72                                 <input type="hidden" name="to_email" value="<?php echo esc_attr( $author->user_email ); ?>" />
    73                                 <input type="hidden" name="to_name" value="<?php echo esc_attr( $author->display_name ); ?>" />
    74                                 <input type="hidden" name="cc" value="<?php echo esc_attr( $cc_emails ); ?>" />
    75                                 <input type="hidden" name="subject" value="<?php echo esc_attr( $subject ); ?>" />
    76                                 <button class="button button-primary" type="submit"><?php _e( 'Contact plugin author', 'wporg-plugins' ); ?></button>
     263                                <input type="hidden" name="to_email" value="<?php echo esc_attr( $author->user_email ); ?>"/>
     264                                <input type="hidden" name="to_name" value="<?php echo esc_attr( $author->display_name ); ?>"/>
     265                                <input type="hidden" name="cc" value="<?php echo esc_attr( $cc_emails ); ?>"/>
     266                                <input type="hidden" name="subject" value="<?php echo esc_attr( $subject ); ?>"/>
     267                                <button class="button button-primary" type="submit">Contact plugin author</button>
    77268                        </form>
    78269                        <?php
    … …  
    82273        }
    83274}
    84 
Note: See TracChangeset for help on using the changeset viewer.