[ Root ] [ Search ] [ Index ]

PHP Cross Reference of WordPress 3.0

Provided by Yoast

title

Body

[close]

/wp-admin/includes/ -> file.php (source)

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


Generated: Thu Oct 14 05:11:12 2010 Cross-referenced by PHPXref 0.7