Initial commit: WordPress wp-content (themes, plugins, languages)

- Theme: momentry (custom theme with REST API routes)
- Plugins: code-snippets (contains all API proxies)
- Languages: zh_TW translations
- Excludes: cache, backups, uploads, logs
This commit is contained in:
OpenCode
2026-05-29 19:07:56 +08:00
commit 09ef1f000f
6521 changed files with 867163 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 Yani Iliev
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,233 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Main template engine file
*
* PHP version 5
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @category Templates
* @package Bandar
* @author Yani Iliev <yani@iliev.me>
* @copyright 2013 Yani Iliev
* @license https://raw.github.com/yani-/bandar/master/LICENSE The MIT License (MIT)
* @version GIT: 3.0.0
* @link https://github.com/yani-/bandar/
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
/**
* Define EOL for CLI and Web
*/
if (!defined('BANDAR_EOL')) {
define('BANDAR_EOL', php_sapi_name() === 'cli' ? PHP_EOL : '<br />');
}
/**
* Include exceptions
*/
require_once
dirname(__FILE__) .
DIRECTORY_SEPARATOR .
'Exceptions' .
DIRECTORY_SEPARATOR .
'TemplateDoesNotExistException.php';
/**
* Bandar Main class
*
* @category Templates
* @package Bandar
* @author Yani Iliev <yani@iliev.me>
* @copyright 2013 Yani Iliev
* @license https://raw.github.com/yani-/bandar/master/LICENSE The MIT License (MIT)
* @version Release: 2.0.1
* @link https://github.com/yani-/bandar/
*/
class Bandar
{
/**
* Path to template files
*
* @var string|null
*/
public static $templatesPath = null;
/**
* Template file to output
* @var string|null
*/
public static $template = null;
/**
* Outputs the passed string if Bandar is in debug mode
*
* @param string $str Debug string to output
*
* @return void
*/
public static function debug($str)
{
/**
* if debug flag is on, output the string
*/
if (defined('BANDAR_DEBUG') && BANDAR_DEBUG) {
echo $str;
}
}
/**
* Retrieves templatesPath from BANDAR_TEMPLATES_PATH constant
*
* @throws TemplatesPathNotSetException If BANDAR_TEMPLATES_PATH is not defined
*
* @return string|null Templates path
*/
public static function getTemplatesPathFromConstant()
{
self::debug(
'Calling getTemplatesPathFromConstant' . BANDAR_EOL
);
if (defined('BANDAR_TEMPLATES_PATH')) {
return realpath(BANDAR_TEMPLATES_PATH) . DIRECTORY_SEPARATOR;
}
return null;
}
/**
* Setter for template
*
* @param string $template Template file
*
* @throws TemplateDoesNotExistException If template file is not found
*
* @return null
*/
public static function setTemplate($template, $path = false)
{
self::debug(
'Calling setTemplate with' . BANDAR_EOL .
'$template = ' . $template . BANDAR_EOL .
'type of $template is ' . gettype($template) . BANDAR_EOL
);
if ($path) {
$template = realpath($path) . DIRECTORY_SEPARATOR . $template;
} else {
$template = self::getTemplatesPathFromConstant() . $template;
}
$template = realpath($template . '.php');
/**
* Check if passed template exist
*/
if (self::templateExists($template)) {
self::$template = $template;
} else {
throw new TemplateDoesNotExistException;
}
}
/**
* Checks if template exists by using file_exists
*
* @param string $template Template file
*
* @return boolean
*/
public static function templateExists($template)
{
self::debug(
'Calling templateExists with ' . BANDAR_EOL .
'$template = ' . $template . BANDAR_EOL .
'type of $template is ' . gettype($template) . BANDAR_EOL
);
return (!is_dir($template) && is_readable($template));
}
/**
* Renders a passed template
*
* @param string $template Template name
* @param array $args Variables to pass to the template file
*
* @return string Contents of the template
*/
public static function render($template, $args=array(), $path = false)
{
self::debug(
'Calling render with' .
'$template = ' . $template . BANDAR_EOL .
'type of $template is ' . gettype($template) . BANDAR_EOL .
'$args = ' . print_r($args, true) . BANDAR_EOL .
'type of $args is ' . gettype($args) . BANDAR_EOL
);
self::setTemplate($template, $path);
/**
* Extracting passed aguments
*/
extract($args);
ob_start();
/**
* Including the view
*/
include self::$template;
return ob_get_flush();
}
/**
* Returns the content of a passed template
*
* @param string $template Template name
* @param array $args Variables to pass to the template file
*
* @return string Contents of the template
*/
public static function getTemplateContent($template, $args=array(), $path = false)
{
self::debug(
'Calling render with' .
'$template = ' . $template . BANDAR_EOL .
'type of $template is ' . gettype($template) . BANDAR_EOL .
'$args = ' . print_r($args, true) . BANDAR_EOL .
'type of $args is ' . gettype($args) . BANDAR_EOL
);
self::setTemplate($template, $path);
/**
* Extracting passed aguments
*/
extract($args);
ob_start();
/**
* Including the view
*/
include self::$template;
$content = ob_get_contents();
ob_end_clean();
return $content;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Contains TemplateDoesNotExistException class to be used in main Bandar class
*
* PHP version 5
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @category Exceptions
* @package Bandar
* @author Yani Iliev <yani@iliev.me>
* @copyright 2013 Yani Iliev
* @license https://raw.github.com/yani-/bandar/master/LICENSE The MIT License (MIT)
* @version GIT: 3.0.0
* @link https://github.com/yani-/bandar/
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
/**
* TemplateDoesNotExistException
*
* @category Exceptions
* @package Bandar
* @author Yani Iliev <yani@iliev.me>
* @copyright 2013 Yani Iliev
* @license https://raw.github.com/yani-/bandar/master/LICENSE The MIT License (MIT)
* @version Release: 2.0.1
* @link https://github.com/yani-/bandar/
*/
class TemplateDoesNotExistException extends Exception
{
}

View File

@@ -0,0 +1,432 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
abstract class Ai1wm_Archiver {
const HEADER_SIZE = 4377;
const READ_CHUNK_SIZE = 512000;
/**
* File name including path to the file
*
* @type string
*/
protected $file_name = null;
/**
* File password string
*
* @type string
*/
protected $file_password = null;
/**
* File compression type
*
* @type string
*/
protected $file_compression = null;
/**
* Handle to the file
*
* @type resource
*/
protected $file_handle = null;
/**
* Header block format of a file
*
* Field Name Offset Length Contents
* name 0 255 filename (no path, no slash)
* size 255 14 size of file contents
* mtime 269 12 last modification time
* prefix 281 4088 path name, no trailing slashes
* crc32 4369 8 CRC32 checksum (hex string, optional)
*
* @type array
*/
protected $block_format = array(
'a255', // filename
'a14', // size of file contents
'a12', // last time modified
'a4088', // path
'a8', // crc32
);
/**
* Archive CRC value from the v2 EOF block
*
* @type string
*/
protected $archive_crc_value = null;
/**
* Archive CRC size from the v2 EOF block
*
* @type string
*/
protected $archive_crc_size = null;
/**
* Default constructor
*
* Initializes filename and end of file block
*
* @param string $file_name File to use as archive
* @param string $file_password File password string
* @param string $file_compression File compression type
* @param bool $file_write File Read/write mode
*
* @throws Ai1wm_Not_Accessible_Exception
* @throws Ai1wm_Not_Seekable_Exception
*/
public function __construct( $file_name, $file_password = null, $file_compression = null, $file_write = false ) {
$this->file_name = $file_name;
$this->file_password = $file_password;
$this->file_compression = $file_compression;
// Open archive file
if ( $file_write ) {
// Open archive file for writing
if ( ( $this->file_handle = @fopen( $file_name, 'cb' ) ) === false ) {
throw new Ai1wm_Not_Accessible_Exception( sprintf( __( 'Could not open file for writing. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Seek to end of archive file
if ( @fseek( $this->file_handle, 0, SEEK_END ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to end of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
} else {
// Open archive file for reading
if ( ( $this->file_handle = @fopen( $file_name, 'rb' ) ) === false ) {
throw new Ai1wm_Not_Accessible_Exception( sprintf( __( 'Could not open file for reading. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
}
}
/**
* Set current file pointer
*
* @param int $offset Archive offset
*
* @throws \Ai1wm_Not_Seekable_Exception
*
* @return void
*/
public function set_file_pointer( $offset ) {
if ( @fseek( $this->file_handle, $offset, SEEK_SET ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $offset ) );
}
}
/**
* Get current file pointer
*
* @throws \Ai1wm_Not_Tellable_Exception
*
* @return int
*/
public function get_file_pointer() {
if ( ( $offset = @ftell( $this->file_handle ) ) === false ) {
throw new Ai1wm_Not_Tellable_Exception( sprintf( __( 'Could not tell offset of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
return $offset;
}
/**
* Appends end of file block to the archive file
*
* @param string|null $archive_crc_value Pre-calculated archive CRC32 (optional)
*
* @throws \Ai1wm_Not_Seekable_Exception
* @throws \Ai1wm_Not_Writable_Exception
* @throws \Ai1wm_Quota_Exceeded_Exception
*
* @return void
*/
protected function append_eof( $archive_crc_value = null ) {
// Seek to end of archive file
if ( @fseek( $this->file_handle, 0, SEEK_END ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to end of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Use pre-calculated CRC if provided, otherwise calculate (fallback)
if ( empty( $archive_crc_value ) ) {
$archive_crc_value = Ai1wm_Crc::calculate_file_crc32( $this->file_name );
}
// Get archive size (before EOF block)
if ( ( $archive_crc_size = @ftell( $this->file_handle ) ) === false ) {
throw new Ai1wm_Not_Tellable_Exception( sprintf( __( 'Could not tell offset of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Write end of file block
if ( ( $eof_block = $this->get_eof_block( $archive_crc_size, $archive_crc_value ) ) ) {
if ( ( $file_bytes = @fwrite( $this->file_handle, $eof_block ) ) !== false ) {
if ( strlen( $eof_block ) !== $file_bytes ) {
throw new Ai1wm_Quota_Exceeded_Exception( sprintf( __( 'Out of disk space. Could not write end of block to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
} else {
throw new Ai1wm_Not_Writable_Exception( sprintf( __( 'Could not write end of block to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
}
}
/**
* Replace forward slash with current directory separator
*
* @param string $path Path
*
* @return string
*/
protected function replace_forward_slash_with_directory_separator( $path ) {
return str_replace( '/', DIRECTORY_SEPARATOR, $path );
}
/**
* Replace current directory separator with forward slash
*
* @param string $path Path
*
* @return string
*/
protected function replace_directory_separator_with_forward_slash( $path ) {
return str_replace( DIRECTORY_SEPARATOR, '/', $path );
}
/**
* Escape Windows directory separator
*
* @param string $path Path
*
* @return string
*/
protected function escape_windows_directory_separator( $path ) {
return preg_replace( '/[\\\\]+/', '\\\\\\\\', $path );
}
/**
* Validate archive file
*
* @return bool
*/
public function is_valid() {
// Failed detecting the current file pointer offset
if ( ( $offset = @ftell( $this->file_handle ) ) === false ) {
return false;
}
// Failed seeking the beginning of EOL block
if ( @fseek( $this->file_handle, -static::HEADER_SIZE, SEEK_END ) === -1 ) {
return false;
}
// Get end of file block
if ( ( $block = @fread( $this->file_handle, static::HEADER_SIZE ) ) === false ) {
return false;
}
// Failed returning to original offset
if ( @fseek( $this->file_handle, $offset, SEEK_SET ) === -1 ) {
return false;
}
// Trailing block does not match EOL
if ( $this->is_eof_block( $block ) === false ) {
return false;
}
return true;
}
/**
* Truncates the archive file
*
* @return void
*/
public function truncate() {
if ( ( $offset = @ftell( $this->file_handle ) ) === false ) {
throw new Ai1wm_Not_Tellable_Exception( sprintf( __( 'Could not tell offset of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
if ( @filesize( $this->file_name ) > $offset ) {
if ( @ftruncate( $this->file_handle, $offset ) === false ) {
throw new Ai1wm_Not_Truncatable_Exception( sprintf( __( 'Could not truncate file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
}
}
/**
* Closes the archive file
*
* We either close the file or append the end of file block if complete argument is set to true
*
* @param bool $complete Flag to append end of file block
* @param string|null $archive_crc_value Pre-calculated archive CRC32 (optional)
*
* @return void
*/
public function close( $complete = false, $archive_crc_value = null ) {
// Are we done appending to the file?
if ( true === $complete ) {
$this->append_eof( $archive_crc_value );
}
if ( @fclose( $this->file_handle ) === false ) {
throw new Ai1wm_Not_Closable_Exception( sprintf( __( 'Could not close file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
}
/**
* Generate end of file block
*
* @param string $archive_crc_value Archive CRC
*
* @return string
*/
protected function get_eof_block( $archive_crc_size = null, $archive_crc_value = null ) {
return pack( 'a255a14a4100a8', '', $archive_crc_size, '', $archive_crc_value );
}
/**
* Check if a block is an end of file block (v1 or v2)
*
* @param string $block The block to check
*
* @return bool
*/
protected function is_eof_block( $block ) {
return $this->is_v1_eof( $block ) || $this->is_v2_eof( $block );
}
/**
* Check if a block is a v1 end of file block (all null bytes)
*
* @param string $block The block to check
*
* @return bool
*/
protected function is_v1_eof( $block ) {
return $this->get_eof_block() === $block;
}
/**
* Check if a block is a v2 end of file block
*
* @param string $block The block to check
*
* @return bool
*/
protected function is_v2_eof( $block ) {
// Unpack end of file data
if ( ( $data = unpack( 'a255/a14size/a4100/a8crc32', $block ) ) ) {
if ( isset( $data['size'], $data['crc32'] ) ) {
if ( preg_match( '/^[0-9a-f]{8}$/i', $data['crc32'] ) ) {
return $this->get_eof_block( $data['size'], $data['crc32'] ) === $block;
}
}
}
return false;
}
/**
* Get archive CRC from EOF block (v2 only)
*
* @return string|null CRC32 hex string or null if v1 archive
*/
public function get_archive_crc_value() {
if ( is_null( $this->archive_crc_value ) ) {
$this->set_archive_crc_data();
}
return $this->archive_crc_value;
}
/**
* Get archive CRC size from EOF block (v2 only)
*
* @return int|null Size hex string or null if v1 archive
*/
public function get_archive_crc_size() {
if ( is_null( $this->archive_crc_size ) ) {
$this->set_archive_crc_data();
}
return $this->archive_crc_size;
}
/**
* Set archive CRC value and size from the v2 EOF block
*
* @return void
*/
protected function set_archive_crc_data() {
// Failed detecting the current file pointer offset
if ( ( $offset = @ftell( $this->file_handle ) ) === false ) {
return;
}
// Failed seeking the beginning of EOL block
if ( @fseek( $this->file_handle, -static::HEADER_SIZE, SEEK_END ) === -1 ) {
return;
}
// Get end of file block
if ( ( $block = @fread( $this->file_handle, static::HEADER_SIZE ) ) === false ) {
return;
}
// Failed returning to original offset
if ( @fseek( $this->file_handle, $offset, SEEK_SET ) === -1 ) {
return;
}
// Check if v2 EOF
if ( $this->is_v2_eof( $block ) === false ) {
return;
}
// Unpack end of file data
if ( ( $data = unpack( 'a255/a14size/a4100/a8crc32', $block ) ) ) {
if ( isset( $data['crc32'] ) ) {
$this->archive_crc_value = trim( $data['crc32'] );
}
if ( isset( $data['size'] ) ) {
$this->archive_crc_size = (int) trim( $data['size'] );
}
}
}
}

View File

@@ -0,0 +1,306 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Compressor extends Ai1wm_Archiver {
/**
* Overloaded constructor that opens the passed file for writing
*
* @param string $file_name File to use as archive
* @param string $file_password File password string
* @param string $file_compression File compression type
*/
public function __construct( $file_name, $file_password = null, $file_compression = null ) {
// Call parent, to initialize variables
parent::__construct( $file_name, $file_password, $file_compression, true );
}
/**
* Add a file to the archive
*
* @param string $file_name File to add to the archive
* @param string $new_file_name Write the file with a different name
* @param int $file_bytes_read Amount of the bytes we read
* @param int $file_bytes_offset File bytes offset
* @param int $file_bytes_written Amount of the bytes we wrote
* @param string|null $file_crc File CRC32 checksum (passed by reference, optional)
*
* @throws \Ai1wm_Not_Seekable_Exception
* @throws \Ai1wm_Not_Writable_Exception
* @throws \Ai1wm_Quota_Exceeded_Exception
*
* @return bool
*/
public function add_file( $file_name, $new_file_name = '', &$file_bytes_read = 0, &$file_bytes_offset = 0, &$file_bytes_written = 0, &$file_crc = null ) {
// Replace forward slash with current directory separator in file name
$file_name = ai1wm_replace_forward_slash_with_directory_separator( $file_name );
// Escape Windows directory separator in file name
$file_name = ai1wm_escape_windows_directory_separator( $file_name );
// Flag to hold if file data has been processed
$completed = true;
// Start time
$start = microtime( true );
// Open the file for reading in binary mode (fopen may return null for quarantined files)
if ( ( $file_handle = @fopen( $file_name, 'rb' ) ) ) {
// Start native hash for current chunk
$hash_ctx = Ai1wm_Crc::init_crc32();
// Get header block with empty CRC placeholder
if ( ( $block = $this->get_file_block( $file_name, $new_file_name, '' ) ) ) {
// Write header block
if ( $file_bytes_offset === 0 ) {
if ( ( $file_bytes = @fwrite( $this->file_handle, $block ) ) !== false ) {
if ( strlen( $block ) !== $file_bytes ) {
throw new Ai1wm_Quota_Exceeded_Exception( sprintf( __( 'Out of disk space. Could not write header to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
} else {
throw new Ai1wm_Not_Writable_Exception( sprintf( __( 'Could not write header to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
}
// Set file offset
if ( @fseek( $file_handle, $file_bytes_offset, SEEK_SET ) !== -1 ) {
$file_bytes_read = 0;
// Cache config file check outside the loop
$should_process_file = ! in_array( $new_file_name, ai1wm_config_filters() );
// Read the file in 512KB chunks
while ( false === @feof( $file_handle ) ) {
if ( ( $file_content = @fread( $file_handle, static::READ_CHUNK_SIZE ) ) !== false ) {
// Empty read indicates EOF
if ( strlen( $file_content ) === 0 ) {
break;
}
// Add the amount of bytes we read
$file_bytes_read += strlen( $file_content );
// Update CRC with original content (BEFORE compression/encryption)
Ai1wm_Crc::update_crc32( $hash_ctx, $file_content );
// Do not encrypt or compress config files
if ( $should_process_file === true ) {
// Add chunk data compression
if ( ! empty( $this->file_compression ) ) {
switch ( $this->file_compression ) {
case 'gzip':
$file_content = gzcompress( $file_content, 9 );
break;
case 'bzip2':
$file_content = bzcompress( $file_content, 9 );
break;
}
}
// Add chunk data encryption
if ( ! empty( $this->file_password ) ) {
$file_content = ai1wm_encrypt_string( $file_content, $this->file_password );
}
// Add variable length chunk size before chunk data
if ( ! empty( $this->file_compression ) ) {
$file_content = pack( 'N', strlen( $file_content ) ) . $file_content;
}
}
if ( ( $file_bytes = @fwrite( $this->file_handle, $file_content ) ) !== false ) {
if ( strlen( $file_content ) !== $file_bytes ) {
throw new Ai1wm_Quota_Exceeded_Exception( sprintf( __( 'Out of disk space. Could not write content to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
} else {
throw new Ai1wm_Not_Writable_Exception( sprintf( __( 'Could not write content to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Add the amount of bytes we wrote
$file_bytes_written += $file_bytes;
}
// Time elapsed
if ( ( $timeout = apply_filters( 'ai1wm_completed_timeout', 10 ) ) ) {
if ( ( microtime( true ) - $start ) > $timeout ) {
$completed = false;
break;
}
}
}
// Add the amount of bytes we read
$file_bytes_offset += $file_bytes_read;
}
// Combine and finalize CRC
if ( empty( $file_crc ) ) {
$file_crc = Ai1wm_Crc::finalize_crc32( $hash_ctx );
} else {
$file_crc = Ai1wm_Crc::combine_crc32( $file_crc, Ai1wm_Crc::finalize_crc32( $hash_ctx ), $file_bytes_read );
}
// Write file size to file header
if ( ( $file_size_block = $this->get_file_size_block( $file_bytes_written ) ) ) {
// Seek to beginning of file size (back over: content + crc32(8) + path(4088) + mtime(12) + size(14))
if ( @fseek( $this->file_handle, - $file_bytes_written - 8 - 4088 - 12 - 14, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( __( 'Your PHP is 32-bit. In order to export your file, please change your PHP version to 64-bit and try again. <a href="https://help.servmask.com/knowledgebase/php-32bit/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ) );
}
// Write file size to file header
if ( ( $file_bytes = @fwrite( $this->file_handle, $file_size_block ) ) !== false ) {
if ( strlen( $file_size_block ) !== $file_bytes ) {
throw new Ai1wm_Quota_Exceeded_Exception( sprintf( __( 'Out of disk space. Could not write size to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
} else {
throw new Ai1wm_Not_Writable_Exception( sprintf( __( 'Could not write size to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Seek to beginning of file CRC (forward over: mtime(12) + path(4088))
if ( @fseek( $this->file_handle, + 12 + 4088, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( __( 'Your PHP is 32-bit. In order to export your file, please change your PHP version to 64-bit and try again. <a href="https://help.servmask.com/knowledgebase/php-32bit/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ) );
}
// Write file CRC to file header
if ( ( $file_crc_block = $this->get_file_crc_block( $file_crc ) ) ) {
if ( ( $file_bytes = @fwrite( $this->file_handle, $file_crc_block ) ) !== false ) {
if ( strlen( $file_crc_block ) !== $file_bytes ) {
throw new Ai1wm_Quota_Exceeded_Exception( sprintf( __( 'Out of disk space. Could not write CRC to file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
}
}
// Seek to end of file content (forward over: content)
if ( @fseek( $this->file_handle, + $file_bytes_written, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( __( 'Your PHP is 32-bit. In order to export your file, please change your PHP version to 64-bit and try again. <a href="https://help.servmask.com/knowledgebase/php-32bit/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ) );
}
}
}
// Close the handle
@fclose( $file_handle );
}
return $completed;
}
/**
* Generate binary block header for a file
*
* @param string $file_name Filename to generate block header for
* @param string $new_file_name Write the file with a different name
* @param string|null $crc32 CRC32 checksum (optional)
*
* @return string
*/
private function get_file_block( $file_name, $new_file_name = '', $crc32 = null ) {
$block = '';
// Get stats about the file
if ( ( $stat = @stat( $file_name ) ) !== false ) {
// Filename of the file we are accessing
if ( empty( $new_file_name ) ) {
$name = ai1wm_basename( $file_name );
} else {
$name = ai1wm_basename( $new_file_name );
}
// Size in bytes of the file
$size = $stat['size'];
// Last time the file was modified
$date = $stat['mtime'];
// Replace current directory separator with backward slash in file path
if ( empty( $new_file_name ) ) {
$path = ai1wm_replace_directory_separator_with_forward_slash( ai1wm_dirname( $file_name ) );
} else {
$path = ai1wm_replace_directory_separator_with_forward_slash( ai1wm_dirname( $new_file_name ) );
}
// Only calculate CRC if not provided
if ( empty( $crc32 ) ) {
$crc32 = Ai1wm_Crc::calculate_file_crc32( $file_name );
}
// Concatenate block format parts
$format = implode( '', $this->block_format );
// Pack file data into binary string
$block = pack( $format, $name, $size, $date, $path, $crc32 );
}
return $block;
}
/**
* Generate file size binary block header for a file
*
* @param int $file_size File size
*
* @return string
*/
public function get_file_size_block( $file_size ) {
$block = '';
// Pack file data into binary string
if ( isset( $this->block_format[1] ) ) {
$block = pack( $this->block_format[1], $file_size );
}
return $block;
}
/**
* Generate file CRC binary block header for a file
*
* @param int $file_crc File CRC
*
* @return string
*/
public function get_file_crc_block( $file_crc ) {
$block = '';
// Pack file data into binary string
if ( isset( $this->block_format[4] ) ) {
$block = pack( $this->block_format[4], $file_crc );
}
return $block;
}
}

View File

@@ -0,0 +1,717 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Extractor extends Ai1wm_Archiver {
/**
* Total files count
*
* @type int
*/
protected $total_files_count = null;
/**
* Total files size
*
* @type int
*/
protected $total_files_size = null;
/**
* Overloaded constructor that opens the passed file for reading
*
* @param string $file_name File to use as archive
* @param string $file_password File password string
* @param string $file_compression File compression type
*/
public function __construct( $file_name, $file_password = null, $file_compression = null ) {
// Call parent, to initialize variables
parent::__construct( $file_name, $file_password, $file_compression, false );
}
/**
* List all files in the archive
*
* @return array
*/
public function list_files() {
$files = array();
// Seek to beginning of archive file
if ( @fseek( $this->file_handle, 0, SEEK_SET ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to beginning of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
$offset = 0;
// Loop over files
while ( ( $block = @fread( $this->file_handle, static::HEADER_SIZE ) ) ) {
// End block has been reached
if ( $this->is_eof_block( $block ) ) {
continue;
}
// Get file data from the block
if ( ( $data = $this->get_data_from_block( $block ) ) ) {
// Store the position where the file begins - used for downloading from archive directly
$data['offset'] = $offset;
// Skip file content, so we can move forward to the next file
if ( @fseek( $this->file_handle, $data['size'], SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $data['size'] ) );
}
$files[] = $data;
}
$offset = @ftell( $this->file_handle );
}
return $files;
}
/**
* Get the total files count in an archive
*
* @return int
*/
public function get_total_files_count() {
if ( is_null( $this->total_files_count ) ) {
$this->set_files_totals();
}
return $this->total_files_count;
}
/**
* Get the total files size in an archive
*
* @return int
*/
public function get_total_files_size() {
if ( is_null( $this->total_files_size ) ) {
$this->set_files_totals();
}
return $this->total_files_size;
}
/**
* Set the total files count and size in the archive
*
* @return void
*/
protected function set_files_totals() {
// Total files count
$this->total_files_count = 0;
// Total files size
$this->total_files_size = 0;
// Seek to beginning of archive file
if ( @fseek( $this->file_handle, 0, SEEK_SET ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to beginning of file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Loop over files
while ( ( $block = @fread( $this->file_handle, static::HEADER_SIZE ) ) ) {
// End block has been reached
if ( $this->is_eof_block( $block ) ) {
continue;
}
// Get file data from the block
if ( ( $data = $this->get_data_from_block( $block ) ) ) {
// We have a file, increment the count
$this->total_files_count += 1;
// We have a file, increment the size
$this->total_files_size += $data['size'];
// Skip file content so we can move forward to the next file
if ( @fseek( $this->file_handle, $data['size'], SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $data['size'] ) );
}
}
}
}
/**
* Extract one file to location
*
* @param string $location Destination path
* @param array $exclude_files Exclude files by name
* @param array $exclude_extensions Exclude files by extension
* @param array $old_paths Old replace paths
* @param array $new_paths New replace paths
* @param int $file_bytes_read Amount of the bytes we read
* @param int $file_bytes_offset File bytes offset
* @param int $file_bytes_written Amount of the bytes we wrote
*
* @throws \Ai1wm_Not_Directory_Exception
* @throws \Ai1wm_Not_Seekable_Exception
*
* @return bool
*/
public function extract_one_file_to( $location, $exclude_files = array(), $exclude_extensions = array(), $old_paths = array(), $new_paths = array(), &$file_bytes_read = 0, &$file_bytes_offset = 0, &$file_bytes_written = 0 ) {
if ( false === is_dir( $location ) ) {
throw new Ai1wm_Not_Directory_Exception( sprintf( __( 'Location is not a directory: %s', 'all-in-one-wp-migration' ), $location ) );
}
// Replace forward slash with current directory separator in location
$location = ai1wm_replace_forward_slash_with_directory_separator( $location );
// Flag to hold if file data has been processed
$completed = true;
// Seek to file offset to archive file
if ( $file_bytes_offset > 0 ) {
if ( @fseek( $this->file_handle, - $file_bytes_offset - static::HEADER_SIZE, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, - $file_bytes_offset - static::HEADER_SIZE ) );
}
}
// Read file header block
if ( ( $block = @fread( $this->file_handle, static::HEADER_SIZE ) ) ) {
// We reached end of file, set the pointer to the end of the file so that feof returns true
if ( $this->is_eof_block( $block ) ) {
// Seek to end of archive file minus 1 byte
@fseek( $this->file_handle, 1, SEEK_END );
// Read 1 character
@fgetc( $this->file_handle );
} else {
// Get file header data from the block
if ( ( $data = $this->get_data_from_block( $block ) ) ) {
// Set file name
$file_name = $data['filename'];
// Set file size
$file_size = $data['size'];
// Set file mtime
$file_mtime = $data['mtime'];
// Set file path
$file_path = $data['path'];
// Set file crc
$file_crc32 = $data['crc32'];
// Should we skip this file by name?
$should_exclude_file = false;
for ( $i = 0; $i < count( $exclude_files ); $i++ ) {
if ( strpos( $file_name . DIRECTORY_SEPARATOR, ai1wm_replace_forward_slash_with_directory_separator( $exclude_files[ $i ] ) . DIRECTORY_SEPARATOR ) === 0 ) {
$should_exclude_file = true;
break;
}
}
// Should we skip this file by extension?
for ( $i = 0; $i < count( $exclude_extensions ); $i++ ) {
if ( strrpos( $file_name, $exclude_extensions[ $i ] ) === strlen( $file_name ) - strlen( $exclude_extensions[ $i ] ) ) {
$should_exclude_file = true;
break;
}
}
// Validate file name and file path for directory traversal
if ( path_is_absolute( $file_name ) || validate_file( $file_name ) !== 0 ) {
$should_exclude_file = true;
}
// Do we have a match?
if ( $should_exclude_file === false ) {
// Replace extract paths
for ( $i = 0; $i < count( $old_paths ); $i++ ) {
if ( strpos( $file_path . DIRECTORY_SEPARATOR, ai1wm_replace_forward_slash_with_directory_separator( $old_paths[ $i ] ) . DIRECTORY_SEPARATOR ) === 0 ) {
$file_name = substr_replace( $file_name, ai1wm_replace_forward_slash_with_directory_separator( $new_paths[ $i ] ), 0, strlen( ai1wm_replace_forward_slash_with_directory_separator( $old_paths[ $i ] ) ) );
$file_path = substr_replace( $file_path, ai1wm_replace_forward_slash_with_directory_separator( $new_paths[ $i ] ), 0, strlen( ai1wm_replace_forward_slash_with_directory_separator( $old_paths[ $i ] ) ) );
break;
}
}
// Escape Windows directory separator in file path
if ( path_is_absolute( $file_path ) ) {
$location_file_path = ai1wm_escape_windows_directory_separator( $file_path );
} else {
$location_file_path = ai1wm_escape_windows_directory_separator( $location . DIRECTORY_SEPARATOR . $file_path );
}
// Escape Windows directory separator in file name
if ( path_is_absolute( $file_name ) ) {
$location_file_name = ai1wm_escape_windows_directory_separator( $file_name );
} else {
$location_file_name = ai1wm_escape_windows_directory_separator( $location . DIRECTORY_SEPARATOR . $file_name );
}
// Check if location doesn't exist, then create it
if ( false === is_dir( $location_file_path ) ) {
@mkdir( $location_file_path, $this->get_permissions_for_directory(), true );
}
$file_bytes_read = 0;
// We have a match, let's extract the file
if ( ( $completed = $this->extract_to( $location_file_name, $file_name, $file_size, $file_mtime, $file_bytes_read, $file_bytes_offset, $file_bytes_written ) ) ) {
$file_bytes_offset = $file_bytes_written = 0;
// Verify CRC32 if present (not empty means version 2 archive with CRC32)
if ( ! empty( $file_crc32 ) ) {
do_action( 'ai1wm_check_file_integrity', $file_name, $file_crc32 );
}
}
} else {
// We don't have a match, skip file content
if ( @fseek( $this->file_handle, $file_size, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $file_size ) );
}
}
}
}
}
return $completed;
}
/**
* Extract specific files from archive
*
* @param string $location Location where to extract files
* @param array $include_files Include files by name
* @param array $exclude_files Exclude files by name
* @param array $exclude_extensions Exclude files by extension
* @param int $file_bytes_read Amount of the bytes we read
* @param int $file_bytes_offset File bytes offset
* @param int $file_bytes_written Amount of the bytes we wrote
*
* @throws \Ai1wm_Not_Directory_Exception
* @throws \Ai1wm_Not_Seekable_Exception
*
* @return bool
*/
public function extract_by_files_array( $location, $include_files = array(), $exclude_files = array(), $exclude_extensions = array(), &$file_bytes_read = 0, &$file_bytes_offset = 0, &$file_bytes_written = 0 ) {
if ( false === is_dir( $location ) ) {
throw new Ai1wm_Not_Directory_Exception( sprintf( __( 'Location is not a directory: %s', 'all-in-one-wp-migration' ), $location ) );
}
// Replace forward slash with current directory separator in location
$location = ai1wm_replace_forward_slash_with_directory_separator( $location );
// Flag to hold if file data has been processed
$completed = true;
// Start time
$start = microtime( true );
// Seek to file offset to archive file
if ( $file_bytes_offset > 0 ) {
if ( @fseek( $this->file_handle, - $file_bytes_offset - static::HEADER_SIZE, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, - $file_bytes_offset - static::HEADER_SIZE ) );
}
}
// We read until we reached the end of the file, or the files we were looking for were found
while ( ( $block = @fread( $this->file_handle, static::HEADER_SIZE ) ) ) {
// We reached end of file, set the pointer to the end of the file so that feof returns true
if ( $this->is_eof_block( $block ) ) {
// Seek to end of archive file minus 1 byte
@fseek( $this->file_handle, 1, SEEK_END );
// Read 1 character
@fgetc( $this->file_handle );
} else {
// Get file header data from the block
if ( ( $data = $this->get_data_from_block( $block ) ) ) {
// Set file name
$file_name = $data['filename'];
// Set file size
$file_size = $data['size'];
// Set file mtime
$file_mtime = $data['mtime'];
// Set file path
$file_path = $data['path'];
// Set file crc
$file_crc32 = $data['crc32'];
// Should we extract this file by name?
$should_include_file = false;
for ( $i = 0; $i < count( $include_files ); $i++ ) {
if ( strpos( $file_name . DIRECTORY_SEPARATOR, ai1wm_replace_forward_slash_with_directory_separator( $include_files[ $i ] ) . DIRECTORY_SEPARATOR ) === 0 ) {
$should_include_file = true;
break;
}
}
// Should we skip this file name?
for ( $i = 0; $i < count( $exclude_files ); $i++ ) {
if ( strpos( $file_name . DIRECTORY_SEPARATOR, ai1wm_replace_forward_slash_with_directory_separator( $exclude_files[ $i ] ) . DIRECTORY_SEPARATOR ) === 0 ) {
$should_include_file = false;
break;
}
}
// Should we skip this file by extension?
for ( $i = 0; $i < count( $exclude_extensions ); $i++ ) {
if ( strrpos( $file_name, $exclude_extensions[ $i ] ) === strlen( $file_name ) - strlen( $exclude_extensions[ $i ] ) ) {
$should_include_file = false;
break;
}
}
// Validate file name and file path for directory traversal
if ( path_is_absolute( $file_name ) || validate_file( $file_name ) !== 0 ) {
$should_include_file = false;
}
// Do we have a match?
if ( $should_include_file === true ) {
// Escape Windows directory separator in file path
$location_file_path = ai1wm_escape_windows_directory_separator( $location . DIRECTORY_SEPARATOR . $file_path );
// Escape Windows directory separator in file name
$location_file_name = ai1wm_escape_windows_directory_separator( $location . DIRECTORY_SEPARATOR . $file_name );
// Check if location doesn't exist, then create it
if ( false === is_dir( $location_file_path ) ) {
@mkdir( $location_file_path, $this->get_permissions_for_directory(), true );
}
$file_bytes_read = 0;
// We have a match, let's extract the file
if ( ( $completed = $this->extract_to( $location_file_name, $file_name, $file_size, $file_mtime, $file_bytes_read, $file_bytes_offset, $file_bytes_written ) ) ) {
$file_bytes_offset = $file_bytes_written = 0;
// Verify CRC32 if present (not empty means version 2 archive with CRC32)
if ( ! empty( $file_crc32 ) ) {
do_action( 'ai1wm_check_file_integrity', $file_name, $file_crc32 );
}
}
} else {
// We don't have a match, skip file content
if ( @fseek( $this->file_handle, $file_size, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $file_size ) );
}
}
// Time elapsed
if ( ( $timeout = apply_filters( 'ai1wm_completed_timeout', 10 ) ) ) {
if ( ( microtime( true ) - $start ) > $timeout ) {
$completed = false;
break;
}
}
}
}
}
return $completed;
}
/**
* Extract file to
*
* @param string $location_file_name Location file name
* @param string $file_name File name
* @param array $file_size File size (in bytes)
* @param array $file_mtime File modified time (in seconds)
* @param int $file_bytes_read Amount of the bytes we read
* @param int $file_bytes_offset File bytes offset
* @param int $file_bytes_written Amount of the bytes we wrote
*
* @throws \Ai1wm_Not_Seekable_Exception
* @throws \Ai1wm_Not_Readable_Exception
* @throws \Ai1wm_Quota_Exceeded_Exception
*
* @return bool
*/
private function extract_to( $location_file_name, $file_name, $file_size, $file_mtime, &$file_bytes_read = 0, &$file_bytes_offset = 0, &$file_bytes_written = 0 ) {
// Flag to hold if file data has been processed
$completed = true;
// Start time
$start = microtime( true );
// Seek to file offset to archive file
if ( $file_bytes_offset > 0 ) {
if ( @fseek( $this->file_handle, $file_bytes_offset, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $file_size ) );
}
}
// Set file size
$file_size -= $file_bytes_offset;
// Should the extract overwrite the file if it exists? (fopen may return null for quarantined files)
if ( ( $file_handle = @fopen( $location_file_name, ( $file_bytes_offset === 0 ? 'wb' : 'cb' ) ) ) ) {
// Set file offset
if ( @fseek( $file_handle, $file_bytes_written, SEEK_SET ) !== -1 ) {
$file_bytes_read = 0;
// Cache config file check outside the loop
$should_process_file = ! in_array( $file_name, ai1wm_config_filters() );
// Is the filesize more than 0 bytes?
while ( $file_size > 0 ) {
// Read the file in chunks of 512KB
$chunk_size = min( $file_size, static::READ_CHUNK_SIZE );
// Do not decrypt or decompress config files
if ( $should_process_file === true ) {
// Get decryption chunk size
if ( ! empty( $this->file_password ) ) {
if ( $file_size > static::READ_CHUNK_SIZE ) {
$chunk_size += ai1wm_crypt_iv_length() * 2;
$chunk_size = min( $chunk_size, $file_size );
}
}
// Read chunk header data
if ( ! empty( $this->file_compression ) ) {
$chunk_header_size = 4;
// Get chunk header block
if ( ( $chunk_header_block = fread( $this->file_handle, $chunk_header_size ) ) === false ) {
throw new Ai1wm_Not_Readable_Exception( sprintf( __( 'Could not read content from file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Get chunk header data
if ( ( $chunk_header_data = unpack( 'Nsize', $chunk_header_block ) ) ) {
if ( isset( $chunk_header_data['size'] ) ) {
$chunk_size = $chunk_header_data['size'];
}
}
// Add the amount of bytes we read
$file_bytes_read += $chunk_header_size;
// Remove the amout of bytes we read
$file_size -= $chunk_header_size;
}
}
// Read data chunk by chunk from archive file
if ( $chunk_size > 0 ) {
// Read the file in chunks of 512KB from archiver
if ( ( $file_content = @fread( $this->file_handle, $chunk_size ) ) === false ) {
throw new Ai1wm_Not_Readable_Exception( sprintf( __( 'Could not read content from file. File: %s', 'all-in-one-wp-migration' ), $this->file_name ) );
}
// Add the amount of bytes we read
$file_bytes_read += $chunk_size;
// Remove the amout of bytes we read
$file_size -= $chunk_size;
// Do not decrypt or decompress config files
if ( $should_process_file === true ) {
// Add chunk data decryption
if ( ! empty( $this->file_password ) ) {
$file_content = ai1wm_decrypt_string( $file_content, $this->file_password );
}
// Add chunk data decompression
if ( ! empty( $this->file_compression ) ) {
switch ( $this->file_compression ) {
case 'gzip':
$file_content = gzuncompress( $file_content );
break;
case 'bzip2':
$file_content = bzdecompress( $file_content );
break;
}
}
}
// Write file contents
if ( ( $file_bytes = @fwrite( $file_handle, $file_content ) ) !== false ) {
if ( strlen( $file_content ) !== $file_bytes ) {
throw new Ai1wm_Quota_Exceeded_Exception( sprintf( __( 'Out of disk space. Could not write content to file. File: %s', 'all-in-one-wp-migration' ), $location_file_name ) );
}
}
// Add the amount of bytes we wrote
$file_bytes_written += $file_bytes;
}
// Time elapsed
if ( ( $timeout = apply_filters( 'ai1wm_completed_timeout', 10 ) ) ) {
if ( ( microtime( true ) - $start ) > $timeout ) {
$completed = false;
break;
}
}
}
// Add the amount of bytes we read
$file_bytes_offset += $file_bytes_read;
}
// Close the handle
@fclose( $file_handle );
// Let's apply last modified date
@touch( $location_file_name, $file_mtime );
// All files should chmoded to 644
@chmod( $location_file_name, $this->get_permissions_for_file() );
} else {
// We don't have file permissions, skip file content
if ( @fseek( $this->file_handle, $file_size, SEEK_CUR ) === -1 ) {
throw new Ai1wm_Not_Seekable_Exception( sprintf( __( 'Could not seek to offset of file. File: %s Offset: %d', 'all-in-one-wp-migration' ), $this->file_name, $file_size ) );
}
}
return $completed;
}
/**
* Get file header data from the block
*
* @param string $block Binary file header
*
* @return array
*/
private function get_data_from_block( $block ) {
$data = false;
// Prepare our array keys to unpack
$format = array(
$this->block_format[0] . 'filename/',
$this->block_format[1] . 'size/',
$this->block_format[2] . 'mtime/',
$this->block_format[3] . 'path/',
$this->block_format[4] . 'crc32',
);
$format = implode( '', $format );
// Unpack file header data
if ( ( $data = unpack( $format, $block ) ) ) {
// Set file details
$data['filename'] = trim( $data['filename'] );
$data['size'] = (int) trim( $data['size'] );
$data['mtime'] = (int) trim( $data['mtime'] );
$data['path'] = trim( $data['path'] );
$data['crc32'] = trim( $data['crc32'] );
// Set file name
$data['filename'] = ( $data['path'] === '.' ? $data['filename'] : $data['path'] . DIRECTORY_SEPARATOR . $data['filename'] );
// Set file path
$data['path'] = ( $data['path'] === '.' ? '' : $data['path'] );
// Replace forward slash with current directory separator in file name
$data['filename'] = ai1wm_replace_forward_slash_with_directory_separator( $data['filename'] );
// Replace forward slash with current directory separator in file path
$data['path'] = ai1wm_replace_forward_slash_with_directory_separator( $data['path'] );
}
return $data;
}
/**
* Check if file has reached end of file
* Returns true if file has reached eof, false otherwise
*
* @return bool
*/
public function has_reached_eof() {
return @feof( $this->file_handle );
}
/**
* Check if file has reached end of file
* Returns true if file has NOT reached eof, false otherwise
*
* @return bool
*/
public function has_not_reached_eof() {
return ! @feof( $this->file_handle );
}
/**
* Get directory permissions
*
* @return int
*/
public function get_permissions_for_directory() {
if ( defined( 'FS_CHMOD_DIR' ) ) {
return FS_CHMOD_DIR;
}
return 0755;
}
/**
* Get file permissions
*
* @return int
*/
public function get_permissions_for_file() {
if ( defined( 'FS_CHMOD_FILE' ) ) {
return FS_CHMOD_FILE;
}
return 0644;
}
}

View File

@@ -0,0 +1,202 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Crc {
/**
* Calculate CRC32 checksum for a file
*
* @param string $file_path Path to the file
* @return string|null CRC32 checksum as hexadecimal string or null on error
*/
public static function calculate_file_crc32( $file_path ) {
if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
return null;
}
// Use hash_file for CRC32b (CRC32 with reversed bit order, more standard)
$crc = hash_file( 'crc32b', $file_path );
return $crc;
}
/**
* Verify file CRC32 checksum
*
* @param string $file_path Path to the file
* @param string $expected_crc Expected CRC32 checksum
* @return bool True if CRC matches, false otherwise
*/
public static function verify_file_crc32( $file_path, $expected_crc ) {
$calculated_crc = self::calculate_file_crc32( $file_path );
if ( $calculated_crc === null ) {
return false;
}
return strcasecmp( $calculated_crc, $expected_crc ) === 0;
}
/**
* Initialize CRC32 hash context for incremental calculation
*
* @return resource|\HashContext Hash context
*/
public static function init_crc32() {
return hash_init( 'crc32b' );
}
/**
* Update CRC32 hash with a data chunk
*
* @param resource|\HashContext $context Hash context
* @param string $data Data chunk to add
* @return void
*/
public static function update_crc32( $context, $data ) {
hash_update( $context, $data );
}
/**
* Finalize CRC32 calculation and return result
*
* @param resource|\HashContext $context Hash context
* @return string CRC32 checksum as hexadecimal string
*/
public static function finalize_crc32( $context ) {
return hash_final( $context );
}
/**
* Combine two CRC32 checksums
*
* This method mathematically combines two CRC32 values, allowing resumable
* CRC calculation across multiple processing cycles (e.g., handling timeouts).
*
* Based on zlib's crc32_combine algorithm using GF(2) polynomial arithmetic.
*
* @param string $crc1_hex CRC32 of first data block (hex string)
* @param string $crc2_hex CRC32 of second data block (hex string)
* @param int $len2 Length of second data block in bytes
* @return string Combined CRC32 checksum as hexadecimal string
*/
public static function combine_crc32( $crc1_hex, $crc2_hex, $len2 ) {
// CRC32 polynomial (reversed)
$poly = 0xEDB88320;
// Convert hex strings to integers
$crc1 = hexdec( $crc1_hex );
$crc2 = hexdec( $crc2_hex );
// If second block is empty, return first CRC unchanged
if ( $len2 === 0 ) {
return sprintf( '%08x', $crc1 );
}
// Build operator matrix for x^n where n = len2 * 8
// This represents multiplication by x^(8*len2) mod poly
$even = array_fill( 0, 32, 0 );
$even[0] = $poly;
$row = 1;
for ( $n = 1; $n < 32; $n++ ) {
$even[ $n ] = $row;
$row = $row << 1;
}
// Square to get x^2, x^4, x^8, etc.
$odd = array_fill( 0, 32, 0 );
self::gf2_matrix_square( $odd, $even );
self::gf2_matrix_square( $even, $odd );
// Apply len2 zeros to crc1 by repeatedly squaring and applying
do {
// Apply zeros operator for this bit of len2
self::gf2_matrix_square( $odd, $even );
if ( $len2 & 1 ) {
$crc1 = self::gf2_matrix_times( $odd, $crc1 );
}
$len2 >>= 1;
// If no more bits, we're done
if ( $len2 === 0 ) {
break;
}
// Square again for next bit
self::gf2_matrix_square( $even, $odd );
if ( $len2 & 1 ) {
$crc1 = self::gf2_matrix_times( $even, $crc1 );
}
$len2 >>= 1;
} while ( $len2 !== 0 );
// Combine the two CRCs
$crc1 ^= $crc2;
return sprintf( '%08x', $crc1 );
}
/**
* Matrix multiplication in GF(2)
*
* @param array $mat Matrix
* @param int $vec Vector
* @return int Result
*/
private static function gf2_matrix_times( $mat, $vec ) {
$sum = 0;
$mat_index = 0;
while ( $vec ) {
if ( $vec & 1 ) {
$sum ^= $mat[ $mat_index ];
}
$vec = ( $vec >> 1 ) & 0x7FFFFFFF;
$mat_index++;
}
return $sum;
}
/**
* Square a matrix in GF(2)
*
* @param array $square Result matrix (passed by reference)
* @param array $mat Input matrix
* @return void
*/
private static function gf2_matrix_square( &$square, $mat ) {
for ( $n = 0; $n < 32; $n++ ) {
$square[ $n ] = self::gf2_matrix_times( $mat, $mat[ $n ] );
}
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
if ( defined( 'WP_CLI' ) ) {
class Ai1wm_WP_CLI_Command extends WP_CLI_Command {
/**
* Creates a new backup.
*
* ## EXAMPLES
*
* $ wp ai1wm export
*
* @subcommand export
*/
public function export( $args = array(), $assoc_args = array() ) {
$this->info();
}
/**
* Creates a new backup.
*
* ## EXAMPLES
*
* $ wp ai1wm backup
*
* @subcommand backup
*/
public function backup( $args = array(), $assoc_args = array() ) {
$this->info();
}
/**
* Imports a backup.
*
* ## EXAMPLES
*
* $ wp ai1wm import
*
* @subcommand import
*/
public function import( $args = array(), $assoc_args = array() ) {
$this->info();
}
/**
* Restores a backup.
*
* ## EXAMPLES
*
* $ wp ai1wm restore
*
* @subcommand restore
*/
public function restore( $args = array(), $assoc_args = array() ) {
$this->info();
}
/**
* Resets site to default WordPress installation.
*
* ## EXAMPLES
*
* $ wp ai1wm reset
*
* @subcommand reset
*/
public function reset( $args = array(), $assoc_args = array() ) {
$this->info();
}
protected function info() {
if ( is_multisite() ) {
WP_CLI::error_multi_line(
array(
__( 'This feature is available in Multisite Extension.', 'all-in-one-wp-migration' ),
__( 'You can purchase it from this address: https://servmask.com/products/multisite-extension', 'all-in-one-wp-migration' ),
)
);
exit;
}
WP_CLI::error_multi_line(
array(
__( 'This feature is available in Unlimited Extension.', 'all-in-one-wp-migration' ),
__( 'You can purchase it from this address: https://servmask.com/products/unlimited-extension', 'all-in-one-wp-migration' ),
)
);
}
}
}

View File

@@ -0,0 +1,142 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Cron {
/**
* Schedules a hook which will be executed by the WordPress
* actions core on a specific interval
*
* @param string $hook Event hook
* @param string $recurrence How often the event should reoccur
* @param integer $timestamp Preferred timestamp (when the event shall be run)
* @param array $args Arguments to pass to the hook function(s)
* @return mixed
*/
public static function add( $hook, $recurrence, $timestamp, $args = array() ) {
$schedules = wp_get_schedules();
// Schedule event
if ( isset( $schedules[ $recurrence ] ) && ( $current = $schedules[ $recurrence ] ) ) {
if ( $timestamp <= ( $current_timestamp = time() ) ) {
while ( $timestamp <= $current_timestamp ) {
$timestamp += $current['interval'];
}
}
return wp_schedule_event( $timestamp, $recurrence, $hook, $args );
}
}
/**
* Un-schedules all previously-scheduled cron jobs using a particular
* hook name or a specific combination of hook name and arguments.
*
* @param string $hook Event hook
* @return boolean
*/
public static function clear( $hook ) {
$cron = get_option( AI1WM_CRON, array() );
if ( empty( $cron ) ) {
return false;
}
foreach ( $cron as $timestamp => $hooks ) {
if ( isset( $hooks[ $hook ] ) ) {
unset( $cron[ $timestamp ][ $hook ] );
// Unset empty timestamps
if ( empty( $cron[ $timestamp ] ) ) {
unset( $cron[ $timestamp ] );
}
}
}
return update_option( AI1WM_CRON, $cron );
}
/**
* Checks whether cronjob already exists
*
* @param string $hook Event hook
* @param array $args Event callback arguments
* @return boolean
*/
public static function exists( $hook, $args = array() ) {
$cron = get_option( AI1WM_CRON, array() );
if ( empty( $cron ) ) {
return false;
}
foreach ( $cron as $timestamp => $hooks ) {
if ( empty( $args ) ) {
if ( isset( $hooks[ $hook ] ) ) {
return true;
}
} else {
if ( isset( $hooks[ $hook ][ md5( serialize( $args ) ) ] ) ) {
return true;
}
}
}
return false;
}
/**
* Deletes cron event(s) if it exists
*
* @param string $hook Event hook
* @param array $args Event callback arguments
* @return boolean
*/
public static function delete( $hook, $args = array() ) {
$cron = get_option( AI1WM_CRON, array() );
if ( empty( $cron ) ) {
return false;
}
$key = md5( serialize( $args ) );
foreach ( $cron as $timestamp => $hooks ) {
if ( isset( $cron[ $timestamp ][ $hook ][ $key ] ) ) {
unset( $cron[ $timestamp ][ $hook ][ $key ] );
}
if ( isset( $cron[ $timestamp ][ $hook ] ) && empty( $cron[ $timestamp ][ $hook ] ) ) {
unset( $cron[ $timestamp ][ $hook ] );
}
if ( empty( $cron[ $timestamp ] ) ) {
unset( $cron[ $timestamp ] );
}
}
return update_option( AI1WM_CRON, $cron );
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Database_Mariadb extends Ai1wm_Database_Mysqli {
/**
* Replace column types
*
* @param string $input Column value
* @return string
*/
protected function replace_column_types( $input ) {
static $search = null;
static $replace = null;
// Cache column types on first call
if ( is_null( $search ) || is_null( $replace ) ) {
$search = array();
$replace = array();
// Convert INET4 column type (10.10.0)
if ( version_compare( $this->server_version(), '10.10.0', '<' ) ) {
$search[] = '/(?<!`)\bINET4\b(?!\s*\()/i';
$replace[] = 'VARCHAR(15)';
}
// Convert INET6 column type (10.5.0)
if ( version_compare( $this->server_version(), '10.5.0', '<' ) ) {
$search[] = '/(?<!`)\bINET6\b(?!\s*\()/i';
$replace[] = 'VARCHAR(45)';
}
// Convert UUID column type (10.7.0)
if ( version_compare( $this->server_version(), '10.7.0', '<' ) ) {
$search[] = '/(?<!`)\bUUID\b(?!\s*\()/i';
$replace[] = 'CHAR(36)';
}
// Convert XMLTYPE column type (12.3.0)
if ( version_compare( $this->server_version(), '12.3.0', '<' ) ) {
$search[] = '/(?<!`)\bXMLTYPE\b(?!\s*\()/i';
$replace[] = 'LONGTEXT';
}
// Convert VECTOR(N) column type (11.7.1)
if ( version_compare( $this->server_version(), '11.7.1', '<' ) ) {
$search[] = '/(?<!`)\bVECTOR\s*\(\s*\d+\s*\)/i';
$replace[] = 'BLOB';
}
}
return preg_replace( $search, $replace, $input );
}
}

View File

@@ -0,0 +1,159 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Database_Mysql extends Ai1wm_Database {
/**
* Check whether table has auto increment attribute
*
* @param string $table_name Table name
* @return boolean
*/
public function has_auto_increment( $table_name ) {
return stripos( $this->get_create_table( $table_name ), 'AUTO_INCREMENT' ) !== false;
}
/**
* Run MySQL query
*
* @param string $input SQL query
* @return mixed
*/
public function query( $input ) {
if ( ! ( $result = mysql_query( $input, $this->wpdb->dbh ) ) ) {
$mysql_errno = 0;
// Get MySQL error code
if ( ! empty( $this->wpdb->dbh ) ) {
if ( is_resource( $this->wpdb->dbh ) ) {
$mysql_errno = mysql_errno( $this->wpdb->dbh );
} else {
$mysql_errno = 2006;
}
}
// MySQL server has gone away, try to reconnect
if ( empty( $this->wpdb->dbh ) || 2006 === $mysql_errno ) {
if ( ! $this->wpdb->check_connection( false ) ) {
throw new Ai1wm_Database_Exception( __( 'Error reconnecting to the database. <a href="https://help.servmask.com/knowledgebase/mysql-error-reconnecting/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), 503 );
}
$result = mysql_query( $input, $this->wpdb->dbh );
}
}
return $result;
}
/**
* Escape string input for MySQL query
*
* @param string $input String to escape
* @return string
*/
public function escape( $input ) {
return mysql_real_escape_string( $input, $this->wpdb->dbh );
}
/**
* Return the error code for the most recent function call
*
* @return integer
*/
public function errno() {
return mysql_errno( $this->wpdb->dbh );
}
/**
* Return a string description of the last error
*
* @return string
*/
public function error() {
return mysql_error( $this->wpdb->dbh );
}
/**
* Return server info
*
* @return string
*/
public function server_info() {
static $cached_result = null;
// Cache server info on first call
if ( $cached_result === null ) {
$cached_result = mysql_get_server_info( $this->wpdb->dbh );
}
return $cached_result;
}
/**
* Return the result from MySQL query as associative array
*
* @param mixed $result MySQL resource
* @return array
*/
public function fetch_assoc( &$result ) {
return mysql_fetch_assoc( $result );
}
/**
* Return the result from MySQL query as row
*
* @param mixed $result MySQL resource
* @return array
*/
public function fetch_row( &$result ) {
return mysql_fetch_row( $result );
}
/**
* Return the number for rows from MySQL results
*
* @param mixed $result MySQL resource
* @return integer
*/
public function num_rows( &$result ) {
return mysql_num_rows( $result );
}
/**
* Free MySQL result memory
*
* @param mixed $result MySQL resource
* @return boolean
*/
public function free_result( &$result ) {
return mysql_free_result( $result );
}
}

View File

@@ -0,0 +1,181 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Database_Mysqli extends Ai1wm_Database {
/**
* Check whether table has auto increment attribute
*
* @param string $table_name Table name
* @return boolean
*/
public function has_auto_increment( $table_name ) {
return stripos( $this->get_create_table( $table_name ), 'AUTO_INCREMENT' ) !== false;
}
/**
* Run MySQL query
*
* @param string $input SQL query
* @return mixed
*/
public function query( $input ) {
if ( ! mysqli_real_query( $this->wpdb->dbh, $input ) ) {
$mysqli_errno = 0;
// Get MySQL error code
if ( ! empty( $this->wpdb->dbh ) ) {
if ( $this->wpdb->dbh instanceof mysqli ) {
$mysqli_errno = mysqli_errno( $this->wpdb->dbh );
} else {
$mysqli_errno = 2006;
}
}
// MySQL server has gone away, try to reconnect
if ( empty( $this->wpdb->dbh ) || 2006 === $mysqli_errno ) {
if ( ! $this->wpdb->check_connection( false ) ) {
throw new Ai1wm_Database_Exception( __( 'Error reconnecting to the database. <a href="https://help.servmask.com/knowledgebase/mysql-error-reconnecting/" target="_blank">Technical details</a>', 'all-in-one-wp-migration' ), 503 );
}
mysqli_real_query( $this->wpdb->dbh, $input );
}
}
// The parameter $mode has had no effect as of PHP 8.1.0.
if ( ( PHP_MAJOR_VERSION >= 8 && PHP_MINOR_VERSION >= 1 ) || ! defined( 'MYSQLI_STORE_RESULT_COPY_DATA' ) ) {
return mysqli_store_result( $this->wpdb->dbh );
}
// Copy results from the internal mysqlnd buffer into the PHP variables fetched
return mysqli_store_result( $this->wpdb->dbh, MYSQLI_STORE_RESULT_COPY_DATA );
}
/**
* Escape string input for MySQL query
*
* @param string $input String to escape
* @return string
*/
public function escape( $input ) {
return mysqli_real_escape_string( $this->wpdb->dbh, $input );
}
/**
* Return the error code for the most recent function call
*
* @return integer
*/
public function errno() {
return mysqli_errno( $this->wpdb->dbh );
}
/**
* Return a string description of the last error
*
* @return string
*/
public function error() {
return mysqli_error( $this->wpdb->dbh );
}
/**
* Return server info
*
* @return string
*/
public function server_info() {
static $cached_result = null;
// Cache server info on first call
if ( $cached_result === null ) {
$cached_result = mysqli_get_server_info( $this->wpdb->dbh );
}
return $cached_result;
}
/**
* Return the result from MySQL query as associative array
*
* @param mixed $result MySQL resource
* @return array
*/
public function fetch_assoc( &$result ) {
if ( $result === false ) {
return false;
}
return mysqli_fetch_assoc( $result );
}
/**
* Return the result from MySQL query as row
*
* @param mixed $result MySQL resource
* @return array
*/
public function fetch_row( &$result ) {
if ( $result === false ) {
return false;
}
return mysqli_fetch_row( $result );
}
/**
* Return the number for rows from MySQL results
*
* @param mixed $result MySQL resource
* @return integer
*/
public function num_rows( &$result ) {
if ( $result === false ) {
return 0;
}
return mysqli_num_rows( $result );
}
/**
* Free MySQL result memory
*
* @param mixed $result MySQL resource
* @return boolean
*/
public function free_result( &$result ) {
if ( $result === false ) {
return true;
}
return mysqli_free_result( $result );
}
}

View File

@@ -0,0 +1,377 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Database_Sqlite extends Ai1wm_Database {
/**
* Check whether table has auto increment attribute
*
* @param string $table_name Table name
* @return boolean
*/
public function has_auto_increment( $table_name ) {
return stripos( $this->get_create_table( $table_name ), 'AUTOINCREMENT' ) !== false;
}
/**
* Get views
*
* @return array
*/
protected function get_views() {
if ( is_null( $this->views ) ) {
$where_query = array();
// Loop over table prefixes
if ( $this->get_table_prefix_filters() ) {
foreach ( $this->get_table_prefix_filters() as $prefix_filter ) {
if ( isset( $prefix_filter[0], $prefix_filter[1] ) ) {
$where_query[] = sprintf( "(`name` REGEXP '^%s' AND `name` NOT REGEXP '^%s')", $prefix_filter[0], $prefix_filter[1] );
} else {
$where_query[] = sprintf( "`name` REGEXP '^%s'", $prefix_filter[0] );
}
}
} else {
$where_query[] = 1;
}
$this->views = array();
// Loop over views
$result = $this->query( sprintf( "SELECT `name` FROM `sqlite_master` WHERE `type`='view' AND (%s)", implode( ' OR ', $where_query ) ) );
while ( $row = $this->fetch_row( $result ) ) {
if ( isset( $row[0] ) ) {
$this->views[] = $row[0];
}
}
$this->free_result( $result );
}
return $this->views;
}
/**
* Get base tables
*
* @return array
*/
protected function get_base_tables() {
if ( is_null( $this->base_tables ) ) {
$where_query = array();
// Loop over table prefixes
if ( $this->get_table_prefix_filters() ) {
foreach ( $this->get_table_prefix_filters() as $prefix_filter ) {
if ( isset( $prefix_filter[0], $prefix_filter[1] ) ) {
$where_query[] = sprintf( "(`name` REGEXP '^%s' AND `name` NOT REGEXP '^%s')", $prefix_filter[0], $prefix_filter[1] );
} else {
$where_query[] = sprintf( "`name` REGEXP '^%s'", $prefix_filter[0] );
}
}
} else {
$where_query[] = 1;
}
$this->base_tables = array();
// Loop over base tables
$result = $this->query( sprintf( "SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND (%s)", implode( ' OR ', $where_query ) ) );
while ( $row = $this->fetch_row( $result ) ) {
if ( isset( $row[0] ) ) {
$this->base_tables[] = $row[0];
}
}
$this->free_result( $result );
}
return $this->base_tables;
}
/**
* Run SQLite query
*
* @param string $input SQL query
* @return mixed
*/
public function query( $input ) {
return $this->wpdb->get_results( $input, ARRAY_A );
}
/**
* Escape string input for SQLite query
*
* @param string $input String to escape
* @return string
*/
public function escape( $input ) {
return $this->wpdb->_real_escape( $input );
}
/**
* Return the error code for the most recent function call
*
* @return integer
*/
public function errno() {
return 0;
}
/**
* Return a string description of the last error
*
* @return string
*/
public function error() {
}
/**
* Return server info
*
* @return string
*/
public function server_info() {
return $this->wpdb->db_server_info();
}
/**
* Return result as associative array
*
* @param mixed $result SQLite resource
* @return array
*/
public function fetch_assoc( &$result ) {
if ( key( $result ) === null ) {
return false;
}
$current = current( $result );
next( $result );
return $current;
}
/**
* Return the result from SQLite query as row
*
* @param mixed $result SQLite resource
* @return array
*/
public function fetch_row( &$result ) {
$current = $this->fetch_assoc( $result );
if ( $current === false ) {
return false;
}
return array_values( $current );
}
/**
* Return the number for rows from SQLite results
*
* @param mixed $result SQLite resource
* @return integer
*/
public function num_rows( &$result ) {
return count( $result );
}
/**
* Stub for free SQLite result memory
*
* @param mixed $result SQLite resource
* @return void
*/
public function free_result( &$result ) {
unset( $result );
}
/**
* Get SQLite create view
*
* @param string $table_name View name
* @return string
*/
protected function get_create_view( $table_name ) {
$result = $this->query( "SELECT `sql` FROM `sqlite_master` WHERE `name` = '{$table_name}'" );
$row = $this->fetch_assoc( $result );
// Close result cursor
$this->free_result( $result );
// Get create table
if ( isset( $row['sql'] ) ) {
return $row['sql'];
}
}
/**
* Get SQLite create table
*
* @param string $table_name Table name
* @return string
*/
protected function get_create_table( $table_name ) {
$result = $this->query( "SELECT `sql` FROM `sqlite_master` WHERE `name` = '{$table_name}'" );
$row = $this->fetch_assoc( $result );
// Close result cursor
$this->free_result( $result );
// Get create table
if ( isset( $row['sql'] ) ) {
return $row['sql'];
}
}
/**
* Replace table defaults
*
* @param string $input SQL statement
* @return string
*/
protected function replace_table_defaults( $input ) {
$pattern = array(
'/DEFAULT(\s+)(\d+)/i',
"/DEFAULT(\s+)'(.*?)'/i",
);
return preg_replace( $pattern, '', $input );
}
/**
* Replace view quotes
*
* @param string $input View value
* @return string
*/
protected function replace_view_quotes( $input ) {
return str_replace( '"', '`', $input );
}
/**
* Replace table quotes
*
* @param string $input Table value
* @return string
*/
protected function replace_table_quotes( $input ) {
return str_replace( '"', '`', $input );
}
/**
* Get SQLite primary keys
*
* @param string $table_name Table name
* @return array
*/
protected function get_primary_keys( $table_name ) {
$primary_keys = array();
// Get primary keys
$result = $this->query( "SELECT `table_info`.`name` FROM PRAGMA_TABLE_INFO('{$table_name}') AS table_info WHERE `table_info`.`pk` != 0" );
while ( $row = $this->fetch_assoc( $result ) ) {
if ( isset( $row['name'] ) ) {
$primary_keys[] = $row['name'];
}
}
// Close result cursor
$this->free_result( $result );
return $primary_keys;
}
/**
* Get SQLite column types
*
* @param string $table_name Table name
* @return array
*/
protected function get_column_types( $table_name ) {
$column_types = array();
// Get column types
$result = $this->query( "SELECT `name`, `type` FROM PRAGMA_TABLE_INFO('{$table_name}')" );
while ( $row = $this->fetch_assoc( $result ) ) {
if ( isset( $row['name'] ) ) {
$column_types[ strtolower( $row['name'] ) ] = $row['type'];
}
}
// Close result cursor
$this->free_result( $result );
return $column_types;
}
/**
* Get SQLite column names
*
* @param string $table_name Table name
* @return array
*/
public function get_column_names( $table_name ) {
$column_names = array();
// Get column names
$result = $this->query( "SELECT `name` FROM PRAGMA_TABLE_INFO('{$table_name}')" );
while ( $row = $this->fetch_assoc( $result ) ) {
if ( isset( $row['name'] ) ) {
$column_names[ strtolower( $row['name'] ) ] = $row['name'];
}
}
// Close result cursor
$this->free_result( $result );
return $column_names;
}
/**
* Get SQLite max allowed packet
*
* @return integer
*/
protected function get_max_allowed_packet() {
return PHP_INT_MAX;
}
/**
* Use SQLite transactions
*
* @return boolean
*/
protected function use_transactions() {
return false;
}
}

View File

@@ -0,0 +1,457 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Database_Utility {
protected static $db_client = null;
/**
* Set the database client instance for injection
*
* @param Ai1wm_Database $db_client Database client instance.
* @return void
*/
public static function set_client( $db_client ) {
self::$db_client = $db_client;
}
/**
* Get the database client instance, creating it if not set
*
* @return Ai1wm_Database
*/
public static function get_client() {
if ( self::$db_client === null ) {
return self::create_client();
}
return self::$db_client;
}
/**
* Create DB client to be used for DB manipulation
*
* @return Ai1wm_Database
*/
private static function create_client() {
global $wpdb;
// SQLite
if ( $wpdb instanceof WP_SQLite_DB || $wpdb instanceof WP_SQLite_DB\wpsqlitedb ) {
return new Ai1wm_Database_Sqlite( $wpdb );
}
// MariaDB
if ( ( $server_version = $wpdb->get_var( 'SELECT VERSION()' ) ) ) {
if ( stripos( $server_version, 'MariaDB' ) !== false ) {
return new Ai1wm_Database_Mariadb( $wpdb );
}
}
// MySQLi
if ( PHP_MAJOR_VERSION >= 7 ) {
return new Ai1wm_Database_Mysqli( $wpdb );
}
// MySQL
if ( empty( $wpdb->use_mysqli ) ) {
return new Ai1wm_Database_Mysql( $wpdb );
}
return new Ai1wm_Database_Mysqli( $wpdb );
}
/**
* Replace all occurrences of the search string with the replacement string.
* This function is case-sensitive.
*
* @param string $data Data to replace
* @param array $search List of string we're looking to replace
* @param array $replace What we want it to be replaced with
* @return string The original string with all elements replaced as needed
*/
public static function replace_values( $data, $search = array(), $replace = array() ) {
return strtr( $data, array_combine( $search, $replace ) );
}
/**
* Replace serialized occurrences of the search string with the replacement string.
* This function is case-sensitive.
*
* @param string $data Data to replace
* @param array $search List of string we're looking to replace
* @param array $replace What we want it to be replaced with
* @return string The original array with all elements replaced as needed
*/
public static function replace_serialized_values( $data, $search = array(), $replace = array() ) {
$pos = 0;
$result = self::parse_serialized_values( $data, $pos, $search, $replace );
if ( $pos !== strlen( $data ) ) {
// Failed to parse entire data
return strtr( $data, array_combine( $search, $replace ) );
}
return $result;
}
/**
* Parse serialized string and replace needed substitutions.
* This function is case-sensitive.
*
* @param string $data Serialized data
* @param integer $pos Character position
* @param array $search List of string we're looking to replace
* @param array $replace What we want it to be replaced with
* @return string The original string with all elements replaced as needed
*/
public static function parse_serialized_values( $data, &$pos, $search = array(), $replace = array() ) {
$length = strlen( $data );
if ( $pos >= $length ) {
return '';
}
$type = $data[ $pos ];
$pos++;
switch ( $type ) {
case 's':
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ':' ) {
$pos--;
return '';
}
$pos++;
$len_end = strpos( $data, ':', $pos );
if ( $len_end === false ) {
$pos--;
return '';
}
$str_length = (int) substr( $data, $pos, $len_end - $pos );
$pos = $len_end + 1;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '"' ) {
$pos--;
return '';
}
$pos++;
$str = substr( $data, $pos, $str_length );
$pos += $str_length;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '"' ) {
$pos--;
return '';
}
$pos++;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ';' ) {
$pos--;
return '';
}
$pos++;
// If the string is a single letter, skip any parsing or replacement.
if ( $str_length === 1 ) {
return 's:' . $str_length . ':"' . $str . '";';
}
// Attempt to parse the string as serialized data
$pos_inner = 0;
$parsed_str = self::parse_serialized_values( $str, $pos_inner, $search, $replace );
if ( $pos_inner === strlen( $str ) ) {
// The string is serialized data, use the parsed string
$new_str = $parsed_str;
} else {
// Regular string, perform replacement
$new_str = strtr( $str, array_combine( $search, $replace ) );
}
return 's:' . strlen( $new_str ) . ':"' . $new_str . '";';
case 'i':
case 'd':
case 'b':
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ':' ) {
$pos--;
return '';
}
$pos++;
$end = strpos( $data, ';', $pos );
if ( $end === false ) {
$pos--;
return '';
}
$value = substr( $data, $pos, $end - $pos );
$pos = $end + 1;
return $type . ':' . $value . ';';
case 'N':
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ';' ) {
$pos--;
return '';
}
$pos++;
return 'N;';
case 'a':
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ':' ) {
$pos--;
return '';
}
$pos++;
$len_end = strpos( $data, ':', $pos );
if ( $len_end === false ) {
$pos--;
return '';
}
$array_length = (int) substr( $data, $pos, $len_end - $pos );
$pos = $len_end + 1;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '{' ) {
$pos--;
return '';
}
$pos++;
$result = 'a:' . $array_length . ':{';
for ( $i = 0; $i < $array_length * 2; $i++ ) {
$element = self::parse_serialized_values( $data, $pos, $search, $replace );
if ( $element === '' ) {
$pos--;
return '';
}
$result .= $element;
}
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '}' ) {
$pos--;
return '';
}
$pos++;
$result .= '}';
return $result;
case 'O':
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ':' ) {
$pos--;
return '';
}
$pos++;
$class_len_end = strpos( $data, ':', $pos );
if ( $class_len_end === false ) {
$pos--;
return '';
}
$class_length = (int) substr( $data, $pos, $class_len_end - $pos );
$pos = $class_len_end + 1;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '"' ) {
$pos--;
return '';
}
$pos++;
$class_name = substr( $data, $pos, $class_length );
$pos += $class_length;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '"' ) {
$pos--;
return '';
}
$pos++;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ':' ) {
$pos--;
return '';
}
$pos++;
$prop_len_end = strpos( $data, ':', $pos );
if ( $prop_len_end === false ) {
$pos--;
return '';
}
$prop_count = (int) substr( $data, $pos, $prop_len_end - $pos );
$pos = $prop_len_end + 1;
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '{' ) {
$pos--;
return '';
}
$pos++;
$result = 'O:' . strlen( $class_name ) . ':"' . $class_name . '":' . $prop_count . ':{';
for ( $i = 0; $i < $prop_count * 2; $i++ ) {
$element = self::parse_serialized_values( $data, $pos, $search, $replace );
if ( $element === '' ) {
$pos--;
return '';
}
$result .= $element;
}
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== '}' ) {
$pos--;
return '';
}
$pos++;
$result .= '}';
return $result;
case 'R':
case 'r':
if ( ! isset( $data[ $pos ] ) || $data[ $pos ] !== ':' ) {
$pos--;
return '';
}
$pos++;
$end = strpos( $data, ';', $pos );
if ( $end === false ) {
$pos--;
return '';
}
$ref = substr( $data, $pos, $end - $pos );
$pos = $end + 1;
return $type . ':' . $ref . ';';
default:
$pos--;
return '';
}
}
/**
* Parse MySQL server version
*
* @param string $info Server info
* @return string
*/
public static function parse_server_version( $info ) {
$matches = array();
if ( preg_match( '/(\d+\.\d+\.\d+)-(\d+\.\d+\.\d+)/i', $info, $matches ) ) {
if ( isset( $matches[2] ) ) {
return $matches[2];
}
}
if ( preg_match( '/(\d+\.\d+\.\d+)/i', $info, $matches ) ) {
if ( isset( $matches[1] ) ) {
return $matches[1];
}
}
return '0.0.0';
}
/**
* Escape MySQL special characters
*
* @param string $data Data to escape
* @return string
*/
public static function escape_mysql( $data ) {
return strtr(
$data,
array_combine(
array( "\x00", "\n", "\r", '\\', "'", '"', "\x1a" ),
array( '\\0', '\\n', '\\r', '\\\\', "\\'", '\\"', '\\Z' )
)
);
}
/**
* Unescape MySQL special characters
*
* @param string $data Data to unescape
* @return string
*/
public static function unescape_mysql( $data ) {
return strtr(
$data,
array_combine(
array( '\\0', '\\n', '\\r', '\\\\', "\\'", '\\"', '\\Z' ),
array( "\x00", "\n", "\r", '\\', "'", '"', "\x1a" )
)
);
}
/**
* Encode base64 characters
*
* @param string $data Data to encode
* @return string
*/
public static function base64_encode( $data ) {
return base64_encode( $data );
}
/**
* Encode base64 characters
*
* @param string $data Data to decode
* @return string
*/
public static function base64_decode( $data ) {
return base64_decode( $data );
}
/**
* Validate base64 data
*
* @param string $data Data to validate
* @return boolean
*/
public static function base64_validate( $data ) {
return base64_encode( base64_decode( $data ) ) === $data;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Directory {
/**
* Create directory (recursively)
*
* @param string $path Path to the directory
* @return boolean
*/
public static function create( $path ) {
if ( @is_dir( $path ) ) {
return true;
}
return @mkdir( $path, 0777, true );
}
/**
* Delete directory (recursively)
*
* @param string $path Path to the directory
* @return boolean
*/
public static function delete( $path ) {
if ( @is_dir( $path ) ) {
try {
// Iterate over directory
$iterator = new Ai1wm_Recursive_Directory_Iterator( $path );
// Recursively iterate over directory
$iterator = new Ai1wm_Recursive_Iterator_Iterator( $iterator, RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
// Remove files and directories
foreach ( $iterator as $item ) {
if ( $item->isDir() ) {
@rmdir( $item->getPathname() );
} else {
@unlink( $item->getPathname() );
}
}
} catch ( Exception $e ) {
}
return @rmdir( $path );
}
return false;
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_File_Htaccess {
/**
* Create backups .htaccess file
*
* @param string $path Path to file
* @return boolean
*/
public static function backups( $path ) {
return Ai1wm_File::create(
$path,
implode(
PHP_EOL,
array(
'<IfModule mod_mime.c>',
' AddType application/octet-stream .wpress',
'</IfModule>',
'<IfModule mod_dir.c>',
' DirectoryIndex index.php',
'</IfModule>',
'<IfModule mod_autoindex.c>',
' Options -Indexes',
'</IfModule>',
)
)
);
}
/**
* Create storage .htaccess file
*
* @param string $path Path to file
* @return boolean
*/
public static function storage( $path ) {
return Ai1wm_File::create(
$path,
implode(
PHP_EOL,
array(
'<IfModule mod_authz_core.c>',
' <FilesMatch ".*">',
' Require all denied',
' </FilesMatch>',
' <FilesMatch "\.log$">',
' Require all granted',
' </FilesMatch>',
'</IfModule>',
'<IfModule !mod_authz_core.c>',
' Order allow,deny',
' Deny from all',
' <FilesMatch "\.log$">',
' Order allow,deny',
' Allow from all',
' </FilesMatch>',
'</IfModule>',
'<IfModule mod_mime.c>',
' AddType text/plain .log',
'</IfModule>',
'<IfModule mod_dir.c>',
' DirectoryIndex index.php',
'</IfModule>',
'<IfModule mod_autoindex.c>',
' Options -Indexes',
'</IfModule>',
)
)
);
}
/**
* Create LiteSpeed .htaccess file
*
* @param string $path Path to file
* @return boolean
*/
public static function litespeed( $path ) {
return Ai1wm_File::insert_with_markers(
$path,
'LiteSpeed',
array(
'<IfModule Litespeed>',
' SetEnv noabort 1',
'</IfModule>',
)
);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_File_Index {
/**
* Create index file
*
* @param string $path Path to file
* @return boolean
*/
public static function create( $path ) {
return Ai1wm_File::create( $path, 'Kangaroos cannot jump here' );
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_File_Robots {
/**
* Create robots.txt file
*
* @param string $path Path to file
* @return boolean
*/
public static function create( $path ) {
return Ai1wm_File::create(
$path,
implode(
PHP_EOL,
array(
'User-agent: *',
'Disallow: /ai1wm-backups/',
'Disallow: /wp-content/ai1wm-backups/',
)
)
);
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_File_Webconfig {
/**
* Create backups web.config file
*
* @param string $path Path to file
* @return boolean
*/
public static function backups( $path ) {
return Ai1wm_File::create(
$path,
implode(
PHP_EOL,
array(
'<?xml version="1.0" encoding="utf-8"?>',
'<configuration>',
' <system.webServer>',
' <staticContent>',
' <mimeMap fileExtension=".wpress" mimeType="application/octet-stream" />',
' </staticContent>',
' <defaultDocument>',
' <files>',
' <add value="index.php" />',
' </files>',
' </defaultDocument>',
' <directoryBrowse enabled="false" />',
' </system.webServer>',
'</configuration>',
)
)
);
}
/**
* Create storage web.config file
*
* @param string $path Path to file
* @return boolean
*/
public static function storage( $path ) {
return Ai1wm_File::create(
$path,
implode(
PHP_EOL,
array(
'<?xml version="1.0" encoding="utf-8"?>',
'<configuration>',
' <system.webServer>',
' <security>',
' <authorization>',
' <deny users="*" />',
' </authorization>',
' </security>',
' <requestFiltering>',
' <fileExtensions allowUnlisted="false">',
' <add fileExtension=".log" allowed="true" />',
' </fileExtensions>',
' </requestFiltering>',
' <staticContent>',
' <mimeMap fileExtension=".log" mimeType="text/plain" />',
' </staticContent>',
' <defaultDocument>',
' <files>',
' <add value="index.php" />',
' </files>',
' </defaultDocument>',
' <directoryBrowse enabled="false" />',
' </system.webServer>',
'</configuration>',
)
)
);
}
}

View File

@@ -0,0 +1,98 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_File {
/**
* Create a file with content
*
* @param string $path Path to the file
* @param string $content Content of the file
* @return boolean
*/
public static function create( $path, $content ) {
if ( ! @file_exists( $path ) ) {
if ( ! @is_writable( dirname( $path ) ) ) {
return false;
}
if ( ! @touch( $path ) ) {
return false;
}
} elseif ( ! @is_writable( $path ) ) {
return false;
}
// No changes were added
if ( function_exists( 'md5_file' ) ) {
if ( @md5_file( $path ) === md5( $content ) ) {
return true;
}
}
$is_written = false;
if ( ( $handle = @fopen( $path, 'w' ) ) !== false ) {
if ( @fwrite( $handle, $content ) !== false ) {
$is_written = true;
}
@fclose( $handle );
}
return $is_written;
}
/**
* Create a file with marker and content
*
* @param string $path Path to the file
* @param string $marker Name of the marker
* @param string $content Content of the file
* @return boolean
*/
public static function insert_with_markers( $path, $marker, $content ) {
return @insert_with_markers( $path, $marker, $content );
}
/**
* Delete a file by path
*
* @param string $path Path to the file
* @return boolean
*/
public static function delete( $path ) {
if ( ! @file_exists( $path ) ) {
return false;
}
return @unlink( $path );
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Recursive_Exclude_Filter extends RecursiveFilterIterator {
protected $exclude = array();
public function __construct( RecursiveIterator $iterator, $exclude = array() ) {
parent::__construct( $iterator );
if ( is_array( $exclude ) ) {
foreach ( $exclude as $path ) {
$this->exclude[] = ai1wm_replace_forward_slash_with_directory_separator( $path );
}
}
}
#[\ReturnTypeWillChange]
public function accept() {
if ( in_array( ai1wm_replace_forward_slash_with_directory_separator( $this->getInnerIterator()->getSubPathname() ), $this->exclude ) ) {
return false;
}
if ( in_array( ai1wm_replace_forward_slash_with_directory_separator( $this->getInnerIterator()->getPathname() ), $this->exclude ) ) {
return false;
}
if ( in_array( ai1wm_replace_forward_slash_with_directory_separator( $this->getInnerIterator()->getPath() ), $this->exclude ) ) {
return false;
}
if ( strpos( $this->getInnerIterator()->getSubPathname(), "\n" ) !== false ) {
return false;
}
if ( strpos( $this->getInnerIterator()->getSubPathname(), "\r" ) !== false ) {
return false;
}
return true;
}
#[\ReturnTypeWillChange]
public function getChildren() {
return new self( $this->getInnerIterator()->getChildren(), $this->exclude );
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Recursive_Extension_Filter extends RecursiveFilterIterator {
protected $include = array();
public function __construct( RecursiveIterator $iterator, $include = array() ) {
parent::__construct( $iterator );
if ( is_array( $include ) ) {
$this->include = $include;
}
}
#[\ReturnTypeWillChange]
public function accept() {
if ( $this->getInnerIterator()->isFile() ) {
if ( ! in_array( pathinfo( $this->getInnerIterator()->getFilename(), PATHINFO_EXTENSION ), $this->include ) ) {
return false;
}
}
return true;
}
#[\ReturnTypeWillChange]
public function getChildren() {
return new self( $this->getInnerIterator()->getChildren(), $this->include );
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Recursive_Directory_Iterator extends RecursiveDirectoryIterator {
public function __construct( $path ) {
parent::__construct( $path );
// Skip current and parent directory
$this->skipdots();
}
#[\ReturnTypeWillChange]
public function rewind() {
parent::rewind();
// Skip current and parent directory
$this->skipdots();
}
#[\ReturnTypeWillChange]
public function next() {
parent::next();
// Skip current and parent directory
$this->skipdots();
}
/**
* Returns whether current entry is a directory and not '.' or '..'
*
* Explicitly set allow links flag, because RecursiveDirectoryIterator::FOLLOW_SYMLINKS
* is not supported by <= PHP 5.3.0
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function hasChildren( $allow_links = true ) {
return parent::hasChildren( $allow_links );
}
protected function skipdots() {
while ( $this->isDot() ) {
parent::next();
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Recursive_Iterator_Iterator extends RecursiveIteratorIterator {
}