Changeset 5147
- Timestamp:
- 03/13/2017 05:56:27 AM (7 years ago)
- Location:
- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory
- Files:
-
- 1 deleted
- 7 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php
r4301 r5147 20 20 new Routes\Query_Plugins(); 21 21 new Routes\SVN_Access(); 22 new Routes\Zip_Management();23 22 new Routes\Plugin_Committers(); 24 23 } -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/bin/rebuild-zip.php
r5139 r5147 1 1 <?php 2 2 namespace WordPressdotorg\Plugin_Directory; 3 use WordPressdotorg\Plugin_Directory\Tools\SVN; 3 4 4 5 // This script should only be called in a CLI environment. … … 7 8 } 8 9 9 ob_start();10 //ob_start(); 10 11 11 $opts = getopt( '', array( 'url:', 'abspath:', 'plugin:', ' changed-tags:', 'async' ) );12 $opts = getopt( '', array( 'url:', 'abspath:', 'plugin:', 'versions:', 'async' ) ); 12 13 13 14 // Guess the default parameters: … … 15 16 $opts['plugin'] = $argv[1]; 16 17 $argv[1] = '--plugin ' . $argv[1]; 18 } 19 if ( empty( $opts ) && $argc == 3 ) { 20 $opts['plugin'] = $argv[1]; 21 $argv[1] = '--plugin ' . $argv[1]; 22 23 $opts['versions'] = $argv[2]; 24 $argv[2] = '--versions ' . $argv[2]; 17 25 } 18 26 if ( empty( $opts['url'] ) ) { … … 22 30 $opts['abspath'] = substr( __DIR__, 0, strpos( __DIR__, 'wp-content' ) ); 23 31 } 24 25 if ( empty( $opts['changed-tags'] ) ) { 26 $opts['changed-tags'] = array( 'trunk' ); 27 } else { 28 $opts['changed-tags'] = explode( ',', $opts['changed-tags'] ); 32 if ( empty( $opts['versions'] ) ) { 33 $opts['versions'] = ''; 29 34 } 30 31 $opts['async'] = isset( $opts['async'] );32 35 33 36 foreach ( array( 'url', 'abspath', 'plugin' ) as $opt ) { … … 36 39 fwrite( STDERR, "Usage: php {$argv[0]} --plugin hello-dolly --abspath /home/example/public_html --url https://wordpress.org/plugins/\n" ); 37 40 fwrite( STDERR, "--url and --abspath will be guessed if possible.\n" ); 38 die();41 exit(1); 39 42 } 40 43 } … … 52 55 fwrite( STDERR, "\tphp " . implode( ' ', $argv ) . " --url " . get_site_url( WPORG_PLUGIN_DIRECTORY_BLOGID, '/' ) . "\n" ); 53 56 } 54 die();57 exit(1); 55 58 } 56 59 57 $plugin_slug 58 $ changed_tags = $opts['changed-tags'];59 $start_time 60 $plugin_slug = $opts['plugin']; 61 $versions = array_filter( array_unique( array_map( 'trim', (array) explode( ',', $opts['versions'] ) ) ), 'strlen' ); 62 $start_time = microtime(1); 60 63 61 // If async, queue it to be parsed instead. 62 if ( $opts['async'] ) { 63 Jobs\Plugin_Import::queue( $plugin_slug, array( 'tags_touched' => $changed_tags ) ); 64 echo "Queueing Import for $plugin_slug... OK\n"; 65 die(); 64 if ( empty( $versions ) ) { 65 // Rebuild them all! 66 $svn_tags = SVN::ls( "http://plugins.svn.wordpress.org/{$plugin_slug}/tags/" ); 67 if ( false === $svn_tags ) { 68 fwrite( STDERR, "Error! Failed to retrieve SVN tag listing." ); 69 exit(1); 70 } 71 72 $versions = array_map( 73 function( $dir ) { return trim( $dir, '/' ); }, 74 $svn_tags 75 ); 76 $versions[] = 'trunk'; 66 77 } 67 78 68 echo "Processing Import for $plugin_slug... "; 79 if ( ! $versions ) { 80 fwrite( STDERR, "Error! No versions specified (or we couldn't find any)" ); 81 exit(1); 82 } 83 84 echo "Rebuilding ZIPs for $plugin_slug... "; 69 85 try { 70 $importer = new CLI\Import; 71 $importer->import_from_svn( $plugin_slug, $changed_tags ); 86 $zip_builder = new ZIP\Builder(); 87 $zip_builder->build( 88 $plugin_slug, 89 $versions, 90 "{$plugin_slug}: Rebuild triggered by " . php_uname('n' ) 91 ); 92 72 93 echo "OK. Took " . round( microtime(1) - $start_time, 2 ) . "s\n"; 73 94 } catch( \Exception $e ) { 74 echo "Failed. Took " . round( microtime(1) - $start_time, 2 ) . "s\n"; 75 76 fwrite( STDERR, "[{$plugin_slug}] Plugin Import Failed: " . $e->getMessage() . "\n" ); 95 fwrite( STDERR, "{$plugin_slug}: Zip Rebuild failed: " . $e->getMessage() . "\n" ); 77 96 exit(1); 78 97 } -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php
r4764 r5147 121 121 'publish_posts' => 'plugin_approve', 122 122 'read_private_posts' => 'do_not_allow', 123 'delete_posts' => 'do_not_allow',123 'delete_posts' => is_super_admin() ? 'manage_options' : 'do_not_allow', 124 124 'create_posts' => 'do_not_allow', 125 125 ), … … 1006 1006 */ 1007 1007 function custom_redirects() { 1008 1009 1008 // Handle a redirect for /$plugin/$tab_name/ to /$plugin/#$tab_name. 1010 1009 if ( get_query_var( 'redirect_plugin_tab' ) ) { … … 1031 1030 // The about page is now over at /developers/. 1032 1031 if ( 'about' === $path[2] ) { 1033 wp_safe_redirect( home_url( '/developers/' . ( ( isset( $path[3] ) && 'add' == $path[3] ) ? 'add/' : '' ) ) ); 1032 if ( isset( $path[3] ) && 'add' == $path[3] ) { 1033 wp_safe_redirect( home_url( '/developers/add/' ) ); 1034 } elseif ( isset( $path[3] ) && 'validator' == $path[3] ) { 1035 wp_safe_redirect( home_url( '/developers/readme-validator/' ) ); 1036 } else { 1037 wp_safe_redirect( home_url( '/developers/' ) ); 1038 } 1034 1039 die(); 1035 1040 } -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/cli/class-import.php
r4727 r5147 8 8 use WordPressdotorg\Plugin_Directory\Tools\Filesystem; 9 9 use WordPressdotorg\Plugin_Directory\Tools\SVN; 10 use WordPressdotorg\Plugin_Directory\Zip\Builder; 10 11 use Exception; 11 12 … … 47 48 * @throws \Exception 48 49 * 49 * @param string $plugin_slug The slug of the plugin to import. 50 * @param array $svn_changed_tags A list of tags/trunk which the SVN change touched. Optional. 51 */ 52 public function import_from_svn( $plugin_slug, $svn_changed_tags = array( 'trunk' ) ) { 50 * @param string $plugin_slug The slug of the plugin to import. 51 * @param array $svn_changed_tags A list of tags/trunk which the SVN change touched. Optional. 52 * @param array $svn_revision_triggered The SVN revision which this import has been triggered by. 53 */ 54 public function import_from_svn( $plugin_slug, $svn_changed_tags = array( 'trunk' ), $svn_revision_triggered = 0 ) { 53 55 global $wpdb; 54 56 … … 190 192 $current_stable_tag = get_post_meta( $plugin->ID, 'stable_tag', true ) ?: 'trunk'; 191 193 192 $this->rebuild_ invalidate_zips( $plugin_slug, $stable_tag, $current_stable_tag, $svn_changed_tags);194 $this->rebuild_affected_zips( $plugin_slug, $stable_tag, $current_stable_tag, $svn_changed_tags, $svn_revision_triggered ); 193 195 194 196 // Finally, set the new version live. … … 202 204 203 205 /** 204 * Rebuild and Invalidate plugin ZIPs on all web nodes using the REST API Endpoints. 205 * 206 * @param string $plugin_slug The plugin slug. 207 * @param string $stable_tag The new stable tag. 208 * @param string $current_stable_tag The new stable tag. 209 * @param array $svn_changed_tags The list of SVN tags modified since last import. 210 */ 211 protected function rebuild_invalidate_zips( $plugin_slug, $stable_tag, $current_stable_tag, $svn_changed_tags ) { 212 global $wporg_webs; 213 $invalidate_zips = $rebuild_zips = array(); 214 215 foreach ( $svn_changed_tags as $tag ) { 216 if ( 'trunk' == $tag ) { 217 if ( 'trunk' == $stable_tag ) { 218 // Trunk is stable, so we'll need to rebuild the zip 219 $rebuild_zips[] = "{$plugin_slug}.zip"; 220 } else { 221 // Trunk isn't stable, so we'll just remove it so it's rebuilt on demand 222 $invalidate_zips[] = "{$plugin_slug}.zip"; 223 } 224 continue; 225 } 226 if ( $tag == $stable_tag || $tag == $current_stable_tag ) { 227 $rebuild_zips[] = "{$plugin_slug}.{$tag}.zip"; 228 } else { 229 $invalidate_zips[] = "{$plugin_slug}.{$tag}.zip"; 230 } 231 } 232 if ( $stable_tag != $current_stable_tag ) { 233 // plugin is updated, ensure that everything is rebuilt. 234 if ( ! in_array( $stable_tag, $svn_changed_tags ) ) { 235 $rebuild_zips[] = "{$plugin_slug}" . ( 'trunk' == $stable_tag ? '' : ".{$stable_tag}" ) . '.zip'; 236 } 237 } 238 239 if ( empty( $wporg_webs ) || ( empty( $invalidate_zips ) && empty( $rebuild_zips ) ) ) { 240 return; 241 } 242 243 $urls = array(); 244 foreach ( $wporg_webs as $node ) { 245 $urls[] = preg_replace( '!^https?://wordpress.org/!', "http://$node/", site_url( '/wp-json/plugins/v1/zip-management' ) ); 246 } 247 $headers = array( 248 'User-Agent' => 'WordPress.org Plugin Directory', 249 'Host' => 'WordPress.org', 250 'Authorization' => 'BEARER ' . PLUGIN_API_INTERNAL_BEARER_TOKEN, 251 ); 252 $body = array( 253 'plugins' => array( 254 $plugin_slug => array( 255 'invalidate' => $invalidate_zips, 256 'rebuild' => $rebuild_zips, 257 ) 258 ) 259 ); 260 261 $results = array(); 262 foreach ( $urls as $url ) { 263 $results[ $url ] = wp_remote_post( $url, array( 264 'body' => $body, 265 'headers' => $headers, 266 'sslverify' => false 267 ) ); 268 } 269 270 // TODO Do something with $results to verify all servers said the rebuilt zip was correct or something. 206 * (Re)build plugin ZIPs affected by this commit. 207 * 208 * @param string $plugin_slug The plugin slug. 209 * @param string $stable_tag The new stable tag. 210 * @param string $current_stable_tag The new stable tag. 211 * @param array $svn_changed_tags The list of SVN tags modified since last import. 212 * @param string $svn_revision_triggered The SVN revision which triggered the rebuild. 213 * 214 * @return bool 215 */ 216 protected function rebuild_affected_zips( $plugin_slug, $stable_tag, $current_stable_tag, $svn_changed_tags, $svn_revision_triggered = 0 ) { 217 $versions_to_build = $svn_changed_tags; 218 219 // Ensure that the stable zip is built/rebuilt if need be. 220 if ( $stable_tag != $current_stable_tag && ! in_array( $stable_tag, $versions_to_build ) ) { 221 $versions_to_build[] = $stable_tag; 222 } 223 224 // Rebuild/Build $build_zips 225 try { 226 // This will rebuild the ZIP. 227 $zip_builder = new Builder(); 228 $zip_builder->build( 229 $plugin_slug, 230 array_unique( $versions_to_build ), 231 $svn_revision_triggered ? 232 "{$plugin_slug}: ZIP build triggered by https://plugins.trac.wordpress.org/changeset/{$svn_revision_triggered}" : 233 "{$plugin_slug}: ZIP build triggered by " . php_uname('n') 234 ); 235 } catch( Exception $e ) { 236 return false; 237 } 238 239 return true; 271 240 } 272 241 -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/jobs/class-plugin-import.php
r4563 r5147 34 34 $changed_tags = isset( $plugin_data['tags_touched'] ) ? $plugin_data['tags_touched'] : array( 'trunk' ); 35 35 36 $revision = isset( $plugin_data['revisions'] ) ? max( (array)$plugin_data['revisions'] ) : false; 37 36 38 try { 37 39 $importer = new CLI\Import; 38 $importer->import_from_svn( $plugin_slug, $changed_tags );40 $importer->import_from_svn( $plugin_slug, $changed_tags, $revision ); 39 41 } catch( Exception $e ) { 40 42 fwrite( STDERR, "[{$plugin_slug}] Plugin Import Failed: " . $e->getMessage() . "\n" ); -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/tools/class-svn.php
r3512 r5147 22 22 * } 23 23 */ 24 public static function import( $path, $url, $message ) { 25 $options = array( 26 'non-interactive', 27 'm' => $message, 28 'user' => PLUGIN_SVN_MANAGEMENT_USER, 29 'pass' => PLUGIN_SVN_MANAGEMENT_PASS, 30 ); 24 public static function import( $path, $url, $message, $options = array() ) { 25 $options[] = 'non-interactive'; 26 $options['m'] = $message; 27 if ( empty( $options['username'] ) ) { 28 $options['username'] = PLUGIN_SVN_MANAGEMENT_USER; 29 $options['password'] = PLUGIN_SVN_MANAGEMENT_PASS; 30 } 31 31 32 $esc_options = self::parse_esc_parameters( $options ); 32 33 … … 68 69 $output = self::shell_exec( "svn export $esc_options $esc_url $esc_destination 2>&1" ); 69 70 if ( preg_match( '/Exported revision (?P<revision>\d+)[.]/i', $output, $m ) ) { 71 $revision = (int) $m['revision']; 72 $result = true; 73 } else { 74 $result = false; 75 $errors = self::parse_svn_errors( $output ); 76 } 77 78 return compact( 'result', 'revision', 'errors' ); 79 } 80 81 /** 82 * Create an SVN Checkout of a URL to a local directory. 83 * 84 * @static 85 * 86 * @param string $url The URL to export. 87 * @param string $destination The local folder to checkout into. 88 * @param array $options Optional. A list of options to pass to SVN. Default: empty array. 89 * @return array { 90 * @type bool $result The result of the operation. 91 * @type int $revision The revision exported. 92 * } 93 */ 94 public static function checkout( $url, $destination, $options = array() ) { 95 $options[] = 'non-interactive'; 96 $esc_options = self::parse_esc_parameters( $options ); 97 98 $esc_url = escapeshellarg( $url ); 99 $esc_destination = escapeshellarg( $destination ); 100 101 $output = self::shell_exec( "svn checkout $esc_options $esc_url $esc_destination 2>&1" ); 102 if ( preg_match( '/Checked out revision (?P<revision>\d+)[.]/i', $output, $m ) ) { 103 $revision = (int) $m['revision']; 104 $result = true; 105 } else { 106 $result = false; 107 $errors = self::parse_svn_errors( $output ); 108 } 109 110 return compact( 'result', 'revision', 'errors' ); 111 } 112 113 /** 114 * Update a SVN checkout. 115 * 116 * @static 117 * 118 * @param string $checkout The path of the SVN checkout to update. 119 * @param array $options Optional. A list of options to pass to SVN. Default: empty array. 120 * @return array { 121 * @type bool $result The result of the operation. 122 * @type int $revision The revision exported. 123 * } 124 */ 125 public static function up( $checkout, $options = array() ) { 126 $options[] = 'non-interactive'; 127 $esc_options = self::parse_esc_parameters( $options ); 128 129 $esc_checkout = escapeshellarg( $checkout ); 130 131 $output = self::shell_exec( "svn up $esc_options $esc_checkout 2>&1" ); 132 if ( preg_match( '/Updated to revision (?P<revision>\d+)[.]/i', $output, $m ) ) { 133 $revision = (int) $m['revision']; 134 $result = true; 135 } else { 136 $result = false; 137 $errors = self::parse_svn_errors( $output ); 138 } 139 140 return compact( 'result', 'revision', 'errors' ); 141 } 142 143 /** 144 * Add a file in a SVN checkout to be revisioned. 145 * 146 * @static 147 * 148 * @param string $checkout The path of the file to add to SVN. 149 * @return array { 150 * @type bool $result The result of the operation. 151 * } 152 */ 153 public static function add( $file ) { 154 $options[] = 'non-interactive'; 155 $esc_options = self::parse_esc_parameters( $options ); 156 157 $esc_file = escapeshellarg( $file ); 158 159 $output = self::shell_exec( "svn add $esc_options $esc_file 2>&1" ); 160 if ( preg_match( "/^A/i", $output ) ) {; 161 $result = true; 162 } else { 163 $result = false; 164 $errors = self::parse_svn_errors( $output ); 165 } 166 167 return compact( 'result', 'errors' ); 168 } 169 170 /** 171 * Commit changes in a SVN checkout. 172 * 173 * @static 174 * 175 * @param string $checkout The local folder to import into SVN. 176 * @param string $message The commit message. 177 * @param array $options Any specific options to pass to SVN. 178 * @return array { 179 * @type bool $result The result of the operation. 180 * @type int $revision The revision imported. 181 * } 182 */ 183 public static function commit( $checkout, $message, $options = array() ) { 184 $options[] = 'non-interactive'; 185 $options['m'] = $message; 186 if ( empty( $options['username'] ) ) { 187 $options['username'] = PLUGIN_SVN_MANAGEMENT_USER; 188 $options['password'] = PLUGIN_SVN_MANAGEMENT_PASS; 189 } 190 191 $esc_options = self::parse_esc_parameters( $options ); 192 193 $esc_checkout = escapeshellarg( $checkout ); 194 195 $output = self::shell_exec( "svn commit $esc_options $esc_checkout 2>&1" ); 196 if ( preg_match( '/Committed revision (?P<revision>\d+)[.]/i', $output, $m ) ) { 70 197 $revision = (int) $m['revision']; 71 198 $result = true; -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/zip/class-builder.php
r4727 r5147 11 11 class Builder { 12 12 13 /** 14 * The base directory for the ZIP files. 15 * Zip files will be stored in a sub-directory, such as: 16 * /tmp/plugin-zipfiles/hello-dolly/hello-dolly.zip 17 */ 18 const ZIP_DIR = '/tmp/plugin-zipfiles'; 19 const SVN_URL = 'https://plugins.svn.wordpress.org'; 20 21 public $zip_file = ''; 22 public $md5_file = ''; 23 protected $tmp_build_file = ''; 13 const TMP_DIR = '/tmp/plugin-zip-builder'; 14 const SVN_URL = 'http://plugins.svn.wordpress.org'; 15 const ZIP_SVN_URL = PLUGIN_ZIP_SVN_URL; 16 17 protected $zip_file = ''; 24 18 protected $tmp_build_dir = ''; 25 26 27 /** 28 * Generate a ZIP for a provided Plugin Version. 29 * 30 * @param string $plugin_slug The Plugin slug 31 * @param string $version The version to build (tag, or trunk) 32 */ 33 public function __construct( $slug, $version ) { 34 if ( ! is_dir( self::ZIP_DIR ) ) { 35 mkdir( self::ZIP_DIR, 0777, true ); 36 chmod( self::ZIP_DIR, 0777 ); 37 } 38 if ( ! is_dir( self::ZIP_DIR . '/' . $slug ) ) { 39 mkdir( self::ZIP_DIR . '/' . $slug, 0777, true ); 40 chmod( self::ZIP_DIR . '/' . $slug, 0777 ); 41 } 42 43 $this->slug = $slug; 44 $this->version = $version; 45 46 if ( 'trunk' == $this->version ) { 47 $this->zip_file = self::ZIP_DIR . "/{$this->slug}/{$this->slug}.zip"; 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. 27 * 28 * @param string $slug The plugin slug. 29 * @param array $versions The versions of the plugin to build ZIPs for. 30 * @param string $context The context of this Builder instance (commit #, etc) 31 */ 32 public function build( $slug, $versions, $context = '' ) { 33 // Bail when in an unconfigured environment. 34 if ( ! defined( 'PLUGIN_ZIP_SVN_URL' ) ) { 35 return false; 36 } 37 38 $this->slug = $slug; 39 $this->versions = $versions; 40 $this->context = $context; 41 42 // General TMP directory 43 if ( ! is_dir( self::TMP_DIR ) ) { 44 mkdir( self::TMP_DIR, 0777, true ); 45 chmod( self::TMP_DIR, 0777 ); 46 } 47 48 // Temp Directory for this instance of the Builder class. 49 $this->tmp_dir = $this->generate_temporary_directory( self::TMP_DIR, $slug ); 50 51 // Create a checkout of the ZIP SVN 52 $res_checkout = SVN::checkout( 53 self::ZIP_SVN_URL, 54 $this->tmp_dir, 55 array( 56 'depth' => 'empty', 57 'username' => PLUGIN_ZIP_SVN_USER, 58 'password' => PLUGIN_ZIP_SVN_PASS, 59 ) 60 ); 61 62 if ( $res_checkout['result'] ) { 63 64 // Ensure the plugins folder exists within svn 65 $plugin_folder = "{$this->tmp_dir}/{$this->slug}/"; 66 $res = SVN::up( 67 $plugin_folder, 68 array( 69 'depth' => 'empty' 70 ) 71 ); 72 if ( ! is_dir( $plugin_folder ) ) { 73 mkdir( $plugin_folder, 0777, true ); 74 $res = SVN::add( $plugin_folder ); 75 } 76 if ( ! $res['result'] ) { 77 throw new Exception( __METHOD__ . ": Failed to create {$plugin_folder}." ); 78 } 48 79 } else { 49 $this->zip_file = self::ZIP_DIR . "/{$this->slug}/{$this->slug}.{$this->version}.zip"; 50 } 51 $this->md5_file = $this->zip_file . '.md5'; 52 53 } 54 55 /** 56 * Generate a ZIP for the plugin + version 57 */ 58 public function build() { 59 try { 60 $this->tmp_build_file = $this->generate_temporary_filename( dirname( $this->zip_file ), "tmp-{$this->slug}.{$this->version}", '.zip' ); 61 $this->tmp_build_dir = $this->tmp_build_file . '-files'; 62 mkdir( $this->tmp_build_dir, 0777, true ); 63 64 $this->export_plugin(); 65 $this->fix_directory_dates(); 66 $this->generate_zip(); 67 $this->move_into_place(); 68 $this->generate_md5(); 69 70 $this->cleanup(); 71 72 return true; 73 } catch( Exception $e ) { 74 $this->cleanup(); 75 throw $e; 76 }/* finally { // PHP 5.5+, meta.svn is limited to PHP 5.4 code still. 77 $this->cleanup(); 78 }*/ 79 } 80 81 /** 82 * Generates a temporary unique file in a given directory 80 throw new Exception( __METHOD__ . ": Failed to create checkout of {$svn_url}." ); 81 } 82 83 // Build the requested ZIPs 84 foreach ( $versions as $version ) { 85 $this->version = $version; 86 87 if ( 'trunk' == $version ) { 88 $this->zip_file = "{$this->tmp_dir}/{$this->slug}/{$this->slug}.zip"; 89 } else { 90 $this->zip_file = "{$this->tmp_dir}/{$this->slug}/{$this->slug}.{$version}.zip"; 91 } 92 93 // Pull the ZIP file down we're going to modify, which may not already exist. 94 SVN::up( $this->zip_file ); 95 96 try { 97 98 $this->tmp_build_dir = $this->zip_file . '-files'; 99 mkdir( $this->tmp_build_dir, 0777, true ); 100 101 $this->export_plugin(); 102 $this->fix_directory_dates(); 103 $this->generate_zip(); 104 $this->cleanup_plugin_tmp(); 105 106 } catch( Exception $e ) { 107 // In event of error, skip this file this time. 108 $this->cleanup_plugin_tmp(); 109 110 // Perform an SVN up to revert any changes made. 111 SVN::up( $this->zip_file ); 112 continue; 113 } 114 115 // Add the ZIP file to SVN - This is only really needed for new files which don't exist in SVN. 116 SVN::add( $this->zip_file ); 117 } 118 119 $res = SVN::commit( 120 $this->tmp_dir, 121 $this->context ? $this->context : "Updated ZIPs for {$this->slug}.", 122 array( 123 'username' => PLUGIN_ZIP_SVN_USER, 124 'password' => PLUGIN_ZIP_SVN_PASS, 125 ) 126 ); 127 128 $this->invalidate_zip_caches( $versions ); 129 130 $this->cleanup(); 131 132 if ( ! $res['result'] ) { 133 if ( $res['errors'] ) { 134 throw new Exception( __METHOD__ . ': Failed to commit the new ZIPs: ' . $res['errors'][0]['error_message'] ); 135 } else { 136 throw new Exception( __METHOD__ . ': Commit failed without error, maybe there were no modified files?' ); 137 } 138 } 139 140 return true; 141 } 142 143 /** 144 * Generates a temporary unique directory in a given directory 83 145 * 84 146 * Performs a similar job to `tempnam()` with an added suffix and doesn't … … 92 154 * @param string $suffix The file suffix, optional. 93 155 * 94 * @return string Filename of unique temporary file.95 */ 96 protected function generate_temporary_ filename( $dir, $prefix, $suffix = '' ) {156 * @return string Path of unique temporary directory. 157 */ 158 protected function generate_temporary_directory( $dir, $prefix, $suffix = '' ) { 97 159 $i = 0; 98 160 do { … … 106 168 107 169 fclose( $fp ); 170 171 // Convert file to directory. 172 unlink( $filename ); 173 if ( ! mkdir( $filename, 0777, true ) ) { 174 throw new Exception( __METHOD__ . ': Could not convert temporary filename to directory.' ); 175 } 176 chmod( $filename, 0777 ); 108 177 109 178 return $filename; … … 168 237 ) ); 169 238 if ( ! $latest_file_modified_timestamp ) { 170 throw new Exception( _ METHOD__ . ': Unable to locate the latest modified files timestamp.', 503 );239 throw new Exception( __METHOD__ . ': Unable to locate the latest modified files timestamp.', 503 ); 171 240 } 172 241 … … 182 251 */ 183 252 protected function generate_zip() { 184 // We have to remove the temporary 0-byte file first as zip will complain about not being able to find the zip structures. 185 unlink( $this->tmp_build_file ); 253 // If we're building an existing zip, remove the existing file first. 254 if ( file_exists( $this->zip_file ) ) { 255 unlink( $this->zip_file ); 256 } 186 257 $this->exec( sprintf( 187 258 'cd %s && find %s -print0 | sort -z | xargs -0 zip -Xu %s 2>&1', 188 259 escapeshellarg( $this->tmp_build_dir ), 189 260 escapeshellarg( $this->slug ), 190 escapeshellarg( $this-> tmp_build_file )261 escapeshellarg( $this->zip_file ) 191 262 ), $zip_build_output, $return_value ); 192 263 … … 196 267 } 197 268 198 /** 199 * Moves the completed ZIP into it's real-life location. 200 */ 201 protected function move_into_place() { 202 $this->exec( sprintf( 203 'mv -f %s %s', 204 escapeshellarg( $this->tmp_build_file ), 205 escapeshellarg( $this->zip_file ) 206 ), $output, $return_value ); 207 208 if ( $return_value ) { 209 throw new Exception( __METHOD__ . ': Could not move ZIP into place.', 503 ); 210 } 211 } 212 213 /** 214 * Generates the MD5 for the ZIP file used for serving. 215 * 216 * This can also be used for generating a package signature in the future. 217 */ 218 protected function generate_md5() { 219 $this->exec( sprintf( 220 "md5sum %s | head -c 32 > %s", 221 escapeshellarg( $this->zip_file ), 222 escapeshellarg( $this->md5_file ) 223 ), $output, $return_code ); 224 225 if ( $return_code ) { 226 throw new Exception( __METHOD__ . ': Failed to create file checksum.', 503 ); 269 270 /** 271 * Purge ZIP caches after ZIP building. 272 * 273 * @param array $versions The list of plugin versions of modified zips. 274 * @return bool 275 */ 276 public function invalidate_zip_caches( $versions ) { 277 // TODO: Implement PURGE 278 return true; 279 if ( ! defined( 'PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION' ) ) { 280 return true; 281 } 282 283 foreach ( $versions as $version ) { 284 if ( 'trunk' == $version ) { 285 $zip = "{$this->slug}/{$this->slug}.zip"; 286 } else { 287 $zip = "{$this->slug}/{$this->slug}.{$version}.zip"; 288 } 289 290 foreach ( $plugins_downloads_load_balancer /* TODO */ as $lb ) { 291 $url = 'http://' . $lb . PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION . $zip; 292 wp_remote_request( 293 $url, 294 array( 295 'method' => 'PURGE', 296 ) 297 ); 298 } 227 299 } 228 300 } … … 232 304 */ 233 305 protected function cleanup() { 234 if ( $this->tmp_build_file && file_exists( $this->tmp_build_file ) ) { 235 unlink( $this->tmp_build_file ); 236 } 306 if ( $this->tmp_dir ) { 307 $this->exec( sprintf( 'rm -rf %s', escapeshellarg( $this->tmp_dir ) ) ); 308 } 309 } 310 311 /** 312 * Cleans up any temporary directories created by the ZIP builder for a specific build. 313 */ 314 protected function cleanup_plugin_tmp() { 237 315 if ( $this->tmp_build_dir ) { 238 316 $this->exec( sprintf( 'rm -rf %s', escapeshellarg( $this->tmp_build_dir ) ) ); -
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/zip/class-serve.php
r4728 r5147 13 13 class Serve { 14 14 15 const ZIP_DIR = '/tmp/plugin-zipfiles';16 17 15 public function __construct() { 18 16 try { 19 17 $request = $this->determine_request(); 20 18 21 // Serve & perhaps build if need be 22 $files = $this->get_files( $request ); 23 if ( ! file_exists( $files['zip'] ) ) { 24 $builder = new Builder( $request['slug'], $request['version'] ); 25 $builder->build(); 26 clearstatcache(); 27 } 28 29 $this->serve_zip( $files, $request ); 19 $this->serve_zip( $request ); 30 20 31 21 if ( $request['args']['stats'] ) { … … 34 24 35 25 } catch ( Exception $e ) { 36 $this->error( $e->getCode());26 $this->error(); 37 27 } 38 28 … … 51 41 52 42 if ( ! preg_match( "!^(?P<slug>[a-z0-9-]+)(.(?P<version>.+))?.zip$!i", $zip, $m ) ) { 53 throw new Exception( __METHOD__ . ": Invalid URL " );43 throw new Exception( __METHOD__ . ": Invalid URL." ); 54 44 } 55 45 … … 96 86 } 97 87 if ( ! $version ) { 98 throw new Exception( __METHOD__ . ": A version for $plugin_slug cannot be determined." , 404);88 throw new Exception( __METHOD__ . ": A version for $plugin_slug cannot be determined." ); 99 89 } 100 90 … … 121 111 122 112 if ( ! $post_id ) { 123 throw new Exception( __METHOD__ . ": A post_id for $plugin_slug cannot be determined." , 404);113 throw new Exception( __METHOD__ . ": A post_id for $plugin_slug cannot be determined." ); 124 114 } 125 115 … … 133 123 * @return array An array containing the files to use for the request, 'zip' and 'md5'. 134 124 */ 135 protected function get_file s( $request ) {125 protected function get_file( $request ) { 136 126 if ( empty( $request['version'] ) || 'trunk' == $request['version'] ) { 137 $zip = self::ZIP_DIR . "/{$request['slug']}/{$request['slug']}.zip";127 return "{$request['slug']}/{$request['slug']}.zip"; 138 128 } else { 139 $zip = self::ZIP_DIR . "/{$request['slug']}/{$request['slug']}.{$request['version']}.zip"; 140 } 141 $md5 = $zip . '.md5'; 142 143 return compact( 'zip', 'md5' ); 129 return "{$request['slug']}/{$request['slug']}.{$request['version']}.zip"; 130 } 144 131 } 145 132 … … 147 134 * Output a ZIP file with all headers. 148 135 * 149 * @param array $files {150 * Array of files for the request.151 *152 * @type string $zip The Zip file to serve.153 * @type string $md5 The MD5 file to use for the Content-MD5 header. Optional.154 * }155 136 * @param array $request The request array for the request. 156 137 */ 157 protected function serve_zip( $files, $request ) { 158 header( 'Content-Type: application/zip' ); 159 header( 'Content-Disposition: attachment; filename=' . basename( $files['zip'] ) ); 160 if ( !empty( $files['md5'] ) && ( $md5 = file_get_contents( $files['md5'] ) ) ) { 161 header( 'Content-MD5: ' . $md5 ); 162 } 163 164 // TODO: Accel Redirect allows for ZIP files to be cached on the LB's 165 // header('X-Accel-Redirect: ' . $accel_redirect ); 166 167 header( 'Content-Length: ' . filesize( $files['zip'] ) ); 168 readfile( $files['zip'] ); 138 protected function serve_zip( $request ) { 139 $zip = $this->get_file( $request ); 140 141 if ( defined( 'PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION' ) ) { 142 $zip_url = PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION . $zip; 143 144 header( 'Content-Type: application/zip' ); 145 header( 'Content-Disposition: attachment; filename=' . basename( $zip ) ); 146 header( "X-Accel-Redirect: $zip_url" ); 147 } else { 148 header( 'Content-Type: text/plain' ); 149 echo "This is a request for $zip, this server isn't currently configured to serve zip files.\n"; 150 } 151 152 if ( function_exists( 'fastcgi_finish_request' ) ) { 153 fastcgi_finish_request(); 154 } 155 169 156 } 170 157 … … 225 212 226 213 /** 227 * Quit with an Error code. 228 * 229 * @param int $code The HTTP Error code, 404 or 503. 230 */ 231 protected function error( $code = 404 ) { 214 * Bail with a 404. 215 */ 216 protected function error() { 232 217 $protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; 233 218 $protocol .= ' '; 234 switch ( $code ) { 235 case 503: 236 header( $protocol . '503 Service Unavailable' ); 237 die( '503 Service Unavailable' ); 238 239 default: 240 case 404: 241 header( $protocol . '404 File not found' ); 242 die( '404 File not found' ); 243 } 219 220 header( $protocol . '404 File not found' ); 221 die( '404 file not found' ); 244 222 } 245 223
Note: See TracChangeset
for help on using the changeset viewer.