PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/backupbuddy/lib/zipbuddy/zbzippclzip.php

https://bitbucket.org/anneivycat/california-tour
PHP | 406 lines | 158 code | 128 blank | 120 comment | 39 complexity | 24d5ef9368e2b07735e8e19777712b7b MD5 | raw file
  1. <?php
  2. /**
  3. * pluginbuddy_zbzippclzip Class
  4. *
  5. * Extends the zip capability core class with proc specific capability
  6. *
  7. * Version: 1.0.0
  8. * Author:
  9. * Author URI:
  10. *
  11. * @param $parent object Optional parent object which can provide functions for reporting, etc.
  12. * @return null
  13. *
  14. */
  15. if ( !class_exists( "pluginbuddy_zbzippclzip" ) ) {
  16. class pluginbuddy_zbzippclzip extends pluginbuddy_zbzipcore {
  17. const ZIP_CONTENT_FILE_NAME = 'last_pclzip_list.txt';
  18. /**
  19. * method tag used to refer to the method and entities associated with it such as class name
  20. *
  21. * @var $_method_tag string
  22. */
  23. public static $_method_tag = 'pclzip';
  24. /**
  25. * This tells us whether this method is regarded as a "compatibility" method
  26. *
  27. * @var bool
  28. */
  29. public static $_is_compatibility_method = true;
  30. /**
  31. * __construct()
  32. *
  33. * Default constructor.
  34. *
  35. * @param reference &$parent [optional] Reference to the object containing the status() function for status updates.
  36. * @return null
  37. *
  38. */
  39. public function __construct( &$parent = NULL ) {
  40. parent::__construct( $parent );
  41. // Define the initial details
  42. $this->_method_details[ 'attr' ] = array( 'name' => 'PclZip Method', 'compatibility' => pluginbuddy_zbzippclzip::$_is_compatibility_method );
  43. $this->_method_details[ 'param' ] = array( 'path' => '' );
  44. }
  45. /**
  46. * __destruct()
  47. *
  48. * Default destructor.
  49. *
  50. * @return null
  51. *
  52. */
  53. public function __destruct( ) {
  54. parent::__destruct();
  55. }
  56. /**
  57. * get_method_tag()
  58. *
  59. * Returns the (static) method tag
  60. *
  61. * @return string The method tag
  62. *
  63. */
  64. public function get_method_tag() {
  65. return pluginbuddy_zbzippclzip::$_method_tag;
  66. }
  67. /**
  68. * get_is_compatibility_method()
  69. *
  70. * Returns the (static) is_compatibility_method boolean
  71. *
  72. * @return bool
  73. *
  74. */
  75. public function get_is_compatibility_method() {
  76. return pluginbuddy_zbzippclzip::$_is_compatibility_method;
  77. }
  78. /**
  79. * is_available()
  80. *
  81. * A function that tests for the availability of the specific method in the requested mode
  82. *
  83. * @parame string $tempdir Temporary directory to use for any test files
  84. * @param string $mode Method mode to test for
  85. * @param array $status Array for any status messages
  86. * @return bool True if the method/mode combination is available, false otherwise
  87. *
  88. */
  89. public function is_available( $tempdir, $mode, &$status ) {
  90. $result = false;
  91. $zip = NULL;
  92. // The class has to be available for us so let's have a go
  93. // Note: it is not required because nothing will break without it but the method will
  94. // simply not be available
  95. // This may seem laborious but it's robust against include_once not playing nice if the
  96. // class is already included and trying to include it again
  97. if ( !class_exists( 'PclZip' ) ) {
  98. $pclzip_file = ABSPATH . 'wp-admin/includes/class-pclzip.php';
  99. pb_backupbuddy::status( 'details', 'PCLZip class not found. Attempting to load from `' . $pclzip_file . '`.' );
  100. @include_once( $pclzip_file );
  101. }
  102. if ( class_exists( 'PclZip' ) ) {
  103. $test_file = $tempdir . 'temp_test_' . uniqid() . '.zip';
  104. $zip = new PclZip( $test_file );
  105. if ( $zip->create( __FILE__ , PCLZIP_OPT_REMOVE_PATH, dirname( __FILE__) ) != 0 ) {
  106. if ( file_exists( $test_file ) ) {
  107. if ( !unlink( $test_file ) ) {
  108. pb_backupbuddy::status( 'details', sprintf( __('Error #564634. Unable to delete test file (%s)!','it-l10n-backupbuddy' ), $test_file ) );
  109. }
  110. pb_backupbuddy::status( 'details', __('PclZip test PASSED.','it-l10n-backupbuddy' ) );
  111. $result = true;
  112. } else {
  113. pb_backupbuddy::status( 'details', __('PclZip test FAILED: Zip file not found.','it-l10n-backupbuddy' ) );
  114. $result = false;
  115. }
  116. } else {
  117. pb_backupbuddy::status( 'details', __('PclZip test FAILED: Unable to create/open zip file.','it-l10n-backupbuddy' ) );
  118. pb_backupbuddy::status( 'details', __('PclZip Error: ','it-l10n-backupbuddy' ) . $zip->errorInfo( true ) );
  119. $result = false;
  120. }
  121. } else {
  122. pb_backupbuddy::status( 'details', __('PclZip test FAILED: PclZip class does not exist.','it-l10n-backupbuddy' ) );
  123. $result = false;
  124. }
  125. if ( NULL != $zip ) { unset( $zip ); }
  126. return $result;
  127. }
  128. /**
  129. * create()
  130. *
  131. * A function that creates an archive file
  132. *
  133. * The $excludes will be a list or relative path excludes if the $listmaker object is NULL otehrwise
  134. * will be absolute path excludes and relative path excludes can be had from the $listmaker object
  135. *
  136. * @param string $zip Full path & filename of ZIP Archive file to create
  137. * @param string $dir Full path of directory to add to ZIP Archive file
  138. * @param bool $compression True to enable compression of files added to ZIP Archive file
  139. * @parame array $excludes List of either absolute path exclusions or relative exclusions
  140. * @param string $tempdir Full path of directory for temporary usage
  141. * @param object $listmaker The object from which we can get an inclusions list
  142. * @return bool True if the creation was successful, false otherwise
  143. *
  144. */
  145. public function create( $zip, $dir, $compression, $excludes, $tempdir, $listmaker = NULL ) {
  146. $exitcode = 0;
  147. $zip_output = array();
  148. $temp_zip = '';
  149. $excluding_additional = false;
  150. $exclude_count = 0;
  151. $exclusions = array();
  152. // The basedir must have a trailing normalized directory separator
  153. $basedir = ( rtrim( trim( $dir ), self::DIRECTORY_SEPARATORS ) ) . self::NORM_DIRECTORY_SEPARATOR;
  154. // Normalize platform specific directory separators in path
  155. $basedir = str_replace( DIRECTORY_SEPARATOR, self::NORM_DIRECTORY_SEPARATOR, $basedir );
  156. pb_backupbuddy::status( 'message', __('Using Compatibility Mode.','it-l10n-backupbuddy' ) );
  157. pb_backupbuddy::status( 'message', __('If your backup times out in Compatibility Mode try disabling zip compression in Settings.','it-l10n-backupbuddy' ) );
  158. // The class has to be available for us so let's have a go
  159. // Note: it is not required because we can just bail out if it isn't (although it should be)
  160. // This may seem laborious but it's robust against include_once not playing nice if the
  161. // class is already included and trying to include it again
  162. if ( !class_exists( 'PclZip' ) ) {
  163. $pclzip_file = ABSPATH . 'wp-admin/includes/class-pclzip.php';
  164. pb_backupbuddy::status( 'details', 'PCLZip class not found. Attempting to load from `' . $pclzip_file . '`.' );
  165. @include_once( $pclzip_file );
  166. // Need to check if we actually got it and bail out if not
  167. if ( !class_exists( 'PclZip' ) ) {
  168. pb_backupbuddy::status( 'details', __('PclZip class must be available but is not.','it-l10n-backupbuddy' ) );
  169. return false;
  170. }
  171. }
  172. if ( empty( $tempdir ) || !file_exists( $tempdir ) ) {
  173. pb_backupbuddy::status( 'details', __('Temporary working directory must be available.','it-l10n-backupbuddy' ) );
  174. return false;
  175. }
  176. // Decide whether we are offering exclusions or not
  177. // Note that unlike proc and zip we always use inclusion if available to offer exclusion capability for pclzip
  178. if ( is_object( $listmaker ) ) {
  179. // Need to get the relative exclusions so we can log what is being excluded...
  180. $exclusions = $listmaker->get_relative_excludes( $basedir );
  181. // Build the exclusion list - first the relative directories
  182. if ( count( $exclusions ) > 0 ) {
  183. pb_backupbuddy::status( 'details', __('Calculating directories to exclude from backup.','it-l10n-backupbuddy' ) );
  184. foreach ( $exclusions as $exclude ) {
  185. if ( !strstr( $exclude, 'backupbuddy_backups' ) ) { // Set variable to show we are excluding additional directories besides backup dir.
  186. $excluding_additional = true;
  187. }
  188. pb_backupbuddy::status( 'details', __('Excluding','it-l10n-backupbuddy' ) . ': ' . $exclude );
  189. $exclude_count++;
  190. }
  191. }
  192. if ( $excluding_additional === true ) {
  193. pb_backupbuddy::status( 'message', __( 'Excluding archives directory and additional directories defined in settings.','it-l10n-backupbuddy' ) . ' ' . $exclude_count . ' ' . __( 'total','it-l10n-backupbuddy' ) . '.' );
  194. } else {
  195. pb_backupbuddy::status( 'message', __( 'Only excluding archives directory based on settings.','it-l10n-backupbuddy' ) . ' ' . $exclude_count . ' ' . __( 'total','it-l10n-backupbuddy' ) . '.' );
  196. }
  197. // Now get the list from the top node
  198. $the_list = $listmaker->get_terminals();
  199. // Retain this for reference for now
  200. file_put_contents( ( dirname( $tempdir ) . DIRECTORY_SEPARATOR . self::ZIP_CONTENT_FILE_NAME ), print_r( $the_list, true ) );
  201. } else {
  202. // We don't have the inclusion list so we are not offering exclusions
  203. pb_backupbuddy::status( 'message', __('WARNING: Directory/file exclusion unavailable in Compatibility Mode. Even existing old backups will be backed up.','it-l10n-backupbuddy' ) );
  204. $the_list = array( $dir );
  205. }
  206. // Get started with out zip object
  207. // Put our final zip file in the temporary directory - it will be moved later
  208. $temp_zip = $tempdir . basename( $zip );
  209. $pclzip = new PclZip( $temp_zip );
  210. if ( $compression !== true ) {
  211. pb_backupbuddy::status( 'details', __('Compression disabled based on settings.','it-l10n-backupbuddy' ) );
  212. $arguments = array( $the_list, PCLZIP_OPT_NO_COMPRESSION, PCLZIP_OPT_REMOVE_PATH, $dir );
  213. } else {
  214. $arguments = array( $the_list, PCLZIP_OPT_REMOVE_PATH, $dir );
  215. }
  216. if ( file_exists( $zip ) ) {
  217. pb_backupbuddy::status( 'details', __('Existing ZIP Archive file will be replaced.','it-l10n-backupbuddy' ) );
  218. unlink( $zip );
  219. }
  220. // Now actually create the zip archive file
  221. // TODO: handle first element of $arguments array being an array itself - could be long, to be displayed?
  222. pb_backupbuddy::status( 'details', $this->get_method_tag() . __( ' commmand arguments','it-l10n-backupbuddy' ) . ': ' . implode( ';', $arguments ) );
  223. $retval = call_user_func_array( array( &$pclzip, 'create' ), $arguments );
  224. // Work out whether we have a problem or not
  225. if ( is_array( $retval ) ) {
  226. // It's an array so a good result
  227. $exitcode = 0;
  228. } else {
  229. // Not an array so a bad error code
  230. $exitcode = $pclzip->errorCode();
  231. }
  232. // Convenience for handling different scanarios
  233. $result = false;
  234. // See if we can figure out what happened - note that $exitcode could be non-zero for a warning or error
  235. if ( ( ! file_exists( $temp_zip ) ) || ( $exitcode != 0 ) ) {
  236. // If we had a non-zero exit code then should report it (file may or may not be created)
  237. if ( $exitcode != 0 ) {
  238. pb_backupbuddy::status( 'details', __('Zip process exit code: ','it-l10n-backupbuddy' ) . $exitcode );
  239. }
  240. // Report whether or not the zip file was created
  241. if ( ! file_exists( $temp_zip ) ) {
  242. pb_backupbuddy::status( 'details', __( 'Zip Archive file not created - check process exit code.','it-l10n-backupbuddy' ) );
  243. } else {
  244. pb_backupbuddy::status( 'details', __( 'Zip Archive file created - check process exit code.','it-l10n-backupbuddy' ) );
  245. }
  246. // Put the error information into an array for consistency
  247. $zip_output[] = $pclzip->errorInfo( true );
  248. // Now we don't move it (because either it doesn't exist or may be incomplete) but we'll show any error/wartning output
  249. if ( !empty( $zip_output ) ) {
  250. // Assume we don't have a lot of lines for now - could be risky assumption!
  251. foreach ( $zip_output as $line ) {
  252. pb_backupbuddy::status( 'details', __( 'Zip process reported: ','it-l10n-backupbuddy' ) . $line );
  253. }
  254. }
  255. $result = false;
  256. } else {
  257. // Got file with no error or warnings at all so just move it to the local archive
  258. pb_backupbuddy::status( 'details', __('Moving Zip Archive file to local archive directory.','it-l10n-backupbuddy' ) );
  259. rename( $temp_zip, $zip );
  260. if ( file_exists( $zip ) ) {
  261. pb_backupbuddy::status( 'details', __('Zip Archive file moved to local archive directory.','it-l10n-backupbuddy' ) );
  262. pb_backupbuddy::status( 'message', __( 'Zip Archive file successfully created with no errors or warnings.','it-l10n-backupbuddy' ) );
  263. $result = true;
  264. } else {
  265. pb_backupbuddy::status( 'details', __('Zip Archive file could not be moved to local archive directory.','it-l10n-backupbuddy' ) );
  266. $result = false;
  267. }
  268. }
  269. // Cleanup the temporary directory that will have all detritus and maybe incomplete zip file
  270. pb_backupbuddy::status( 'details', __('Removing temporary directory.','it-l10n-backupbuddy' ) );
  271. if ( !( $this->delete_directory_recursive( $tempdir ) ) ) {
  272. pb_backupbuddy::status( 'details', __('Temporary directory could not be deleted: ','it-l10n-backupbuddy' ) . $tempdir );
  273. }
  274. return $result;
  275. }
  276. } // end pluginbuddy_zbzippclzip class.
  277. }
  278. ?>