WordPress.org

Making WordPress.org


Ignore:
Timestamp:
10/13/17 08:56:56 (2 months ago)
Author:
dd32
Message:

Plugin Directory: Generate md5 hashes for plugins.

This is a POC and may change or be removed in the future, it's here for testing purposes.

A api.wordpress.org endpoint may be available in the future to access it.
This is only enabled for the 'exploit-scanner' plugin at present, purely for testing, as it publishes the md5 hashes of its own files already

Compare https://wordpress.org/plugins/exploit-scanner/ to https://downloads.wordpress.org/plugins/exploit-scanner.1.5.2.checksums.json

See #3192

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/zip/class-builder.php

    r5246 r6022  
    1515    const ZIP_SVN_URL = PLUGIN_ZIP_SVN_URL; 
    1616 
    17     protected $zip_file = ''; 
    18     protected $tmp_build_dir  = ''; 
    19     protected $tmp_dir = ''; 
    20  
    21     protected $slug    = ''; 
    22     protected $version = ''; 
    23     protected $context = ''; 
    24  
    25     /** 
    26      * Generate a ZIP for a provided Plugin versions. 
     17    protected $zip_file      = ''; 
     18    protected $checksum_file = ''; 
     19    protected $tmp_build_dir = ''; 
     20    protected $tmp_dir       = ''; 
     21 
     22    protected $slug       = ''; 
     23    protected $version    = ''; 
     24    protected $context    = ''; 
     25    protected $stable_tag = ''; 
     26 
     27    /** 
     28     * Generate a ZIP for a provided Plugin tags. 
    2729     * 
    2830     * @param string $slug     The plugin slug. 
     
    3032     * @param string $context  The context of this Builder instance (commit #, etc) 
    3133     */ 
    32     public function build( $slug, $versions, $context = '' ) { 
     34    public function build( $slug, $versions, $context = '', $stable_tag = '' ) { 
    3335        // Bail when in an unconfigured environment. 
    3436        if ( ! defined( 'PLUGIN_ZIP_SVN_URL' ) ) { 
     
    3638        } 
    3739 
    38         $this->slug     = $slug; 
    39         $this->versions = $versions; 
    40         $this->context  = $context; 
     40        $this->slug       = $slug; 
     41        $this->versions   = $versions; 
     42        $this->context    = $context; 
     43        $this->stable_tag = $stable_tag; 
    4144 
    4245        // General TMP directory 
     
    97100            // Pull the ZIP file down we're going to modify, which may not already exist. 
    98101            SVN::up( $this->zip_file ); 
     102            // This is done within the checksum generation function due to us not knowing the checksum filename until export_plugin(). 
     103            // SVN::up( $this->checksum_file ); 
    99104 
    100105            try { 
     
    104109 
    105110                $this->export_plugin(); 
    106                 $this->fix_directory_dates();            
     111                $this->fix_directory_dates(); 
     112 
    107113                $this->generate_zip(); 
     114 
     115                $this->generate_checksums(); 
     116 
    108117                $this->cleanup_plugin_tmp(); 
    109118 
     
    114123                // Perform an SVN up to revert any changes made. 
    115124                SVN::up( $this->zip_file ); 
     125                if ( $this->checksum_file ) { 
     126                    SVN::up( $this->checksum_file ); 
     127                } 
    116128                continue; 
    117129            } 
    118130 
    119131            // Add the ZIP file to SVN - This is only really needed for new files which don't exist in SVN. 
    120             SVN::add( $this->zip_file );             
     132            SVN::add( $this->zip_file ); 
     133            if ( $this->checksum_file ) { 
     134                SVN::add( $this->checksum_file ); 
     135            } 
    121136        } 
    122137 
     
    146161 
    147162    /** 
     163     * Generates a JSON file containing the checksums of the files within the ZIP. 
     164     * 
     165     * In the event that a previous ZIP for this version exists, checksums for all versions of the file will be included. 
     166     */ 
     167    function generate_checksums() { 
     168        // Only enable this for the `exploit-scanner` plugin for the time being. 
     169        if ( 'exploit-scanner' != $this->slug ) { 
     170            return; 
     171        } 
     172 
     173        // Don't create checksums for trunk. 
     174        if ( ! $this->stable_tag || ( 'trunk' == $this->version && 'trunk' != $this->stable_tag && '' != $this->stable_tag ) ) { 
     175            return; 
     176        } 
     177 
     178        // Fetch the plugin headers 
     179        $plugin_data = false; 
     180        foreach ( glob( $this->tmp_build_dir . '/' . $this->slug . '/*.php' ) as $filename ) { 
     181            $plugin_data = get_plugin_data( $filename, false, false ); 
     182 
     183            if ( $plugin_data['Name'] && '' !== $plugin_data['Version'] ) { 
     184                break; 
     185            } 
     186        } 
     187 
     188        if ( ! $plugin_data || '' === $plugin_data['Version'] ) { 
     189            return; 
     190        } 
     191 
     192        $plugin_version = $plugin_data['Version']; 
     193        // Catch malformed version strings. 
     194        if ( basename( $plugin_version ) != $plugin_version ) { 
     195            return; 
     196        } 
     197 
     198        $this->checksum_file = "{$this->tmp_dir}/{$this->slug}/{$this->slug}.{$plugin_version}.checksums.json"; 
     199 
     200        // Checkout the Checksum file for this plugin version 
     201        SVN::up( $this->checksum_file ); 
     202 
     203        // Existing checksums? 
     204        $existing_json_checksum_file = file_exists( $this->checksum_file ); 
     205 
     206        $this->exec( sprintf( 
     207            'cd %s && find . -type f -print0 | sort -z | xargs -0 md5sum 2>&1', 
     208            escapeshellarg( $this->tmp_build_dir . '/' . $this->slug ) 
     209        ), $checksum_output, $return_value ); 
     210 
     211        if ( $return_value ) { 
     212        //  throw new Exception( __METHOD__ . ': Checksum generation failed, return code: ' . $return_value, 503 ); 
     213        // For now, just silently bail. 
     214            return; 
     215        } 
     216 
     217        $checksums = array(); 
     218        foreach ( $checksum_output as $line ) { 
     219            list( $md5, $filename ) = preg_split( '!\s+!', $line ); 
     220            $filename = preg_replace( '!^./!', '', $filename ); 
     221            $checksums[ trim( $filename ) ] = trim( $md5 ); 
     222        } 
     223 
     224        $json_checksum_file = (object) array( 
     225            'plugin'     => $this->slug, 
     226            'version'    => $plugin_version, 
     227            'source_tag' => $this->version, 
     228            'zip'        => basename( $this->zip_file ), 
     229            'checksums'  => $checksums 
     230        ); 
     231 
     232        // If the checksum file exists already, merge it into this one. 
     233        if ( $existing_json_checksum_file ) { 
     234            $existing_json_checksum_file = json_decode( file_get_contents( $this->checksum_file ) ); 
     235 
     236            if ( $existing_json_checksum_file && ! empty( $existing_json_checksum_file->checksums ) ) { 
     237                foreach ( $existing_json_checksum_file->checksums as $file => $checksum_details ) { 
     238 
     239                    if ( ! isset( $json_checksum_file->checksums[ $file ] ) ) { 
     240                        // Deleted file, include it in checksums. 
     241                        $json_checksum_file->checksums[ $file ] = $checksum_details; 
     242 
     243                    } elseif ( $json_checksum_file->checksums[ $file ] != $checksum_details ) { 
     244                        // Checksum has changed, include both in the resulting json file. 
     245                        if ( is_array( $checksum_details ) ) { 
     246                            $checksum_details[] = $json_checksum_file->checksums[ $file ]; 
     247                            $json_checksum_file->checksums[ $file ] = $checksum_details; 
     248                        } else { 
     249                            $json_checksum_file->checksums[ $file ] = array( 
     250                                $json_checksum_file->checksums[ $file ], 
     251                                $checksum_details 
     252                            ); 
     253                        } 
     254                    } 
     255                } 
     256            } 
     257        } 
     258 
     259        file_put_contents( $this->checksum_file, wp_json_encode( $json_checksum_file ) ); 
     260    } 
     261 
     262    /** 
    148263     * Generates a temporary unique directory in a given directory 
    149264     * 
     
    279394     */ 
    280395    public function invalidate_zip_caches( $versions ) { 
    281         // TODO: Implement PURGE  
     396        // TODO: Implement PURGE 
    282397        return true; 
    283398        if ( ! defined( 'PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION' ) ) { 
Note: See TracChangeset for help on using the changeset viewer.