[ Index ]

PHP Cross Reference of WordPress

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


Generated: Fri May 25 03:56:23 2012 Hosted by follow the white rabbit.