WordPress PHP Cross Reference Web Logs

Source: /wp-admin/includes/file.php - 1061 lines - 42035 bytes - Summary - Text - Print

Description: Functions for reading, writing, modifying, and deleting files on the file system. Includes functionality for theme-specific files as well as operations for uploading, archiving, and rendering output when necessary.

   1  <?php
   2  /**
   3   * Functions for reading, writing, modifying, and deleting files on the file system.
   4   * Includes functionality for theme-specific files as well as operations for uploading,
   5   * archiving, and rendering output when necessary.
   6   *
   7   * @package WordPress
   8   * @subpackage Administration
   9   */
  10  
  11  /** The descriptions for theme files. */
  12  $wp_file_descriptions = array(
  13      'index.php' => __( 'Main Index Template' ),
  14      'style.css' => __( 'Stylesheet' ),
  15      'editor-style.css' => __( 'Visual Editor Stylesheet' ),
  16      'editor-style-rtl.css' => __( 'Visual Editor RTL Stylesheet' ),
  17      'rtl.css' => __( 'RTL Stylesheet' ),
  18      'comments.php' => __( 'Comments' ),
  19      'comments-popup.php' => __( 'Popup Comments' ),
  20      'footer.php' => __( 'Footer' ),
  21      'header.php' => __( 'Header' ),
  22      'sidebar.php' => __( 'Sidebar' ),
  23      'archive.php' => __( 'Archives' ),
  24      'author.php' => __( 'Author Template' ),
  25      'tag.php' => __( 'Tag Template' ),
  26      'category.php' => __( 'Category Template' ),
  27      'page.php' => __( 'Page Template' ),
  28      'search.php' => __( 'Search Results' ),
  29      'searchform.php' => __( 'Search Form' ),
  30      'single.php' => __( 'Single Post' ),
  31      '404.php' => __( '404 Template' ),
  32      'link.php' => __( 'Links Template' ),
  33      'functions.php' => __( 'Theme Functions' ),
  34      'attachment.php' => __( 'Attachment Template' ),
  35      'image.php' => __('Image Attachment Template'),
  36      'video.php' => __('Video Attachment Template'),
  37      'audio.php' => __('Audio Attachment Template'),
  38      'application.php' => __('Application Attachment Template'),
  39      'my-hacks.php' => __( 'my-hacks.php (legacy hacks support)' ),
  40      '.htaccess' => __( '.htaccess (for rewrite rules )' ),
  41      // Deprecated files
  42      'wp-layout.css' => __( 'Stylesheet' ),
  43      'wp-comments.php' => __( 'Comments Template' ),
  44      'wp-comments-popup.php' => __( 'Popup Comments Template' ),
  45  );
  46  
  47  /**
  48   * Get the description for standard WordPress theme files and other various standard
  49   * WordPress files
  50   *
  51   * @since 1.5.0
  52   *
  53   * @uses _cleanup_header_comment
  54   * @uses $wp_file_descriptions
  55   * @param string $file Filesystem path or filename
  56   * @return string Description of file from $wp_file_descriptions or basename of $file if description doesn't exist
  57   */
  58  function get_file_description( $file ) {
  59      global $wp_file_descriptions;
  60  
  61      if ( isset( $wp_file_descriptions[basename( $file )] ) ) {
  62          return $wp_file_descriptions[basename( $file )];
  63      }
  64      elseif ( file_exists( $file ) && is_file( $file ) ) {
  65          $template_data = implode( '', file( $file ) );
  66          if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name ))
  67              return sprintf( __( '%s Page Template' ), _cleanup_header_comment($name[1]) );
  68      }
  69  
  70      return trim( basename( $file ) );
  71  }
  72  
  73  /**
  74   * Get the absolute filesystem path to the root of the WordPress installation
  75   *
  76   * @since 1.5.0
  77   *
  78   * @uses get_option
  79   * @return string Full filesystem path to the root of the WordPress installation
  80   */
  81  function get_home_path() {
  82      $home = get_option( 'home' );
  83      $siteurl = get_option( 'siteurl' );
  84      if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
  85          $wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */
  86          $pos = strripos( str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] ), trailingslashit( $wp_path_rel_to_home ) );
  87          $home_path = substr( $_SERVER['SCRIPT_FILENAME'], 0, $pos );
  88          $home_path = trailingslashit( $home_path );
  89      } else {
  90          $home_path = ABSPATH;
  91      }
  92  
  93      return $home_path;
  94  }
  95  
  96  /**
  97   * Get the real file system path to a file to edit within the admin
  98   *
  99   * If the $file is index.php or .htaccess this function will assume it is relative
 100   * to the install root, otherwise it is assumed the file is relative to the wp-content
 101   * directory
 102   *
 103   * @since 1.5.0
 104   *
 105   * @uses get_home_path
 106   * @uses WP_CONTENT_DIR full filesystem path to the wp-content directory
 107   * @param string $file filesystem path relative to the WordPress install directory or to the wp-content directory
 108   * @return string full file system path to edit
 109   */
 110  function get_real_file_to_edit( $file ) {
 111      if ('index.php' == $file || '.htaccess' == $file ) {
 112          $real_file = get_home_path() . $file;
 113      } else {
 114          $real_file = WP_CONTENT_DIR . $file;
 115      }
 116  
 117      return $real_file;
 118  }
 119  
 120  /**
 121   * Returns a listing of all files in the specified folder and all subdirectories up to 100 levels deep.
 122   * The depth of the recursiveness can be controlled by the $levels param.
 123   *
 124   * @since 2.6.0
 125   *
 126   * @param string $folder Full path to folder
 127   * @param int $levels (optional) Levels of folders to follow, Default: 100 (PHP Loop limit).
 128   * @return bool|array False on failure, Else array of files
 129   */
 130  function list_files( $folder = '', $levels = 100 ) {
 131      if ( empty($folder) )
 132          return false;
 133  
 134      if ( ! $levels )
 135          return false;
 136  
 137      $files = array();
 138      if ( $dir = @opendir( $folder ) ) {
 139          while (($file = readdir( $dir ) ) !== false ) {
 140              if ( in_array($file, array('.', '..') ) )
 141                  continue;
 142              if ( is_dir( $folder . '/' . $file ) ) {
 143                  $files2 = list_files( $folder . '/' . $file, $levels - 1);
 144                  if ( $files2 )
 145                      $files = array_merge($files, $files2 );
 146                  else
 147                      $files[] = $folder . '/' . $file . '/';
 148              } else {
 149                  $files[] = $folder . '/' . $file;
 150              }
 151          }
 152      }
 153      @closedir( $dir );
 154      return $files;
 155  }
 156  
 157  /**
 158   * Returns a filename of a Temporary unique file.
 159   * Please note that the calling function must unlink() this itself.
 160   *
 161   * The filename is based off the passed parameter or defaults to the current unix timestamp,
 162   * while the directory can either be passed as well, or by leaving it blank, default to a writable temporary directory.
 163   *
 164   * @since 2.6.0
 165   *
 166   * @param string $filename (optional) Filename to base the Unique file off
 167   * @param string $dir (optional) Directory to store the file in
 168   * @return string a writable filename
 169   */
 170  function wp_tempnam($filename = '', $dir = '') {
 171      if ( empty($dir) )
 172          $dir = get_temp_dir();
 173      $filename = basename($filename);
 174      if ( empty($filename) )
 175          $filename = time();
 176  
 177      $filename = preg_replace('|\..*$|', '.tmp', $filename);
 178      $filename = $dir . wp_unique_filename($dir, $filename);
 179      touch($filename);
 180      return $filename;
 181  }
 182  
 183  /**
 184   * Make sure that the file that was requested to edit, is allowed to be edited
 185   *
 186   * Function will die if if you are not allowed to edit the file
 187   *
 188   * @since 1.5.0
 189   *
 190   * @uses wp_die
 191   * @uses validate_file
 192   * @param string $file file the users is attempting to edit
 193   * @param array $allowed_files Array of allowed files to edit, $file must match an entry exactly
 194   * @return null
 195   */
 196  function validate_file_to_edit( $file, $allowed_files = '' ) {
 197      $code = validate_file( $file, $allowed_files );
 198  
 199      if (!$code )
 200          return $file;
 201  
 202      switch ( $code ) {
 203          case 1 :
 204              wp_die( __('Sorry, can&#8217;t edit files with &#8220;..&#8221; in the name. If you are trying to edit a file in your WordPress home directory, you can just type the name of the file in.' ));
 205  
 206          //case 2 :
 207          //    wp_die( __('Sorry, can&#8217;t call files with their real path.' ));
 208  
 209          case 3 :
 210              wp_die( __('Sorry, that file cannot be edited.' ));
 211      }
 212  }
 213  
 214  /**
 215   * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 216   * and moving the file to the appropriate directory within the uploads directory.
 217   *
 218   * @since 2.0
 219   *
 220   * @uses wp_handle_upload_error
 221   * @uses apply_filters
 222   * @uses is_multisite
 223   * @uses wp_check_filetype_and_ext
 224   * @uses current_user_can
 225   * @uses wp_upload_dir
 226   * @uses wp_unique_filename
 227   * @uses delete_transient
 228   * @param array $file Reference to a single element of $_FILES. Call the function once for each uploaded file.
 229   * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ).
 230   * @param string $time Optional. Time formatted in 'yyyy/mm'.
 231   * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
 232   */
 233  function wp_handle_upload( &$file, $overrides = false, $time = null ) {
 234      // The default error handler.
 235      if ( ! function_exists( 'wp_handle_upload_error' ) ) {
 236  		function wp_handle_upload_error( &$file, $message ) {
 237              return array( 'error'=>$message );
 238          }
 239      }
 240  
 241      $file = apply_filters( 'wp_handle_upload_prefilter', $file );
 242  
 243      // You may define your own function and pass the name in $overrides['upload_error_handler']
 244      $upload_error_handler = 'wp_handle_upload_error';
 245  
 246      // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
 247      if ( isset( $file['error'] ) && !is_numeric( $file['error'] ) && $file['error'] )
 248          return $upload_error_handler( $file, $file['error'] );
 249  
 250      // You may define your own function and pass the name in $overrides['unique_filename_callback']
 251      $unique_filename_callback = null;
 252  
 253      // $_POST['action'] must be set and its value must equal $overrides['action'] or this:
 254      $action = 'wp_handle_upload';
 255  
 256      // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
 257      $upload_error_strings = array( false,
 258          __( "The uploaded file exceeds the upload_max_filesize directive in php.ini." ),
 259          __( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." ),
 260          __( "The uploaded file was only partially uploaded." ),
 261          __( "No file was uploaded." ),
 262          '',
 263          __( "Missing a temporary folder." ),
 264          __( "Failed to write file to disk." ),
 265          __( "File upload stopped by extension." ));
 266  
 267      // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
 268      $test_form = true;
 269      $test_size = true;
 270      $test_upload = true;
 271  
 272      // If you override this, you must provide $ext and $type!!!!
 273      $test_type = true;
 274      $mimes = false;
 275  
 276      // Install user overrides. Did we mention that this voids your warranty?
 277      if ( is_array( $overrides ) )
 278          extract( $overrides, EXTR_OVERWRITE );
 279  
 280      // A correct form post will pass this test.
 281      if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) )
 282          return call_user_func($upload_error_handler, $file, __( 'Invalid form submission.' ));
 283  
 284      // A successful upload will pass this test. It makes no sense to override this one.
 285      if ( $file['error'] > 0 )
 286          return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']] );
 287  
 288      // A non-empty file will pass this test.
 289      if ( $test_size && !($file['size'] > 0 ) ) {
 290          if ( is_multisite() )
 291              $error_msg = __( 'File is empty. Please upload something more substantial.' );
 292          else
 293              $error_msg = __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.' );
 294          return call_user_func($upload_error_handler, $file, $error_msg);
 295      }
 296  
 297      // A properly uploaded file will pass this test. There should be no reason to override this one.
 298      if ( $test_upload && ! @ is_uploaded_file( $file['tmp_name'] ) )
 299          return call_user_func($upload_error_handler, $file, __( 'Specified file failed upload test.' ));
 300  
 301      // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
 302      if ( $test_type ) {
 303          $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes );
 304  
 305          extract( $wp_filetype );
 306  
 307          // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
 308          if ( $proper_filename )
 309              $file['name'] = $proper_filename;
 310  
 311          if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) )
 312              return call_user_func($upload_error_handler, $file, __( 'Sorry, this file type is not permitted for security reasons.' ));
 313  
 314          if ( !$ext )
 315              $ext = ltrim(strrchr($file['name'], '.'), '.');
 316  
 317          if ( !$type )
 318              $type = $file['type'];
 319      } else {
 320          $type = '';
 321      }
 322  
 323      // A writable uploads dir will pass this test. Again, there's no point overriding this one.
 324      if ( ! ( ( $uploads = wp_upload_dir($time) ) && false === $uploads['error'] ) )
 325          return call_user_func($upload_error_handler, $file, $uploads['error'] );
 326  
 327      $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback );
 328  
 329      // Move the file to the uploads dir
 330      $new_file = $uploads['path'] . "/$filename";
 331      if ( false === @ move_uploaded_file( $file['tmp_name'], $new_file ) )
 332          return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path'] ) );
 333  
 334      // Set correct file permissions
 335      $stat = stat( dirname( $new_file ));
 336      $perms = $stat['mode'] & 0000666;
 337      @ chmod( $new_file, $perms );
 338  
 339      // Compute the URL
 340      $url = $uploads['url'] . "/$filename";
 341  
 342      if ( is_multisite() )
 343          delete_transient( 'dirsize_cache' );
 344  
 345      return apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ), 'upload' );
 346  }
 347  
 348  /**
 349   * Handle sideloads, which is the process of retrieving a media item from another server instead of
 350   * a traditional media upload. This process involves sanitizing the filename, checking extensions
 351   * for mime type, and moving the file to the appropriate directory within the uploads directory.
 352   *
 353   * @since 2.6.0
 354   *
 355   * @uses wp_handle_upload_error
 356   * @uses apply_filters
 357   * @uses wp_check_filetype_and_ext
 358   * @uses current_user_can
 359   * @uses wp_upload_dir
 360   * @uses wp_unique_filename
 361   * @param array $file an array similar to that of a PHP $_FILES POST array
 362   * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ).
 363   * @param string $time Optional. Time formatted in 'yyyy/mm'.
 364   * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
 365   */
 366  function wp_handle_sideload( &$file, $overrides = false, $time = null ) {
 367      // The default error handler.
 368      if (! function_exists( 'wp_handle_upload_error' ) ) {
 369  		function wp_handle_upload_error( &$file, $message ) {
 370              return array( 'error'=>$message );
 371          }
 372      }
 373  
 374      // You may define your own function and pass the name in $overrides['upload_error_handler']
 375      $upload_error_handler = 'wp_handle_upload_error';
 376  
 377      // You may define your own function and pass the name in $overrides['unique_filename_callback']
 378      $unique_filename_callback = null;
 379  
 380      // $_POST['action'] must be set and its value must equal $overrides['action'] or this:
 381      $action = 'wp_handle_sideload';
 382  
 383      // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
 384      $upload_error_strings = array( false,
 385          __( "The uploaded file exceeds the <code>upload_max_filesize</code> directive in <code>php.ini</code>." ),
 386          __( "The uploaded file exceeds the <em>MAX_FILE_SIZE</em> directive that was specified in the HTML form." ),
 387          __( "The uploaded file was only partially uploaded." ),
 388          __( "No file was uploaded." ),
 389          '',
 390          __( "Missing a temporary folder." ),
 391          __( "Failed to write file to disk." ),
 392          __( "File upload stopped by extension." ));
 393  
 394      // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
 395      $test_form = true;
 396      $test_size = true;
 397  
 398      // If you override this, you must provide $ext and $type!!!!
 399      $test_type = true;
 400      $mimes = false;
 401  
 402      // Install user overrides. Did we mention that this voids your warranty?
 403      if ( is_array( $overrides ) )
 404          extract( $overrides, EXTR_OVERWRITE );
 405  
 406      // A correct form post will pass this test.
 407      if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) )
 408          return $upload_error_handler( $file, __( 'Invalid form submission.' ));
 409  
 410      // A successful upload will pass this test. It makes no sense to override this one.
 411      if ( ! empty( $file['error'] ) )
 412          return $upload_error_handler( $file, $upload_error_strings[$file['error']] );
 413  
 414      // A non-empty file will pass this test.
 415      if ( $test_size && !(filesize($file['tmp_name']) > 0 ) )
 416          return $upload_error_handler( $file, __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini.' ));
 417  
 418      // A properly uploaded file will pass this test. There should be no reason to override this one.
 419      if (! @ is_file( $file['tmp_name'] ) )
 420          return $upload_error_handler( $file, __( 'Specified file does not exist.' ));
 421  
 422      // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
 423      if ( $test_type ) {
 424          $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes );
 425  
 426          extract( $wp_filetype );
 427  
 428          // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
 429          if ( $proper_filename )
 430              $file['name'] = $proper_filename;
 431  
 432          if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) )
 433              return $upload_error_handler( $file, __( 'Sorry, this file type is not permitted for security reasons.' ));
 434  
 435          if ( !$ext )
 436              $ext = ltrim(strrchr($file['name'], '.'), '.');
 437  
 438          if ( !$type )
 439              $type = $file['type'];
 440      }
 441  
 442      // A writable uploads dir will pass this test. Again, there's no point overriding this one.
 443      if ( ! ( ( $uploads = wp_upload_dir( $time ) ) && false === $uploads['error'] ) )
 444          return $upload_error_handler( $file, $uploads['error'] );
 445  
 446      $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback );
 447  
 448      // Strip the query strings.
 449      $filename = str_replace('?','-', $filename);
 450      $filename = str_replace('&','-', $filename);
 451  
 452      // Move the file to the uploads dir
 453      $new_file = $uploads['path'] . "/$filename";
 454      if ( false === @ rename( $file['tmp_name'], $new_file ) ) {
 455          return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path'] ) );
 456      }
 457  
 458      // Set correct file permissions
 459      $stat = stat( dirname( $new_file ));
 460      $perms = $stat['mode'] & 0000666;
 461      @ chmod( $new_file, $perms );
 462  
 463      // Compute the URL
 464      $url = $uploads['url'] . "/$filename";
 465  
 466      $return = apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ), 'sideload' );
 467  
 468      return $return;
 469  }
 470  
 471  /**
 472   * Downloads a url to a local temporary file using the WordPress HTTP Class.
 473   * Please note, That the calling function must unlink() the file.
 474   *
 475   * @since 2.5.0
 476   *
 477   * @param string $url the URL of the file to download
 478   * @param int $timeout The timeout for the request to download the file default 300 seconds
 479   * @return mixed WP_Error on failure, string Filename on success.
 480   */
 481  function download_url( $url, $timeout = 300 ) {
 482      //WARNING: The file is not automatically deleted, The script must unlink() the file.
 483      if ( ! $url )
 484          return new WP_Error('http_no_url', __('Invalid URL Provided.'));
 485  
 486      $tmpfname = wp_tempnam($url);
 487      if ( ! $tmpfname )
 488          return new WP_Error('http_no_file', __('Could not create Temporary file.'));
 489  
 490      $response = wp_remote_get( $url, array( 'timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname ) );
 491  
 492      if ( is_wp_error( $response ) ) {
 493          unlink( $tmpfname );
 494          return $response;
 495      }
 496  
 497      if ( 200 != wp_remote_retrieve_response_code( $response ) ){
 498          unlink( $tmpfname );
 499          return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
 500      }
 501  
 502      return $tmpfname;
 503  }
 504  
 505  /**
 506   * Unzips a specified ZIP file to a location on the Filesystem via the WordPress Filesystem Abstraction.
 507   * Assumes that WP_Filesystem() has already been called and set up. Does not extract a root-level __MACOSX directory, if present.
 508   *
 509   * Attempts to increase the PHP Memory limit to 256M before uncompressing,
 510   * However, The most memory required shouldn't be much larger than the Archive itself.
 511   *
 512   * @since 2.5.0
 513   *
 514   * @param string $file Full path and filename of zip archive
 515   * @param string $to Full path on the filesystem to extract archive to
 516   * @return mixed WP_Error on failure, True on success
 517   */
 518  function unzip_file($file, $to) {
 519      global $wp_filesystem;
 520  
 521      if ( ! $wp_filesystem || !is_object($wp_filesystem) )
 522          return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
 523  
 524      // Unzip can use a lot of memory, but not this much hopefully
 525      @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
 526  
 527      $needed_dirs = array();
 528      $to = trailingslashit($to);
 529  
 530      // Determine any parent dir's needed (of the upgrade directory)
 531      if ( ! $wp_filesystem->is_dir($to) ) { //Only do parents if no children exist
 532          $path = preg_split('![/\\\]!', untrailingslashit($to));
 533          for ( $i = count($path); $i >= 0; $i-- ) {
 534              if ( empty($path[$i]) )
 535                  continue;
 536  
 537              $dir = implode('/', array_slice($path, 0, $i+1) );
 538              if ( preg_match('!^[a-z]:$!i', $dir) ) // Skip it if it looks like a Windows Drive letter.
 539                  continue;
 540  
 541              if ( ! $wp_filesystem->is_dir($dir) )
 542                  $needed_dirs[] = $dir;
 543              else
 544                  break; // A folder exists, therefor, we dont need the check the levels below this
 545          }
 546      }
 547  
 548      if ( class_exists('ZipArchive') && apply_filters('unzip_file_use_ziparchive', true ) ) {
 549          $result = _unzip_file_ziparchive($file, $to, $needed_dirs);
 550          if ( true === $result ) {
 551              return $result;
 552          } elseif ( is_wp_error($result) ) {
 553              if ( 'incompatible_archive' != $result->get_error_code() )
 554                  return $result;
 555          }
 556      }
 557      // Fall through to PclZip if ZipArchive is not available, or encountered an error opening the file.
 558      return _unzip_file_pclzip($file, $to, $needed_dirs);
 559  }
 560  
 561  /**
 562   * This function should not be called directly, use unzip_file instead. Attempts to unzip an archive using the ZipArchive class.
 563   * Assumes that WP_Filesystem() has already been called and set up.
 564   *
 565   * @since 3.0.0
 566   * @see unzip_file
 567   * @access private
 568   *
 569   * @param string $file Full path and filename of zip archive
 570   * @param string $to Full path on the filesystem to extract archive to
 571   * @param array $needed_dirs A partial list of required folders needed to be created.
 572   * @return mixed WP_Error on failure, True on success
 573   */
 574  function _unzip_file_ziparchive($file, $to, $needed_dirs = array() ) {
 575      global $wp_filesystem;
 576  
 577      $z = new ZipArchive();
 578  
 579      // PHP4-compat - php4 classes can't contain constants
 580      $zopen = $z->open($file, /* ZIPARCHIVE::CHECKCONS */ 4);
 581      if ( true !== $zopen )
 582          return new WP_Error('incompatible_archive', __('Incompatible Archive.'));
 583  
 584      for ( $i = 0; $i < $z->numFiles; $i++ ) {
 585          if ( ! $info = $z->statIndex($i) )
 586              return new WP_Error('stat_failed', __('Could not retrieve file from archive.'));
 587  
 588          if ( '__MACOSX/' === substr($info['name'], 0, 9) ) // Skip the OS X-created __MACOSX directory
 589              continue;
 590  
 591          if ( '/' == substr($info['name'], -1) ) // directory
 592              $needed_dirs[] = $to . untrailingslashit($info['name']);
 593          else
 594              $needed_dirs[] = $to . untrailingslashit(dirname($info['name']));
 595      }
 596  
 597      $needed_dirs = array_unique($needed_dirs);
 598      foreach ( $needed_dirs as $dir ) {
 599          // Check the parent folders of the folders all exist within the creation array.
 600          if ( untrailingslashit($to) == $dir ) // Skip over the working directory, We know this exists (or will exist)
 601              continue;
 602          if ( strpos($dir, $to) === false ) // If the directory is not within the working directory, Skip it
 603              continue;
 604  
 605          $parent_folder = dirname($dir);
 606          while ( !empty($parent_folder) && untrailingslashit($to) != $parent_folder && !in_array($parent_folder, $needed_dirs) ) {
 607              $needed_dirs[] = $parent_folder;
 608              $parent_folder = dirname($parent_folder);
 609          }
 610      }
 611      asort($needed_dirs);
 612  
 613      // Create those directories if need be:
 614      foreach ( $needed_dirs as $_dir ) {
 615          if ( ! $wp_filesystem->mkdir($_dir, FS_CHMOD_DIR) && ! $wp_filesystem->is_dir($_dir) ) // Only check to see if the Dir exists upon creation failure. Less I/O this way.
 616              return new WP_Error('mkdir_failed', __('Could not create directory.'), $_dir);
 617      }
 618      unset($needed_dirs);
 619  
 620      for ( $i = 0; $i < $z->numFiles; $i++ ) {
 621          if ( ! $info = $z->statIndex($i) )
 622              return new WP_Error('stat_failed', __('Could not retrieve file from archive.'));
 623  
 624          if ( '/' == substr($info['name'], -1) ) // directory
 625              continue;
 626  
 627          if ( '__MACOSX/' === substr($info['name'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files
 628              continue;
 629  
 630          $contents = $z->getFromIndex($i);
 631          if ( false === $contents )
 632              return new WP_Error('extract_failed', __('Could not extract file from archive.'), $info['name']);
 633  
 634          if ( ! $wp_filesystem->put_contents( $to . $info['name'], $contents, FS_CHMOD_FILE) )
 635              return new WP_Error('copy_failed', __('Could not copy file.'), $to . $info['name']);
 636      }
 637  
 638      $z->close();
 639  
 640      return true;
 641  }
 642  
 643  /**
 644   * This function should not be called directly, use unzip_file instead. Attempts to unzip an archive using the PclZip library.
 645   * Assumes that WP_Filesystem() has already been called and set up.
 646   *
 647   * @since 3.0.0
 648   * @see unzip_file
 649   * @access private
 650   *
 651   * @param string $file Full path and filename of zip archive
 652   * @param string $to Full path on the filesystem to extract archive to
 653   * @param array $needed_dirs A partial list of required folders needed to be created.
 654   * @return mixed WP_Error on failure, True on success
 655   */
 656  function _unzip_file_pclzip($file, $to, $needed_dirs = array()) {
 657      global $wp_filesystem;
 658  
 659      // See #15789 - PclZip uses string functions on binary data, If it's overloaded with Multibyte safe functions the results are incorrect.
 660      if ( ini_get('mbstring.func_overload') && function_exists('mb_internal_encoding') ) {
 661          $previous_encoding = mb_internal_encoding();
 662          mb_internal_encoding('ISO-8859-1');
 663      }
 664  
 665      require_once (ABSPATH . 'wp-admin/includes/class-pclzip.php');
 666  
 667      $archive = new PclZip($file);
 668  
 669      $archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING);
 670  
 671      if ( isset($previous_encoding) )
 672          mb_internal_encoding($previous_encoding);
 673  
 674      // Is the archive valid?
 675      if ( !is_array($archive_files) )
 676          return new WP_Error('incompatible_archive', __('Incompatible Archive.'), $archive->errorInfo(true));
 677  
 678      if ( 0 == count($archive_files) )
 679          return new WP_Error('empty_archive', __('Empty archive.'));
 680  
 681      // Determine any children directories needed (From within the archive)
 682      foreach ( $archive_files as $file ) {
 683          if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Skip the OS X-created __MACOSX directory
 684              continue;
 685  
 686          $needed_dirs[] = $to . untrailingslashit( $file['folder'] ? $file['filename'] : dirname($file['filename']) );
 687      }
 688  
 689      $needed_dirs = array_unique($needed_dirs);
 690      foreach ( $needed_dirs as $dir ) {
 691          // Check the parent folders of the folders all exist within the creation array.
 692          if ( untrailingslashit($to) == $dir ) // Skip over the working directory, We know this exists (or will exist)
 693              continue;
 694          if ( strpos($dir, $to) === false ) // If the directory is not within the working directory, Skip it
 695              continue;
 696  
 697          $parent_folder = dirname($dir);
 698          while ( !empty($parent_folder) && untrailingslashit($to) != $parent_folder && !in_array($parent_folder, $needed_dirs) ) {
 699              $needed_dirs[] = $parent_folder;
 700              $parent_folder = dirname($parent_folder);
 701          }
 702      }
 703      asort($needed_dirs);
 704  
 705      // Create those directories if need be:
 706      foreach ( $needed_dirs as $_dir ) {
 707          if ( ! $wp_filesystem->mkdir($_dir, FS_CHMOD_DIR) && ! $wp_filesystem->is_dir($_dir) ) // Only check to see if the dir exists upon creation failure. Less I/O this way.
 708              return new WP_Error('mkdir_failed', __('Could not create directory.'), $_dir);
 709      }
 710      unset($needed_dirs);
 711  
 712      // Extract the files from the zip
 713      foreach ( $archive_files as $file ) {
 714          if ( $file['folder'] )
 715              continue;
 716  
 717          if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files
 718              continue;
 719  
 720          if ( ! $wp_filesystem->put_contents( $to . $file['filename'], $file['content'], FS_CHMOD_FILE) )
 721              return new WP_Error('copy_failed', __('Could not copy file.'), $to . $file['filename']);
 722      }
 723      return true;
 724  }
 725  
 726  /**
 727   * Copies a directory from one location to another via the WordPress Filesystem Abstraction.
 728   * Assumes that WP_Filesystem() has already been called and setup.
 729   *
 730   * @since 2.5.0
 731   *
 732   * @param string $from source directory
 733   * @param string $to destination directory
 734   * @param array $skip_list a list of files/folders to skip copying
 735   * @return mixed WP_Error on failure, True on success.
 736   */
 737  function copy_dir($from, $to, $skip_list = array() ) {
 738      global $wp_filesystem;
 739  
 740      $dirlist = $wp_filesystem->dirlist($from);
 741  
 742      $from = trailingslashit($from);
 743      $to = trailingslashit($to);
 744  
 745      $skip_regex = '';
 746      foreach ( (array)$skip_list as $key => $skip_file )
 747          $skip_regex .= preg_quote($skip_file, '!') . '|';
 748  
 749      if ( !empty($skip_regex) )
 750          $skip_regex = '!(' . rtrim($skip_regex, '|') . ')$!i';
 751  
 752      foreach ( (array) $dirlist as $filename => $fileinfo ) {
 753          if ( !empty($skip_regex) )
 754              if ( preg_match($skip_regex, $from . $filename) )
 755                  continue;
 756  
 757          if ( 'f' == $fileinfo['type'] ) {
 758              if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) {
 759                  // If copy failed, chmod file to 0644 and try again.
 760                  $wp_filesystem->chmod($to . $filename, 0644);
 761                  if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) )
 762                      return new WP_Error('copy_failed', __('Could not copy file.'), $to . $filename);
 763              }
 764          } elseif ( 'd' == $fileinfo['type'] ) {
 765              if ( !$wp_filesystem->is_dir($to . $filename) ) {
 766                  if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) )
 767                      return new WP_Error('mkdir_failed', __('Could not create directory.'), $to . $filename);
 768              }
 769              $result = copy_dir($from . $filename, $to . $filename, $skip_list);
 770              if ( is_wp_error($result) )
 771                  return $result;
 772          }
 773      }
 774      return true;
 775  }
 776  
 777  /**
 778   * Initialises and connects the WordPress Filesystem Abstraction classes.
 779   * This function will include the chosen transport and attempt connecting.
 780   *
 781   * Plugins may add extra transports, And force WordPress to use them by returning the filename via the 'filesystem_method_file' filter.
 782   *
 783   * @since 2.5.0
 784   *
 785   * @param array $args (optional) Connection args, These are passed directly to the WP_Filesystem_*() classes.
 786   * @param string $context (optional) Context for get_filesystem_method(), See function declaration for more information.
 787   * @return boolean false on failure, true on success
 788   */
 789  function WP_Filesystem( $args = false, $context = false ) {
 790      global $wp_filesystem;
 791  
 792      require_once (ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
 793  
 794      $method = get_filesystem_method($args, $context);
 795  
 796      if ( ! $method )
 797          return false;
 798  
 799      if ( ! class_exists("WP_Filesystem_$method") ) {
 800          $abstraction_file = apply_filters('filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method);
 801          if ( ! file_exists($abstraction_file) )
 802              return;
 803  
 804          require_once($abstraction_file);
 805      }
 806      $method = "WP_Filesystem_$method";
 807  
 808      $wp_filesystem = new $method($args);
 809  
 810      //Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default.
 811      if ( ! defined('FS_CONNECT_TIMEOUT') )
 812          define('FS_CONNECT_TIMEOUT', 30);
 813      if ( ! defined('FS_TIMEOUT') )
 814          define('FS_TIMEOUT', 30);
 815  
 816      if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() )
 817          return false;
 818  
 819      if ( !$wp_filesystem->connect() )
 820          return false; //There was an error connecting to the server.
 821  
 822      // Set the permission constants if not already set.
 823      if ( ! defined('FS_CHMOD_DIR') )
 824          define('FS_CHMOD_DIR', 0755 );
 825      if ( ! defined('FS_CHMOD_FILE') )
 826          define('FS_CHMOD_FILE', 0644 );
 827  
 828      return true;
 829  }
 830  
 831  /**
 832   * Determines which Filesystem Method to use.
 833   * The priority of the Transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets (Via Sockets class, or fsockopen())
 834   *
 835   * Note that the return value of this function can be overridden in 2 ways
 836   *  - By defining FS_METHOD in your <code>wp-config.php</code> file
 837   *  - By using the filesystem_method filter
 838   * Valid values for these are: 'direct', 'ssh', 'ftpext' or 'ftpsockets'
 839   * Plugins may also define a custom transport handler, See the WP_Filesystem function for more information.
 840   *
 841   * @since 2.5.0
 842   *
 843   * @param array $args Connection details.
 844   * @param string $context Full path to the directory that is tested for being writable.
 845   * @return string The transport to use, see description for valid return values.
 846   */
 847  function get_filesystem_method($args = array(), $context = false) {
 848      $method = defined('FS_METHOD') ? FS_METHOD : false; //Please ensure that this is either 'direct', 'ssh', 'ftpext' or 'ftpsockets'
 849  
 850      if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){
 851          if ( !$context )
 852              $context = WP_CONTENT_DIR;
 853          $context = trailingslashit($context);
 854          $temp_file_name = $context . 'temp-write-test-' . time();
 855          $temp_handle = @fopen($temp_file_name, 'w');
 856          if ( $temp_handle ) {
 857              if ( getmyuid() == @fileowner($temp_file_name) )
 858                  $method = 'direct';
 859              @fclose($temp_handle);
 860              @unlink($temp_file_name);
 861          }
 862       }
 863  
 864      if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2';
 865      if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext';
 866      if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread
 867      return apply_filters('filesystem_method', $method, $args);
 868  }
 869  
 870  /**
 871   * Displays a form to the user to request for their FTP/SSH details in order to connect to the filesystem.
 872   * All chosen/entered details are saved, Excluding the Password.
 873   *
 874   * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) to specify an alternate FTP/SSH port.
 875   *
 876   * Plugins may override this form by returning true|false via the <code>request_filesystem_credentials</code> filter.
 877   *
 878   * @since 2.5.0
 879   *
 880   * @param string $form_post the URL to post the form to
 881   * @param string $type the chosen Filesystem method in use
 882   * @param boolean $error if the current request has failed to connect
 883   * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method()
 884   * @param string $extra_fields Extra POST fields which should be checked for to be included in the post.
 885   * @return boolean False on failure. True on success.
 886   */
 887  function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null) {
 888      $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields );
 889      if ( '' !== $req_cred )
 890          return $req_cred;
 891  
 892      if ( empty($type) )
 893          $type = get_filesystem_method(array(), $context);
 894  
 895      if ( 'direct' == $type )
 896          return true;
 897  
 898      if ( is_null( $extra_fields ) )
 899          $extra_fields = array( 'version', 'locale' );
 900  
 901      $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => ''));
 902  
 903      // If defined, set it to that, Else, If POST'd, set it to that, If not, Set it to whatever it previously was(saved details in option)
 904      $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? stripslashes($_POST['hostname']) : $credentials['hostname']);
 905      $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? stripslashes($_POST['username']) : $credentials['username']);
 906      $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? stripslashes($_POST['password']) : '');
 907  
 908      // Check to see if we are setting the public/private keys for ssh
 909      $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? stripslashes($_POST['public_key']) : '');
 910      $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? stripslashes($_POST['private_key']) : '');
 911  
 912      //sanitize the hostname, Some people might pass in odd-data:
 913      $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off
 914  
 915      if ( strpos($credentials['hostname'], ':') ) {
 916          list( $credentials['hostname'], $credentials['port'] ) = explode(':', $credentials['hostname'], 2);
 917          if ( ! is_numeric($credentials['port']) )
 918              unset($credentials['port']);
 919      } else {
 920          unset($credentials['port']);
 921      }
 922  
 923      if ( (defined('FTP_SSH') && FTP_SSH) || (defined('FS_METHOD') && 'ssh' == FS_METHOD) )
 924          $credentials['connection_type'] = 'ssh';
 925      else if ( (defined('FTP_SSL') && FTP_SSL) && 'ftpext' == $type ) //Only the FTP Extension understands SSL
 926          $credentials['connection_type'] = 'ftps';
 927      else if ( !empty($_POST['connection_type']) )
 928          $credentials['connection_type'] = stripslashes($_POST['connection_type']);
 929      else if ( !isset($credentials['connection_type']) ) //All else fails (And its not defaulted to something else saved), Default to FTP
 930          $credentials['connection_type'] = 'ftp';
 931  
 932      if ( ! $error &&
 933              (
 934                  ( !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) ||
 935                  ( 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']) )
 936              ) ) {
 937          $stored_credentials = $credentials;
 938          if ( !empty($stored_credentials['port']) ) //save port as part of hostname to simplify above code.
 939              $stored_credentials['hostname'] .= ':' . $stored_credentials['port'];
 940  
 941          unset($stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key']);
 942          update_option('ftp_credentials', $stored_credentials);
 943          return $credentials;
 944      }
 945      $hostname = '';
 946      $username = '';
 947      $password = '';
 948      $connection_type = '';
 949      if ( !empty($credentials) )
 950          extract($credentials, EXTR_OVERWRITE);
 951      if ( $error ) {
 952          $error_string = __('<strong>ERROR:</strong> There was an error connecting to the server, Please verify the settings are correct.');
 953          if ( is_wp_error($error) )
 954              $error_string = esc_html( $error->get_error_message() );
 955          echo '<div id="message" class="error"><p>' . $error_string . '</p></div>';
 956      }
 957  
 958      $types = array();
 959      if ( extension_loaded('ftp') || extension_loaded('sockets') || function_exists('fsockopen') )
 960          $types[ 'ftp' ] = __('FTP');
 961      if ( extension_loaded('ftp') ) //Only this supports FTPS
 962          $types[ 'ftps' ] = __('FTPS (SSL)');
 963      if ( extension_loaded('ssh2') && function_exists('stream_get_contents') )
 964          $types[ 'ssh' ] = __('SSH2');
 965  
 966      $types = apply_filters('fs_ftp_connection_types', $types, $credentials, $type, $error, $context);
 967  
 968  ?>
 969  <script type="text/javascript">
 970  <!--
 971  jQuery(function($){
 972      jQuery("#ssh").click(function () {
 973          jQuery("#ssh_keys").show();
 974      });
 975      jQuery("#ftp, #ftps").click(function () {
 976          jQuery("#ssh_keys").hide();
 977      });
 978      jQuery('form input[value=""]:first').focus();
 979  });
 980  -->
 981  </script>
 982  <form action="<?php echo $form_post ?>" method="post">
 983  <div class="wrap">
 984  <?php screen_icon(); ?>
 985  <h2><?php _e('Connection Information') ?></h2>
 986  <p><?php
 987      $label_user = __('Username');
 988      $label_pass = __('Password');
 989      _e('To perform the requested action, WordPress needs to access your web server.');
 990      echo ' ';
 991      if ( ( isset( $types['ftp'] ) || isset( $types['ftps'] ) ) ) {
 992          if ( isset( $types['ssh'] ) ) {
 993              _e('Please enter your FTP or SSH credentials to proceed.');
 994              $label_user = __('FTP/SSH Username');
 995              $label_pass = __('FTP/SSH Password');
 996          } else {
 997              _e('Please enter your FTP credentials to proceed.');
 998              $label_user = __('FTP Username');
 999              $label_pass = __('FTP Password');
1000          }
1001          echo ' ';
1002      }
1003      _e('If you do not remember your credentials, you should contact your web host.');
1004  ?></p>
1005  <table class="form-table">
1006  <tr valign="top">
1007  <th scope="row"><label for="hostname"><?php _e('Hostname') ?></label></th>
1008  <td><input name="hostname" type="text" id="hostname" value="<?php echo esc_attr($hostname); if ( !empty($port) ) echo ":$port"; ?>"<?php disabled( defined('FTP_HOST') ); ?> size="40" /></td>
1009  </tr>
1010  
1011  <tr valign="top">
1012  <th scope="row"><label for="username"><?php echo $label_user; ?></label></th>
1013  <td><input name="username" type="text" id="username" value="<?php echo esc_attr($username) ?>"<?php disabled( defined('FTP_USER') ); ?> size="40" /></td>
1014  </tr>
1015  
1016  <tr valign="top">
1017  <th scope="row"><label for="password"><?php echo $label_pass; ?></label></th>
1018  <td><input name="password" type="password" id="password" value="<?php if ( defined('FTP_PASS') ) echo '*****'; ?>"<?php disabled( defined('FTP_PASS') ); ?> size="40" /></td>
1019  </tr>
1020  
1021  <?php if ( isset($types['ssh']) ) : ?>
1022  <tr id="ssh_keys" valign="top" style="<?php if ( 'ssh' != $connection_type ) echo 'display:none' ?>">
1023  <th scope="row"><?php _e('Authentication Keys') ?>
1024  <div class="key-labels textright">
1025  <label for="public_key"><?php _e('Public Key:') ?></label ><br />
1026  <label for="private_key"><?php _e('Private Key:') ?></label>
1027  </div></th>
1028  <td><br /><input name="public_key" type="text" id="public_key" value="<?php echo esc_attr($public_key) ?>"<?php disabled( defined('FTP_PUBKEY') ); ?> size="40" /><br /><input name="private_key" type="text" id="private_key" value="<?php echo esc_attr($private_key) ?>"<?php disabled( defined('FTP_PRIKEY') ); ?> size="40" />
1029  <div><?php _e('Enter the location on the server where the keys are located. If a passphrase is needed, enter that in the password field above.') ?></div></td>
1030  </tr>
1031  <?php endif; ?>
1032  
1033  <tr valign="top">
1034  <th scope="row"><?php _e('Connection Type') ?></th>
1035  <td>
1036  <fieldset><legend class="screen-reader-text"><span><?php _e('Connection Type') ?></span></legend>
1037  <?php
1038      $disabled = disabled( (defined('FTP_SSL') && FTP_SSL) || (defined('FTP_SSH') && FTP_SSH), true, false );
1039      foreach ( $types as $name => $text ) : ?>
1040      <label for="<?php echo esc_attr($name) ?>">
1041          <input type="radio" name="connection_type" id="<?php echo esc_attr($name) ?>" value="<?php echo esc_attr($name) ?>"<?php checked($name, $connection_type); echo $disabled; ?> />
1042          <?php echo $text ?>
1043      </label>
1044      <?php endforeach; ?>
1045  </fieldset>
1046  </td>
1047  </tr>
1048  </table>
1049  
1050  <?php
1051  foreach ( (array) $extra_fields as $field ) {
1052      if ( isset( $_POST[ $field ] ) )
1053          echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( stripslashes( $_POST[ $field ] ) ) . '" />';
1054  }
1055  submit_button( __( 'Proceed' ), 'button', 'upgrade' );
1056  ?>
1057  </div>
1058  </form>
1059  <?php
1060      return false;
1061  }

title

Description

title

Description

title

Description

title

title

Body