Changeset 562699
- Timestamp:
- 06/22/2012 09:14:28 PM (13 years ago)
- Location:
- backup/trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
backup/trunk/backup.php
r558116 r562699 2 2 /* 3 3 Plugin Name: Backup 4 Version: 2.0 4 Version: 2.0.1 5 5 Plugin URI: http://hel.io/wordpress/backup/ 6 6 Description: Backup your WordPress website to Google Drive. … … 100 100 * @access private 101 101 */ 102 private $ docs;102 private $gdocs; 103 103 104 104 /** … … 219 219 'display' => __('Weekly', $this->text_domain) 220 220 ), 221 'mont ly' => array(221 'monthly' => array( 222 222 'interval' => 2592000, 223 223 'display' => __('Monthly', $this->text_domain) … … 791 791 public function do_backup() { 792 792 // Check if the backup folder is writable 793 if ( !( is_dir($this->local_folder) &&@is_writable($this->local_folder) ) ) {793 if ( !( @is_writable($this->local_folder) ) ) { 794 794 $this->log('ERROR', "The directory '" . $this->local_folder . "' does not exist or it is not writable."); 795 exit; 795 796 } 796 797 … … 807 808 // Create database dump sql file. 808 809 if ( in_array('database', $this->options['source_list']) ) { 809 $this->log('NOTICE', 'Attempting to dump database to ' . $this->dump_file);810 $this->log('NOTICE', "Attempting to dump database to '" . $this->dump_file . "'."); 810 811 $dump_time = db_dump($this->dump_file); 811 812 … … 830 831 for ( $i = 0; $i < $count; $i++ ) 831 832 for ( $j = 0; $j < $count; $j++ ) 832 if ( $j != $i && isset($sources[$i]) && isset($sources[$j]) && is_subdir($sources[$j], $sources[$i]) ) 833 if ( $j != $i && isset($sources[$i]) && isset($sources[$j]) && 834 is_subdir($sources[$j], $sources[$i]) && $this->sources['database']['path'] != $sources[$j] ) 833 835 unset($sources[$j]); 834 836 835 837 // Create archive from all enabled sources. 836 $this->log('NOTICE', 'Attempting to create archive ' . $file_path);838 $this->log('NOTICE', "Attempting to create archive '" . $file_path . "'."); 837 839 $zip_time = zip($sources, $file_path, $exclude); 838 840 … … 842 844 } 843 845 844 $this->log('NOTICE', 'Archive created successfully in ' . round($zip_time, 2) . ' seconds. Archive file size is ' . size_format( filesize( $file_path ) ) ) . '.';846 $this->log('NOTICE', 'Archive created successfully in ' . round($zip_time, 2) . ' seconds. Archive file size is ' . size_format( filesize( $file_path ) ) . '.'); 845 847 delete_path($this->dump_file); 846 848 … … 858 860 $this->gdocs->set_option('time_limit', $this->options['time_limit']); 859 861 860 $this->log('NOTICE', 'Attempting to upload archive to Google Drive ');862 $this->log('NOTICE', 'Attempting to upload archive to Google Drive.'); 861 863 $id = $this->gdocs->upload_file($file_path, $file_name, $this->options['drive_folder']); 862 864 if ( is_wp_error($id) ) { 863 $this->log_wp_error($id);864 865 $err = $id->get_error_message('resumable'); 865 if ( ! empty($err) ) // If we are here it means we have a chance at resuming the download so schedule resume. 866 if ( ! empty($err) ) { // If we are here it means we have a chance at resuming the download so schedule resume. 867 $this->log("WARNING", $err . ' The upload speed was around ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.'); 866 868 wp_schedule_single_event($this->time, 'backup_resume'); 869 } 870 else { 871 $this->log_wp_error($id); 872 delete_path( $file_path ); 873 } 867 874 } 868 875 else { 869 $this->log('NOTICE', 'Archive ' . $file_name . ' uploaded to Google Drive in ' . round($this->gdocs->time_taken(), 2) . ' seconds ');876 $this->log('NOTICE', 'Archive ' . $file_name . ' uploaded to Google Drive in ' . round($this->gdocs->time_taken(), 2) . ' seconds at an upload speed of ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.'); 870 877 $this->options['local_files'][] = $file_path; 871 878 $this->options['drive_files'][] = $id; … … 899 906 */ 900 907 public function backup_resume() { 901 // Check if the backup folder is writable.902 if ( !( is_dir($this->local_folder) && @is_writable($this->local_folder) ) ) {903 $this->log('ERROR', "The directory '" . $this->local_folder . "' does not exist or it is not writable.");904 }905 908 $access_token = $this->goauth->get_access_token(); 906 if ( is_wp_error($access_token) ) 909 if ( is_wp_error($access_token) ) { 907 910 $this->log_wp_error($access_token); 911 exit; 912 } 913 914 // We need an instance of GDocs here to talk to the Google Documents List API. 915 if ( ! is_gdocs($this->gdocs) ) 916 $this->gdocs = new GDocs($access_token); 917 918 $file = $this->gdocs->get_resume_item(); 919 if ( !$file ) { 920 $this->log("WARNING", "There is no upload to resume."); 921 exit; 922 } 923 924 $this->gdocs->set_option('chunk_size', $this->options['chunk_size']); 925 $this->gdocs->set_option('time_limit', $this->options['time_limit']); 926 927 $this->log('NOTICE', 'Resuming upload of ' . $file['title'] . '.'); 928 $id = $this->gdocs->resume_upload(); 929 if ( is_wp_error($id) ) { 930 $err = $id->get_error_message('resumable'); 931 if ( ! empty($err) ) { 932 $this->log("WARNING", $err . ' The upload speed was around ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.'); 933 wp_schedule_single_event($this->time, 'backup_resume'); 934 } 935 else { 936 $this->log_wp_error($id); 937 delete_path( $file['path'] ); 938 } 939 } 908 940 else { 909 // We need an instance of GDocs here to talk to the Google Documents List API. 910 if ( ! is_gdocs($this->gdocs) ) 911 $this->gdocs = new GDocs($access_token); 912 $file = $this->gdocs->get_resume_item(); 913 if ( $file ) 914 $this->log('NOTICE', 'Resuming upload of ' . $file['title'] . '.'); 915 $id = $this->gdocs->resume_upload(); 916 if ( is_wp_error($id) ) { 917 $this->log_wp_error($id); 918 $err = $id->get_error_message('resumable'); 919 if ( ! empty($err) ) 920 wp_schedule_single_event($this->time, 'backup_resume'); 921 } 922 else { 923 $this->log('NOTICE', 'The archive was uploaded successfully.'); 924 $this->options['drive_files'][] = $id; 925 $this->options['last_backup'] = substr($file['title'], 0, strpos($file['title'], '.')); // take the time from the title 926 // Update quotas if uploading to Google Drive was successful. 927 $this->update_quota(); 928 $this->purge_drive_files(); 929 delete_path($file['path']); 930 // Updating options in the database. 931 update_option('backup_options', $this->options); 932 } 933 } 941 $this->log('NOTICE', 'The archive was uploaded successfully. The upload speed was around ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.'); 942 $this->options['local_files'][] = $file['path']; 943 $this->options['drive_files'][] = $id; 944 $this->options['last_backup'] = substr($file['title'], 0, strpos($file['title'], '.')); // take the time from the title 945 // Update quotas if uploading to Google Drive was successful. 946 $this->update_quota(); 947 $this->purge_local_files(); 948 $this->purge_drive_files(); 949 // Updating options in the database. 950 update_option('backup_options', $this->options); 951 } 934 952 } 935 953 -
backup/trunk/class-gdocs.php
r558116 r562699 61 61 /** 62 62 * Stores feeds to avoid requesting them again for successive use. 63 * 63 64 * @var array 65 * @access private 64 66 */ 65 67 private $cache = array(); 68 69 /** 70 * Stores the handle of the file open for uploading. 71 * 72 * @var resource 73 * @access private 74 */ 75 private $file_handle; 66 76 67 77 /** … … 103 113 */ 104 114 private $max_resume_attempts; 115 116 /** 117 * This is true if a failed upload is resumable. 118 * 119 * @var boolean 120 */ 121 private $resumable; 105 122 106 123 /** … … 132 149 $this->time_limit = 120; // 2 minutes 133 150 $this->max_resume_attempts = 5; 151 $this->resumable = false; 134 152 $this->resume_list = get_option( 'gdocs_resume' ); 135 153 $this->timer = array( … … 339 357 public function upload_file( $file, $title, $parent = '', $type = '' ) { 340 358 341 if ( ! @is_ file($file) )342 return new WP_Error('not_file', "The path '" . $file . "' does not point to a file.");359 if ( ! @is_readable($file) ) 360 return new WP_Error('not_file', "The path '" . $file . "' does not point to a readable file."); 343 361 344 362 // If a mime type wasn't passed try to guess it from the extension based on the WordPress allowed mime types … … 383 401 update_option('gdocs_resume', $this->resume_list); 384 402 385 // Start timer 403 // Start timer. 386 404 $this->timer['start'] = microtime( true ); 387 405 388 // Set time limit 406 // Set time limit. 389 407 set_time_limit($this->time_limit); 408 409 // Open file for reading. 410 if ( !$this->file_handle = fopen( $file, "rb" ) ) 411 return new WP_Error( 'open_error', "Could not open file '" . $file . "' for reading." ); 390 412 391 413 return $this->upload_chunks( $file, 0 ); … … 403 425 if( !$id ) 404 426 return new WP_Error("no_items", "There are no uploads that need to be resumed."); 405 if ( ! @is_ file($this->resume_list[$id]['path']) ) {427 if ( ! @is_readable($this->resume_list[$id]['path']) ) { 406 428 unset($this->resume_list[$id]); 407 429 update_option('gdocs_resume', $this->resume_list); 408 return new WP_Error('not_file', "The path '" . $this->resume_list[$id]['path'] . "' does not point to a file. Upload has been canceled.");430 return new WP_Error('not_file', "The path '" . $this->resume_list[$id]['path'] . "' does not point to a readable file. Upload has been canceled."); 409 431 } 410 432 … … 416 438 $headers = array( 'Content-Range' => 'bytes */' . $this->resume_list[$id]['size'] ); 417 439 $result = $this->request( $this->resume_list[$id]['location'], 'PUT', $headers ); 418 if( is_wp_error( $result ) ) 440 if( is_wp_error( $result ) ) { 441 $this->resumable = true; 419 442 return $result; 420 if ( $result['response']['code'] != '308' ) 443 } 444 if ( $result['response']['code'] != '308' ) { 445 $this->resumable = true; 421 446 return new WP_Error('bad_response', "Received response code '" . $result['response']['code'] . " " . $result['response']['message'] . "' while trying to resume the upload of file '" . $this->resume_list[$id]['title'] . "'."); 447 } 422 448 if( isset( $result['headers']['location'] ) ) 423 449 $this->resume_list[$id]['location'] = $result['headers']['location']; … … 429 455 // Set time limit 430 456 set_time_limit($this->time_limit); 457 458 // Open file for reading. 459 if ( $this->file_handle = fopen( $this->resume_list[$id]['path'], "rb" ) ) 460 return new WP_Error( 'open_error', "Could not open file '" . $this->resume_list[$id]['path'] . "' for reading." ); 431 461 432 462 return $this->upload_chunks($id, $pointer); … … 459 489 */ 460 490 public function get_resume_item() { 461 return $this->resume_list[$this->get_resume_item_id()]; 491 if ( $id = $this->get_resume_item_id() ) 492 return $this->resume_list[$id]; 493 return false; 462 494 } 463 495 … … 472 504 private function upload_chunks( $id, $pointer ) { 473 505 $cycle_start = microtime(true); 474 $chunk = @file_get_contents( $this->resume_list[$id]['path'], false, NULL, $pointer, $this->chunk_size ); 506 fseek( $this->file_handle, $pointer ); 507 $chunk = @fread( $this->file_handle, $this->chunk_size ); 475 508 if ( $chunk === false ) 476 509 return new WP_Error( 'read_error', "Failed to read from file '" . $this->resume_list[$id]['path'] . "'." ); … … 497 530 $this->resume_list[$id]['used'] = false; 498 531 update_option('gdocs_resume', $this->resume_list); 499 return new WP_Error('resumable', "The upload process timed out but can be resumed."); 532 $this->resumable = true; 533 return new WP_Error('timeout', "The upload process timed out but can be resumed."); 500 534 } 501 535 else { … … 505 539 } 506 540 if ( $result['response']['code'] == '201' ) { 541 fclose( $this->file_handle ); 507 542 $feed = @simplexml_load_string( $result['body'] ); 508 543 if ( $feed === false ) … … 521 556 522 557 // If we got to this point it means the upload wasn't successful. 558 fclose( $this->file_handle ); 523 559 524 560 // Give up if we tried to resume too many times … … 527 563 unset( $this->resume_list[$id] ); 528 564 update_option( 'gdocs_resume', $this->resume_list ); 529 return new WP_Error( ' fail', "The upload of file '" . $temp['path'] . "' failed after trying " . $temp['attempt'] . " times." );565 return new WP_Error( 'permanent_fail', "The upload of file '" . $temp['path'] . "' failed after trying " . $temp['attempt'] . " times." ); 530 566 } 531 567 … … 533 569 $this->resume_list[$id]['used'] = false; 534 570 update_option( 'gdocs_resume', $this->resume_list ); 535 return new WP_Error( 'resumable', "Received response code '" . $result['response']['code'] . " " . $result['response']['message'] . "' while trying to upload a chunk of file '" . $this->resume_list[$id]['title'] . "'. The upload might be resumable." ); 571 $this->resumable = true; 572 return new WP_Error( 'bad_response', "Received response code '" . $result['response']['code'] . " " . $result['response']['message'] . "' while trying to upload a chunk of file '" . $this->resume_list[$id]['title'] . "'. The upload might be resumable." ); 573 } 574 575 /** 576 * Get the upload speed recorded on the last upload performed. 577 * 578 * @access public 579 * @return mixed Returns the upload speed in bytes/second or FALSE. 580 */ 581 public function get_upload_speed() { 582 if ( isset( $this->timer['cycle'] ) ) 583 return $this->chunk_size / $this->timer['cycle']; 584 return false; 585 } 586 587 /** 588 * Find out if a failed upload is resumable. 589 * 590 * @access public 591 * @return boolean Returns TRUE if a failed upload is resumable, FALSE otherwise. 592 */ 593 public function is_resumable() { 594 return $this->resumable; 536 595 } 537 596 … … 539 598 * Checks if the script is nearing max execution time. 540 599 * 600 * @access private 541 601 * @return boolean Returns TRUE if nearing max execution time, FALSE otherwise. 542 602 */ … … 548 608 549 609 /** 550 * Returns the time taken for an upload to complete 551 * 552 * @return float The number of seconds accurate to the microsecond it took for the upload to complete 610 * Returns the time taken for an upload to complete. 611 * 612 * @access public 613 * @return mixed Returns a float number of seconds if an upload has been completed, FALSE otherwise. 553 614 */ 554 615 public function time_taken() { 555 return $this->timer['delta']; 616 if ( isset( $this->timer['delta'] ) ) 617 return $this->timer['delta']; 618 return false; 556 619 } 557 620 } -
backup/trunk/functions.php
r558116 r562699 142 142 143 143 foreach ( $sources as $source ) 144 if ( @is_dir($source) ) { 145 $files = directory_list($source, true, $exclude); 146 foreach ( $files as $file ) 147 if ( @is_dir($file) ) 148 $zip->addEmptyDir(str_replace(parent_dir($source) . '/', '', $file . '/')); 149 elseif ( @is_file($file) ) 150 $zip->addFile($file, str_replace(parent_dir($source) . '/', '', $file)); 151 } 152 elseif ( @is_file($source) ) 153 $zip->addFile($source, basename($source)); 144 if ( @is_readable($source) ) 145 if ( @is_dir($source) ) { 146 $files = directory_list($source, true, $exclude); 147 foreach ( $files as $file ) 148 if ( @is_dir($file) && @is_readable($file) ) 149 $zip->addEmptyDir(str_replace(parent_dir($source) . '/', '', $file . '/')); 150 elseif ( @is_file($file) && @is_readable($file) ) 151 $zip->addFile($file, str_replace(parent_dir($source) . '/', '', $file)); 152 } 153 elseif ( @is_file($source) ) 154 $zip->addFile($source, basename($source)); 154 155 155 156 $zip_result = $zip->close(); … … 176 177 $zip = new PclZip($destination); 177 178 foreach ( $sources as $source ) 178 if ( @is_dir($source) ) { 179 $files = directory_list($source, true, $exclude); 180 $res = $zip->add($files, PCLZIP_OPT_REMOVE_PATH, parent_dir($source)); 181 if ( 0 == $res ) 182 return new WP_Error('pclzip', $zip->errorInfo(true)); 183 } 184 elseif ( @is_file($source) ) { 185 $res = $zip->add($source, parent_dir($source)); 186 if ( 0 == $res ) 187 return new WP_Error('pclzip', $zip->errorInfo(true)); 188 } 179 if ( @is_readable($source) ) 180 if ( @is_dir($source) ) { 181 $files = directory_list($source, true, $exclude); 182 $res = $zip->add($files, PCLZIP_OPT_REMOVE_PATH, parent_dir($source)); 183 if ( 0 == $res ) 184 return new WP_Error('pclzip', $zip->errorInfo(true)); 185 } 186 elseif ( @is_file($source) ) { 187 $res = $zip->add($source, PCLZIP_OPT_REMOVE_PATH, parent_dir($source)); 188 if ( 0 == $res ) 189 return new WP_Error('pclzip', $zip->errorInfo(true)); 190 } 189 191 return true; 190 192 } -
backup/trunk/readme.txt
r558121 r562699 47 47 == Changelog == 48 48 49 = 2.0.1 = 50 * Fixed database dump not getting added to the backup archive in some circumstances. 51 * Fixed not setting the time limit and chunk size when resuming uploads. 52 * Fixed local backups not being deleted after a failed upload. 53 * Fixed some bugs in the GDocs class and optimized chunk reading. 54 * Now logging upload speeds. 55 * Other minor bug fixes. 56 49 57 = 2.0 = 50 58 * Rewrote 95% of the plugin to make it more compatible with older PHP versions, more portable and cleaner. It now uses classes and functions already found in WordPress where possible.
Note: See TracChangeset
for help on using the changeset viewer.