PATH:
home
/
thebhoeo
/
.trash
/
backwpup
/
inc
<?php class BackWPup_Destination_Ftp extends BackWPup_Destinations { /** * Service name * * @var string */ private const SERVICE_NAME = 'FTP'; /** * SFTP service name. * * @var string */ private const SFTP_SERVICE_NAME = 'SFTP'; /** * Returns default FTP options. * * @return array<string, mixed> Default options. */ public function option_defaults(): array { return [ 'ftphost' => '', 'ftphostport' => 21, 'ftptimeout' => 90, 'ftpuser' => '', 'ftppass' => '', 'ftpdir' => trailingslashit( sanitize_title_with_dashes( get_bloginfo( 'name' ) ) ), 'ftpmaxbackups' => 15, 'ftppasv' => true, 'ftpssl' => false, 'ftpssh' => false, 'ftpsshprivkey' => '', ]; } /** * {@inheritDoc} * * @param int|array $id * * @return void * * @phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ public function edit_form_post_save( $id ): void { $jobids = (array) $id; $_POST['ftphost'] = str_replace( [ 'http://', 'ftp://' ], '', sanitize_text_field( $_POST['ftphost'] ) ); if ( ! empty( $_POST['ftpdir'] ) ) { $_POST['ftpdir'] = trailingslashit( str_replace( '//', '/', str_replace( '\\', '/', trim( sanitize_text_field( $_POST['ftpdir'] ) ) ) ) ); } foreach ( $jobids as $id ) { BackWPup_Option::update( $id, 'ftphost', $_POST['ftphost'] ?? '' ); BackWPup_Option::update( $id, 'ftphostport', ! empty( $_POST['ftphostport'] ) ? absint( $_POST['ftphostport'] ) : 21 ); BackWPup_Option::update( $id, 'ftptimeout', ! empty( $_POST['ftptimeout'] ) ? absint( $_POST['ftptimeout'] ) : 90 ); BackWPup_Option::update( $id, 'ftpuser', sanitize_text_field( $_POST['ftpuser'] ) ); BackWPup_Option::update( $id, 'ftppass', BackWPup_Encryption::encrypt( $_POST['ftppass'] ) ); BackWPup_Option::update( $id, 'ftpdir', $_POST['ftpdir'] ); BackWPup_Option::update( $id, 'ftpmaxbackups', isset( $_POST['ftpmaxbackups'] ) && is_numeric( $_POST['ftpmaxbackups'] ) ? absint( $_POST['ftpmaxbackups'] ) : $this->option_defaults()['ftpmaxbackups'] ); if ( function_exists( 'ftp_ssl_connect' ) ) { BackWPup_Option::update( $id, 'ftpssl', ! empty( $_POST['ftpssl'] ) ); } else { BackWPup_Option::update( $id, 'ftpssl', false ); } if ( class_exists( phpseclib3\Net\SFTP::class ) ) { BackWPup_Option::update( $id, 'ftpssh', ! empty( $_POST['ftpssh'] ) ); } else { BackWPup_Option::update( $id, 'ftpssh', false ); } BackWPup_Option::update( $id, 'ftppasv', ! empty( $_POST['ftppasv'] ) ); if ( ! empty( $_POST['ftpsshprivkey'] ) ) { BackWPup_Option::update( $id, 'ftpsshprivkey', BackWPup_Encryption::encrypt( wp_unslash( trim( $_POST['ftpsshprivkey'] ) ) ) ); } } } /** * {@inheritDoc} * * @param string $jobdest Job destination identifier. * @param string $backupfile Backup file name. * * @return void */ public function file_delete( string $jobdest, string $backupfile ): void { $files = $this->file_get_list( $jobdest ); [$jobid, $dest] = explode( '_', $jobdest ); $job_options = (object) BackWPup_Option::get_job( $jobid ); if ( ! empty( $job_options->ftpssh ) && BackWPup::is_pro() ) { $ftp = new BackWPup_Pro_Destination_Ftp_Type_Sftp(); } else { $ftp = new BackWPup_Destination_Ftp_Type_Ftp(); } $deleted_files = []; try { $ftp->connect( $job_options->ftpuser, BackWPup_Encryption::decrypt( $job_options->ftppass ), $job_options->ftphost, [ 'port' => $job_options->ftphostport, 'timeout' => $job_options->ftptimeout, 'ssl' => ! empty( $job_options->ftpssl ), 'pasv' => ! empty( $job_options->ftppasv ), 'privkey' => ! empty( $job_options->ftpsshprivkey ) ? BackWPup_Encryption::decrypt( $job_options->ftpsshprivkey ) : '', ] ); $ftp->delete( $backupfile ); foreach ( $files as $key => $file ) { if ( is_array( $file ) && $file['file'] === $backupfile ) { unset( $files[ $key ] ); } } $deleted_files[] = $backupfile; } catch ( \Exception $e ) { BackWPup_Admin::message( 'FTP: ' . $e->getMessage(), true ); } $this->remove_file_history_from_database( $deleted_files, 'FTP' ); set_site_transient( 'backwpup_' . strtolower( $jobdest ), $files, YEAR_IN_SECONDS ); } /** * Upload the backup archive to FTP. * * @param BackWPup_Job $job_object Job object. * * @return bool True on success, false on failure. */ public function job_run_archive( BackWPup_Job $job_object ): bool { $job_object->substeps_todo = 2 + $job_object->backup_filesize; if ( $job_object->steps_data[ $job_object->step_working ]['SAVE_STEP_TRY'] !== $job_object->steps_data[ $job_object->step_working ]['STEP_TRY'] ) { $job_object->log( sprintf( // translators: %d: try number. __( '%d. Try to send backup file to an FTP server …', 'backwpup' ), $job_object->steps_data[ $job_object->step_working ]['STEP_TRY'] ) ); } if ( ! empty( $job_object->job['ftpssh'] ) && BackWPup::is_pro() ) { $ftp = new BackWPup_Pro_Destination_Ftp_Type_Sftp( [ $job_object, 'log' ] ); } else { $ftp = new BackWPup_Destination_Ftp_Type_Ftp( [ $job_object, 'log' ] ); } try { $connected = $ftp->connect( $job_object->job['ftpuser'], BackWPup_Encryption::decrypt( $job_object->job['ftppass'] ), $job_object->job['ftphost'], [ 'port' => $job_object->job['ftphostport'], 'timeout' => $job_object->job['ftptimeout'], 'ssl' => ! empty( $job_object->job['ftpssl'] ), 'pasv' => ! empty( $job_object->job['ftppasv'] ), 'privkey' => ! empty( $job_object->job['ftpsshprivkey'] ) ? BackWPup_Encryption::decrypt( $job_object->job['ftpsshprivkey'] ) : '', ] ); if ( ! $connected ) { $ftp->disconnect(); return false; } $current_ftp_dir = trailingslashit( $ftp->chdir( $job_object->job['ftpdir'] ) ); if ( ! $job_object->substeps_done ) { $job_object->log( // translators: %s: current FTP folder. sprintf( __( 'FTP current folder is: %s', 'backwpup' ), $current_ftp_dir ) ); } // upload backup file. $job_object->substeps_done = $ftp->size( $current_ftp_dir . $job_object->backup_file ); if ( $job_object->substeps_done < $job_object->backup_filesize ) { $job_object->log( __( 'Starting upload to FTP  …', 'backwpup' ) ); // get file size to resume upload and check if appending works. if ( ! $ftp->supports_appending() ) { $job_object->substeps_done = 0; $job_max_execution_time = get_site_option( 'backwpup_cfg_jobmaxexecutiontime' ); if ( $job_max_execution_time ) { $job_object->log( __( 'Looks like the FTP Server do not support upload files in chunks. Try to upload it at once without restarts.', 'backwpup' ), E_USER_WARNING ); } } $fp = fopen( $job_object->backup_folder . $job_object->backup_file, 'rb' ); //phpcs:ignore fseek( $fp, $job_object->substeps_done ); $continue = $ftp->upload( $current_ftp_dir . $job_object->backup_file, $fp ); $job_object->substeps_done = ftell( $fp ); while ( $continue ) { $job_object->update_working_data(); if ( $ftp->supports_appending() ) { $job_object->do_restart_time(); } $continue = $ftp->upload( $current_ftp_dir . $job_object->backup_file, $fp ); $job_object->substeps_done = ftell( $fp ); } fclose( $fp ); //phpcs:ignore // check backup file size. if ( $job_object->backup_filesize !== $job_object->substeps_done ) { $job_object->log( __( 'Backup not correctly transferred to FTP server! Filesize not match.', 'backwpup' ), E_USER_ERROR ); return false; } $job_object->substeps_done = $job_object->backup_filesize + 1; $job_object->log( sprintf( // translators: %s: backup file name. __( 'Backup transferred to FTP server: %s', 'backwpup' ), $current_ftp_dir . $job_object->backup_file ) ); if ( ! empty( $job_object->job['jobid'] ) ) { BackWPup_Option::update( $job_object->job['jobid'], 'lastbackupdownloadurl', network_admin_url( 'admin.php?page=backwpupbackups&action=downloadftp&file=' . $current_ftp_dir . $job_object->backup_file . '&local_file=' . $job_object->backup_file . '&jobid=' . $job_object->job['jobid'] ) ); } } // get list of backups on FTP server. $job_object->do_restart_time(); $backup_file_list = $ftp->list_files( $current_ftp_dir ); foreach ( $backup_file_list as $key => $file ) { if ( ! $this->is_backup_archive( $file['file'] ) || ! $this->is_backup_owned_by_job( $file['file'], $job_object->job['jobid'] ) ) { unset( $backup_file_list[ $key ] ); } else { $backup_file_list[ $key ]['folder'] = $ftp->connection_url . '/' . ltrim( $file['file'], '/' ); $backup_file_list[ $key ]['downloadurl'] = network_admin_url( 'admin.php?page=backwpupbackups&action=downloadftp&file=' . $file['file'] . '&local_file=' . $file['filename'] . '&jobid=' . $job_object->job['jobid'] ); } } // Delete old backups. if ( $backup_file_list && ! empty( $job_object->job['ftpmaxbackups'] ) && $job_object->job['ftpmaxbackups'] > 0 && count( $backup_file_list ) > $job_object->job['ftpmaxbackups'] ) { ksort( $backup_file_list ); $backups_to_delete = array_slice( $backup_file_list, 0, count( $backup_file_list ) - $job_object->job['ftpmaxbackups'] ); if ( $backups_to_delete ) { $deleted_files = []; foreach ( $backups_to_delete as $file ) { if ( $ftp->delete( $file['file'] ) ) { foreach ( $backup_file_list as $index => $file_data ) { if ( $file_data === $file ) { unset( $backup_file_list[ $index ] ); } } $deleted_files[] = $file['file']; } else { $job_object->log( sprintf( // translators: %s: file name. __( 'Cannot delete "%s" on FTP server!', 'backwpup' ), $job_object->job['ftpdir'] . $file ), E_USER_ERROR ); } } if ( count( $deleted_files ) > 0 ) { $job_object->log( sprintf( // translators: %d: number of deleted files. _n( 'One file deleted on FTP server', //phpcs:ignore '%d files deleted on FTP server', count( $deleted_files ), 'backwpup' ), count( $deleted_files ) ) ); } $this->remove_file_history_from_database( $deleted_files, 'FTP' ); } } set_site_transient( 'backwpup_' . $job_object->job['jobid'] . '_ftp', $backup_file_list, YEAR_IN_SECONDS ); ++$job_object->substeps_done; $ftp->disconnect(); } catch ( Exception $e ) { $context = $this->error_context( $e->getMessage(), ! empty( $job_object->job['ftpssh'] ) && BackWPup::is_pro() ? 'SFTP' : 'FTP' ); $job_object->log( /* translators: %s: FTP error message. */ sprintf( esc_html__( 'FTP server error: %s', 'backwpup' ), $e->getMessage() ), E_USER_ERROR, $e->getFile(), $e->getLine(), $context ); $ftp->disconnect(); if ( $fp && is_resource( $fp ) ) { fclose( $fp ); //phpcs:ignore } return false; } return true; } /** * Test if the job can run. * * @param array $job_settings * @param bool $test_connection Should test live connectivity. * @return boolean */ public function can_run( array $job_settings, bool $test_connection = true ): bool { if ( empty( $job_settings['ftphost'] ) ) { return false; } if ( empty( $job_settings['ftpuser'] ) ) { return false; } if ( ! $test_connection ) { return true; } if ( ! empty( $job_settings['ftpssh'] ) && BackWPup::is_pro() ) { $ftp = new BackWPup_Pro_Destination_Ftp_Type_Sftp(); } else { $ftp = new BackWPup_Destination_Ftp_Type_Ftp(); } try { $login = $ftp->connect( $job_settings['ftpuser'], BackWPup_Encryption::decrypt( $job_settings['ftppass'] ), $job_settings['ftphost'], [ 'port' => $job_settings['ftphostport'], 'timeout' => $job_settings['ftptimeout'], 'ssl' => ! empty( $job_settings['ftpssl'] ), 'pasv' => ! empty( $job_settings['ftppasv'] ), 'privkey' => ! empty( $job_settings['ftpsshprivkey'] ) ? BackWPup_Encryption::decrypt( $job_settings['ftpsshprivkey'] ) : '', ] ); if ( ! $login ) { $ftp->disconnect(); return false; } $ftp->disconnect(); return true; } catch ( Exception $e ) { $ftp->disconnect(); return false; } } /** * Get service name */ public function get_service_name(): string { return self::SERVICE_NAME; } /** * Build error context for FTP errors. * * @param string $message FTP or SFTP error message. * @param string $protocol Protocol identifier. * @return array */ private function error_context( string $message, string $protocol = 'FTP' ): array { if ( 'SFTP' === strtoupper( $protocol ) ) { $mapper = new \WPMedia\BackWPup\Backup\FailureContext\Sftp\SftpFailureContextMapper(); } else { $mapper = new \WPMedia\BackWPup\Backup\FailureContext\Ftp\FtpFailureContextMapper(); } return $mapper->map( $message ); } }
[-] class-system-tests-runner.php
[edit]
[-] class-jobtype-dbdump.php
[edit]
[-] class-destination-rsc.php
[edit]
[-] class-encryption.php
[edit]
[-] class-destination-downloader-factory.php
[edit]
[-] class-destination-downloader-interface.php
[edit]
[-] class-destination-ftp-type-ftp.php
[edit]
[-] class-path-fixer.php
[edit]
[-] class-message-box.php
[edit]
[-] class-destination-dropbox-api.php
[edit]
[-] class-option.php
[edit]
[-] class-destination-dropbox-api-request-exception.php
[edit]
[-] class-page-about.php
[edit]
[-] class-migrate.php
[edit]
[-] class-system-requirements.php
[edit]
[-] class-adminbar.php
[edit]
[-] class-msazure-destination-configuration.php
[edit]
[-] class-job.php
[edit]
[-] class-destination-ftp-type-exception.php
[edit]
[-] class-destination-sugarsync-api.php
[edit]
[-] class-download-file-interface.php
[edit]
[-] class-encryption-fallback.php
[edit]
[-] BackWPup.php
[edit]
[-] class-page-backwpup.php
[edit]
[-] class-destination-downloader-data.php
[edit]
[-] class-mysqldump-exception.php
[edit]
[-] class-s3-destination.php
[edit]
[-] class-destination-ftp.php
[edit]
[-] class-cron.php
[edit]
[+]
Notice
[-] class-destination-downloader.php
[edit]
[-] class-destinations.php
[edit]
[-] class-destination-ftp-downloader.php
[edit]
[-] class-destination-dropbox-downloader.php
[edit]
[-] class-download-handler.php
[edit]
[-] class-destination-dropbox.php
[edit]
[-] class-system-tests.php
[edit]
[-] class-destination-folder-downloader.php
[edit]
[-] class-destination-ftp-type.php
[edit]
[-] class-thirdparties.php
[edit]
[-] class-jobtype-wpplugin.php
[edit]
[-] class-directory.php
[edit]
[-] class-recursive-directory.php
[edit]
[-] class-destination-msazure-downloader.php
[edit]
[-] class-destination-connect-interface.php
[edit]
[-] class-install.php
[edit]
[-] class-admin.php
[edit]
[-] class-jobtype-file.php
[edit]
[-] functions.php
[edit]
[+]
Utils
[+]
ThirdParty
[-] class-destination-s3-downloader.php
[edit]
[-] class-destination-rsc-downloader.php
[edit]
[-] class-destination-sugarsync-downloader.php
[edit]
[-] class-destination-email.php
[edit]
[+]
..
[-] class-mysqldump.php
[edit]
[-] class-page-firstbackup.php
[edit]
[-] class-jobtype-wpexp.php
[edit]
[-] class-jobtype-dbcheck.php
[edit]
[-] class-file.php
[edit]
[-] class-sanitize-path.php
[edit]
[+]
Settings
[-] class-destination-s3.php
[edit]
[-] class-page-logs.php
[edit]
[-] class-factory-exception.php
[edit]
[-] class-page-restore.php
[edit]
[+]
dependencies
[-] class-create-archive-exception.php
[edit]
[-] class-page-editjob.php
[edit]
[-] class-page-backups.php
[edit]
[-] class-destination-dropbox-api-exception.php
[edit]
[-] class-create-archive.php
[edit]
[-] class-encryption-openssl.php
[edit]
[-] class-destination-onedrive-config-trait.php
[edit]
[-] class-destination-download-exception.php
[edit]
[-] class-download-file.php
[edit]
[-] class-page-settings.php
[edit]
[-] class-destination-msazure.php
[edit]
[-] class-page-onboarding.php
[edit]
[-] class-destination-folder.php
[edit]
[-] class-jobtypes.php
[edit]
[-] class-destination-connect-exception.php
[edit]
[-] class-destination-sugarsync.php
[edit]
[-] class-page-jobs.php
[edit]
[-] class-destination-sugarsync-api-exception.php
[edit]
[-] class-encryption-mcrypt.php
[edit]