PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/backupbuddy/destinations/ftp/init.php

https://gitlab.com/mattswann/launch-housing
PHP | 368 lines | 261 code | 66 blank | 41 comment | 67 complexity | 1e0742c76bcab5fcf93f9c0a3653fb48 MD5 | raw file
  1. <?php
  2. // DO NOT CALL THIS CLASS DIRECTLY. CALL VIA: pb_backupbuddy_destination in bootstrap.php.
  3. class pb_backupbuddy_destination_ftp {
  4. public static $destination_info = array(
  5. 'name' => 'FTP',
  6. 'description' => 'File Transport Protocol. This is the most common way of sending larger files between servers. Most web hosting accounts provide FTP access. This common and well-known transfer method is tried and true.',
  7. 'category' => 'normal', // best, normal, legacy
  8. );
  9. // Default settings. Should be public static for auto-merging.
  10. public static $default_settings = array(
  11. 'type' => 'ftp', // MUST MATCH your destination slug.
  12. 'title' => '', // Required destination field.
  13. 'address' => '',
  14. 'username' => '',
  15. 'password' => '',
  16. 'path' => '',
  17. 'active_mode' => 0, // 1 = active, 0=passive mode (default > v3.1.8).
  18. 'ftps' => 0,
  19. 'archive_limit' => 0,
  20. 'url' => '', // optional url for migration that corresponds to this ftp/path.
  21. 'disable_file_management' => '0', // When 1, _manage.php will not load which renders remote file management DISABLED.
  22. 'disabled' => '0', // When 1, disable this destination.
  23. );
  24. /* send()
  25. *
  26. * Send one or more files.
  27. *
  28. * @param array $files Array of one or more files to send.
  29. * @return boolean True on success, else false.
  30. */
  31. public static function send( $settings = array(), $files = array(), $send_id = '' ) {
  32. global $pb_backupbuddy_destination_errors;
  33. if ( '1' == $settings['disabled'] ) {
  34. $pb_backupbuddy_destination_errors[] = __( 'Error #48933: This destination is currently disabled. Enable it under this destination\'s Advanced Settings.', 'it-l10n-backupbuddy' );
  35. return false;
  36. }
  37. if ( ! is_array( $files ) ) {
  38. $files = array( $files );
  39. }
  40. pb_backupbuddy::status( 'details', 'FTP class send() function started.' );
  41. if ( $settings['active_mode'] == '0' ) {
  42. $active_mode = false;
  43. } else {
  44. $active_mode = true;
  45. }
  46. $server = $settings['address'];
  47. $username = $settings['username'];
  48. $password = $settings['password'];
  49. $path = $settings['path'];
  50. $ftps = $settings['ftps'];
  51. $limit = $settings['archive_limit'];
  52. $active = $settings['active_mode'];
  53. $port = '21'; // Default FTP port.
  54. if ( strstr( $server, ':' ) ) { // Handle custom FTP port.
  55. $server_params = explode( ':', $server );
  56. $server = $server_params[0];
  57. $port = $server_params[1];
  58. }
  59. // Connect to server.
  60. if ( $ftps == '1' ) { // Connect with FTPs.
  61. if ( function_exists( 'ftp_ssl_connect' ) ) {
  62. $conn_id = ftp_ssl_connect( $server, $port );
  63. if ( $conn_id === false ) {
  64. pb_backupbuddy::status( 'details', 'Unable to connect to FTPS `' . $server . '` on port `' . $port . '` (check address/FTPS support and that server can connect to this address via this port).', 'error' );
  65. return false;
  66. } else {
  67. pb_backupbuddy::status( 'details', 'Connected to FTPs.' );
  68. }
  69. } else {
  70. pb_backupbuddy::status( 'details', 'Your web server doesnt support FTPS in PHP.', 'error' );
  71. return false;
  72. }
  73. } else { // Connect with FTP (normal).
  74. if ( function_exists( 'ftp_connect' ) ) {
  75. $conn_id = ftp_connect( $server, $port );
  76. if ( $conn_id === false ) {
  77. pb_backupbuddy::status( 'details', 'ERROR: Unable to connect to FTP server `' . $server . '` on port `' . $port . '` (check address and that server can connect to this address via this port).', 'error' );
  78. return false;
  79. } else {
  80. pb_backupbuddy::status( 'details', 'Connected to FTP.' );
  81. }
  82. } else {
  83. pb_backupbuddy::status( 'details', 'Your web server doesnt support FTP in PHP.', 'error' );
  84. return false;
  85. }
  86. }
  87. // Log in.
  88. $login_result = @ftp_login( $conn_id, $username, $password );
  89. if ( $login_result === false ) {
  90. backupbuddy_core::mail_error( 'ERROR #9011 ( http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9011 ). FTP/FTPs login failed on scheduled FTP.' );
  91. return false;
  92. } else {
  93. pb_backupbuddy::status( 'details', 'Logged in. Sending backup via FTP/FTPs ...' );
  94. }
  95. if ( $active_mode === true ) {
  96. // do nothing, active is default.
  97. pb_backupbuddy::status( 'details', 'Active FTP mode based on settings.' );
  98. } elseif ( $active_mode === false ) {
  99. // Turn passive mode on.
  100. pb_backupbuddy::status( 'details', 'Passive FTP mode based on settings.' );
  101. ftp_pasv( $conn_id, true );
  102. } else {
  103. pb_backupbuddy::status( 'error', 'Unknown FTP active/passive mode: `' . $active_mode . '`.' );
  104. }
  105. // Create directory if it does not exist.
  106. @ftp_mkdir( $conn_id, $path );
  107. // Change to directory.
  108. pb_backupbuddy::status( 'details', 'Entering FTP directory `' . $path . '`.' );
  109. ftp_chdir( $conn_id, $path );
  110. // Upload files.
  111. $total_transfer_size = 0;
  112. $total_transfer_time = 0;
  113. foreach( $files as $file ) {
  114. if ( ! file_exists( $file ) ) {
  115. pb_backupbuddy::status( 'error', 'Error #859485495. Could not upload local file `' . $file . '` to send to FTP as it does not exist. Verify the file exists, permissions of file, parent directory, and that ownership is correct. You may need suphp installed on the server.' );
  116. }
  117. if ( ! is_readable( $file ) ) {
  118. pb_backupbuddy::status( 'error', 'Error #8594846548. Could not read local file `' . $file . '` to sendto FTP as it is not readable. Verify permissions of file, parent directory, and that ownership is correct. You may need suphp installed on the server.' );
  119. }
  120. $filesize = filesize( $file );
  121. $total_transfer_size += $filesize;
  122. $destination_file = basename( $file ); // Using chdir() so path not needed. $path . '/' . basename( $file );
  123. pb_backupbuddy::status( 'details', 'About to put to FTP local file `' . $file . '` of size `' . pb_backupbuddy::$format->file_size( $filesize ) . '` to remote file `' . $destination_file . '`.' );
  124. $send_time = -microtime( true );
  125. $upload = ftp_put( $conn_id, $destination_file, $file, FTP_BINARY );
  126. $send_time += microtime( true );
  127. $total_transfer_time += $send_time;
  128. if ( $upload === false ) {
  129. $error_message = 'ERROR #9012 ( http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9012 ). FTP/FTPs file upload failed. Check file permissions & disk quota.';
  130. pb_backupbuddy::status( 'error', $error_message );
  131. backupbuddy_core::mail_error( $error_message );
  132. return false;
  133. } else {
  134. pb_backupbuddy::status( 'details', 'Success completely sending `' . basename( $file ) . '` to destination.' );
  135. // Start remote backup limit
  136. if ( $limit > 0 ) {
  137. pb_backupbuddy::status( 'details', 'Getting contents of backup directory.' );
  138. ftp_chdir( $conn_id, $path );
  139. $contents = ftp_nlist( $conn_id, '' );
  140. // Create array of backups
  141. $bkupprefix = backupbuddy_core::backup_prefix();
  142. $backups = array();
  143. foreach ( $contents as $backup ) {
  144. // check if file is backup
  145. $pos = strpos( $backup, 'backup-' . $bkupprefix . '-' );
  146. if ( $pos !== FALSE ) {
  147. array_push( $backups, $backup );
  148. }
  149. }
  150. arsort( $backups ); // some ftp servers seem to not report in proper order so reversing insufficiently reliable. need to reverse sort by filename. array_reverse( (array)$backups );
  151. if ( ( count( $backups ) ) > $limit ) {
  152. $delete_fail_count = 0;
  153. $i = 0;
  154. foreach( $backups as $backup ) {
  155. $i++;
  156. if ( $i > $limit ) {
  157. if ( !ftp_delete( $conn_id, $backup ) ) {
  158. pb_backupbuddy::status( 'details', 'Unable to delete excess FTP file `' . $backup . '` in path `' . $path . '`.' );
  159. $delete_fail_count++;
  160. }
  161. }
  162. }
  163. if ( $delete_fail_count !== 0 ) {
  164. backupbuddy_core::mail_error( sprintf( __('FTP remote limit could not delete %s backups. Please check and verify file permissions.', 'it-l10n-backupbuddy' ), $delete_fail_count ) );
  165. }
  166. }
  167. } else {
  168. pb_backupbuddy::status( 'details', 'No FTP file limit to enforce.' );
  169. }
  170. // End remote backup limit
  171. }
  172. } // end $files loop.
  173. // Load destination fileoptions.
  174. pb_backupbuddy::status( 'details', 'About to load fileoptions data.' );
  175. require_once( pb_backupbuddy::plugin_path() . '/classes/fileoptions.php' );
  176. pb_backupbuddy::status( 'details', 'Fileoptions instance #13.' );
  177. $fileoptions_obj = new pb_backupbuddy_fileoptions( backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false );
  178. if ( true !== ( $result = $fileoptions_obj->is_ok() ) ) {
  179. pb_backupbuddy::status( 'error', __('Fatal Error #9034.84838. Unable to access fileoptions data.', 'it-l10n-backupbuddy' ) . ' Error: ' . $result );
  180. return false;
  181. }
  182. pb_backupbuddy::status( 'details', 'Fileoptions data loaded.' );
  183. $fileoptions = &$fileoptions_obj->options;
  184. // Save stats.
  185. $fileoptions['write_speed'] = $total_transfer_size / $total_transfer_time;
  186. //$fileoptions['finish_time'] = time();
  187. //$fileoptions['status'] = 'success';
  188. $fileoptions_obj->save();
  189. unset( $fileoptions_obj );
  190. ftp_close( $conn_id );
  191. return true;
  192. } // End send().
  193. /* test()
  194. *
  195. * function description
  196. *
  197. * @param array $settings Destination settings.
  198. * @return bool|string True on success, string error message on failure.
  199. */
  200. public static function test( $settings ) {
  201. if ( ( $settings['address'] == '' ) || ( $settings['username'] == '' ) || ( $settings['password'] == '' ) ) {
  202. return __('Missing required input.', 'it-l10n-backupbuddy' );
  203. }
  204. // Try sending a file.
  205. $send_response = pb_backupbuddy_destinations::send( $settings, dirname( dirname( __FILE__ ) ) . '/remote-send-test.php', $send_id = 'TEST-' . pb_backupbuddy::random_string( 12 ) ); // 3rd param true forces clearing of any current uploads.
  206. if ( false === $send_response ) {
  207. $send_response = 'Error sending test file to FTP.';
  208. } else {
  209. $send_response = 'Success.';
  210. }
  211. // Now we will need to go and cleanup this potentially uploaded file.
  212. $delete_response = 'Error deleting test file from FTP.'; // Default.
  213. // Settings.
  214. $server = $settings['address'];
  215. $username = $settings['username'];
  216. $password = $settings['password'];
  217. $path = $settings['path'];
  218. $ftps = $settings['ftps'];
  219. if ( $settings['active_mode'] == '0' ) {
  220. $active_mode = false;
  221. } else {
  222. $active_mode = true;
  223. }
  224. $url = $settings['url']; // optional url for using with migration.
  225. $port = '21';
  226. if ( strstr( $server, ':' ) ) {
  227. $server_params = explode( ':', $server );
  228. $server = $server_params[0];
  229. $port = $server_params[1];
  230. }
  231. // Connect.
  232. if ( $ftps == '0' ) {
  233. $conn_id = @ftp_connect( $server, $port, 10 ); // timeout of 10 seconds.
  234. if ( $conn_id === false ) {
  235. $error = __( 'Unable to connect to FTP address `' . $server . '` on port `' . $port . '`.', 'it-l10n-backupbuddy' );
  236. $error .= "\n" . __( 'Verify the server address and port (default 21). Verify your host allows outgoing FTP connections.', 'it-l10n-backupbuddy' );
  237. return $send_response . ' ' . $error;
  238. }
  239. } else {
  240. if ( function_exists( 'ftp_ssl_connect' ) ) {
  241. $conn_id = @ftp_ssl_connect( $server, $port );
  242. if ( $conn_id === false ) {
  243. return $send_response . ' ' . __('Destination server does not support FTPS?', 'it-l10n-backupbuddy' );
  244. }
  245. } else {
  246. return $send_response . ' ' . __('Your web server doesnt support FTPS.', 'it-l10n-backupbuddy' );
  247. }
  248. }
  249. $login_result = @ftp_login( $conn_id, $username, $password );
  250. if ( ( !$conn_id ) || ( !$login_result ) ) {
  251. pb_backupbuddy::status( 'details', 'FTP test: Invalid user/pass.' );
  252. $response = __('Unable to login. Bad user/pass.', 'it-l10n-backupbuddy' );
  253. if ( $ftps != '0' ) {
  254. $response .= "\n\nNote: You have FTPs enabled. You may get this error if your host does not support encryption at this address/port.";
  255. }
  256. return $send_response . ' ' . $response;
  257. }
  258. pb_backupbuddy::status( 'details', 'FTP test: Success logging in.' );
  259. // Handle active/pasive mode.
  260. if ( $active_mode === true ) {
  261. // do nothing, active is default.
  262. pb_backupbuddy::status( 'details', 'Active FTP mode based on settings.' );
  263. } elseif ( $active_mode === false ) {
  264. // Turn passive mode on.
  265. pb_backupbuddy::status( 'details', 'Passive FTP mode based on settings.' );
  266. ftp_pasv( $conn_id, true );
  267. } else {
  268. pb_backupbuddy::status( 'error', 'Unknown FTP active/passive mode: `' . $active_mode . '`.' );
  269. }
  270. // Delete test file.
  271. pb_backupbuddy::status( 'details', 'FTP test: Deleting temp test file.' );
  272. if ( true === ftp_delete( $conn_id, $path . '/remote-send-test.php' ) ) {
  273. $delete_response = 'Success.';
  274. }
  275. // Close FTP connection.
  276. pb_backupbuddy::status( 'details', 'FTP test: Closing FTP connection.' );
  277. @ftp_close($conn_id);
  278. // Load destination fileoptions.
  279. pb_backupbuddy::status( 'details', 'About to load fileoptions data.' );
  280. require_once( pb_backupbuddy::plugin_path() . '/classes/fileoptions.php' );
  281. pb_backupbuddy::status( 'details', 'Fileoptions instance #12.' );
  282. $fileoptions_obj = new pb_backupbuddy_fileoptions( backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false );
  283. if ( true !== ( $result = $fileoptions_obj->is_ok() ) ) {
  284. pb_backupbuddy::status( 'error', __('Fatal Error #9034.72373. Unable to access fileoptions data.', 'it-l10n-backupbuddy' ) . ' Error: ' . $result );
  285. return false;
  286. }
  287. pb_backupbuddy::status( 'details', 'Fileoptions data loaded.' );
  288. $fileoptions = &$fileoptions_obj->options;
  289. if ( ( 'Success.' != $send_response ) || ( 'Success.' != $delete_response ) ) {
  290. $fileoptions['status'] = 'failure';
  291. $fileoptions_obj->save();
  292. unset( $fileoptions_obj );
  293. return 'Send details: `' . $send_response . '`. Delete details: `' . $delete_response . '`.';
  294. } else {
  295. $fileoptions['status'] = 'success';
  296. $fileoptions['finish_time'] = microtime(true);
  297. }
  298. $fileoptions_obj->save();
  299. unset( $fileoptions_obj );
  300. return true;
  301. } // End test().
  302. } // End class.