├── .distignore
├── .env.example
├── .github
├── ISSUE_TEMPLATE
│ └── pre-release-testing.md
└── workflows
│ ├── deploy-wp.sh
│ ├── deploy.yml
│ ├── update-tested-up-to.sh
│ └── update-tested-up-to.yml
├── .gitignore
├── README.md
├── _config.yml
├── build.sh
├── docker-compose.yml
├── docker
├── Dockerfile
└── entrypoint.sh
├── docs
├── local-dev.md
├── release-process.md
├── reporting-bugs.md
├── testing-cli-commands.md
├── testing-pull-requests.md
└── workflows.md
├── package-lock.json
├── package.json
├── phpstan-baseline.neon
├── phpstan.neon
├── webpack.dev.js
├── webpack.prod.js
└── xcloner-backup-and-restore
├── CHANGELOG.txt
├── LICENSE.txt
├── README.txt
├── admin
├── assets
│ ├── btn_google_signin_dark_pressed_web.png
│ ├── database-icon.png
│ ├── file-icon-d.png
│ ├── file-icon-f.png
│ ├── file-icon-l.png
│ ├── file-icon-root.png
│ └── table-icon.png
├── class-xcloner-admin.php
├── css
│ ├── jquery.dataTables.min.css
│ ├── materialize.min.css
│ ├── responsive.dataTables.css
│ └── xcloner-admin.css
├── fonts
│ └── roboto
│ │ ├── Roboto-Bold.eot
│ │ ├── Roboto-Bold.ttf
│ │ ├── Roboto-Bold.woff
│ │ ├── Roboto-Bold.woff2
│ │ ├── Roboto-Light.eot
│ │ ├── Roboto-Light.ttf
│ │ ├── Roboto-Light.woff
│ │ ├── Roboto-Light.woff2
│ │ ├── Roboto-Medium.eot
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-Medium.woff
│ │ ├── Roboto-Medium.woff2
│ │ ├── Roboto-Regular.eot
│ │ ├── Roboto-Regular.ttf
│ │ ├── Roboto-Regular.woff
│ │ ├── Roboto-Regular.woff2
│ │ ├── Roboto-Thin.eot
│ │ ├── Roboto-Thin.ttf
│ │ ├── Roboto-Thin.woff
│ │ └── Roboto-Thin.woff2
├── images
│ ├── Sorting icons.psd
│ ├── banners
│ │ ├── CF Banner 728x90 blue.jpg
│ │ └── CF Banner 728x90 red.jpg
│ ├── favicon.ico
│ ├── sort_asc.png
│ ├── sort_asc_disabled.png
│ ├── sort_both.png
│ ├── sort_desc.png
│ ├── sort_desc_disabled.png
│ └── xcloner-logo.svg
├── index.php
├── js
│ ├── dataTables.responsive.js
│ ├── index.js
│ ├── index.min.js
│ ├── index.min.js.LICENSE.txt
│ ├── index.min.js.map
│ ├── jquery.dataTables.min.js
│ ├── materialize.min.js
│ ├── xcloner-admin.js
│ ├── xcloner-backup-class.js
│ ├── xcloner-manage-backups-class.js
│ ├── xcloner-remote-storage-class.js
│ ├── xcloner-restore-class.js
│ └── xcloner-scheduler-class.js
└── partials
│ ├── remote_storage
│ ├── aws.php
│ ├── azure.php
│ ├── backblaze.php
│ ├── dropbox.php
│ ├── ftp.php
│ ├── gdrive.php
│ ├── index.html
│ ├── local.php
│ ├── onedrive.php
│ ├── sftp.php
│ └── webdav.php
│ ├── xcloner_console_page.php
│ ├── xcloner_generate_backups_page.php
│ ├── xcloner_header.php
│ ├── xcloner_init_page.php
│ ├── xcloner_manage_backups_page.php
│ ├── xcloner_remote_storage_page.php
│ ├── xcloner_restore_page.php
│ └── xcloner_scheduled_backups_page.php
├── composer.json
├── composer.lock
├── index.php
├── languages
├── xcloner-backup-and-restore-de_DE.mo
├── xcloner-backup-and-restore-de_DE.po
├── xcloner-backup-and-restore-ro_RO.mo
├── xcloner-backup-and-restore-ro_RO.po
├── xcloner-backup-and-restore.mo
└── xcloner-backup-and-restore.po
├── lib
├── Xcloner.php
├── Xcloner_Activator.php
├── Xcloner_Api.php
├── Xcloner_Archive.php
├── Xcloner_Archive_Restore.php
├── Xcloner_Composer_Actions.php
├── Xcloner_Database.php
├── Xcloner_Deactivator.php
├── Xcloner_Encryption.php
├── Xcloner_File_Transfer.php
├── Xcloner_Filesystem.php
├── Xcloner_Loader.php
├── Xcloner_Logger.php
├── Xcloner_Remote_Storage.php
├── Xcloner_Requirements.php
├── Xcloner_Restore.php
├── Xcloner_Sanitization.php
├── Xcloner_Scheduler.php
├── Xcloner_Settings.php
├── Xcloner_cli.php
└── Xcloner_i18n.php
├── uninstall.php
└── xcloner.php
/.distignore:
--------------------------------------------------------------------------------
1 | /vendor/**.md
2 | /vendor/**tests/
3 | /vendor/bin/
4 | /admin/js/index.js
5 | /admin/js/xcloner*
6 | /admin/js/materialize.min.js
7 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | WORDPRESS_DEBUG=true
2 | WORDPRESS_PORT=8080
3 | WORDPRESS_DB_HOST=db
4 | WORDPRESS_DB_USER=wordpress
5 | WORDPRESS_DB_PASSWORD=wordpress
6 | WORDPRESS_DB_NAME=wordpress
7 | WORDPRESS_URL=https://wordpress.xcloner.local
8 | WORDPRESS_TITLE='XCloner Testing'
9 | WORDPRESS_ADMIN_USER=admin
10 | WORDPRESS_ADMIN_PASSWORD=admin
11 | WORDPRESS_ADMIN_EMAIL=hello@watchful.net
12 |
13 | XCLONER_GDRIVE_CLIENT_ID:
14 | XCLONER_GDRIVE_REDIRECT_URL:
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/pre-release-testing.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Pre-release testing
3 | about: Use this template to test new versions before release.
4 | title: "[TESTING] Testing for version x.y.z"
5 | labels: testing
6 | assignees: jimiero
7 |
8 | ---
9 |
10 | # Settings
11 | - [ ] Basic Settings can be saved
12 | - [ ] Remote Storages settings show `VALID` message when saved.
13 | - [ ] Amazon S3
14 | - [ ] Azure Blob
15 | - [ ] Backblaze
16 | - [ ] BOX
17 | - [ ] Dropbox
18 | - [ ] Google Drive
19 | - [ ] SFTP
20 | - [ ] WebDav
21 |
22 | # Generate Local Backup
23 | - [ ] Full backup with default settings completes successfully.
24 | - [ ] Partial backup with some tables excluded completes successfully.
25 | - [ ] Partial backup with some files excludes completes successfully.
26 | - [ ] Partial backup with additional databases included completes successfully.
27 | - [ ] Backup options
28 | - [ ] Backup process completes successfully with encryption enabled
29 | - [ ] Backup process completes successfully when `transfer to Dropbox` enabled.
30 | - [ ] Check that backup archive successfuly uploaded in Dropbox account.
31 | - [ ] Backup process completes successfully when `transferr to Dropbox` enabled and `delete from local storage` selected.
32 | - [ ] Check that backup archive successfuly deleted from Dropbox account.
33 |
34 | # Send backups to remote storage
35 |
36 | In these tests, use a very a simple backup that will complete quickly and have a very small size. For example, do not include any databases and exclude all files except `index.php`.
37 |
38 | - [ ] Partial backup completes successfully and send file to SFTP location.
39 | - [ ] Partial backup completes successfully and send file to Dropbox location (likely tested above).
40 | - [ ] Partial backup completes successfully and send file to Azure Blob location.
41 | - [ ] Partial backup completes successfully and send file to Amazon S3 location.
42 | - [ ] Partial backup completes successfully and send file to Backblaze location.
43 | - [ ] Partial backup completes successfully and send file to BOX location.
44 |
45 | # Manage Local Backups
46 | - [ ] Make sure backups are listed.
47 | - [ ] Make sure backups can be deleted when the icon is clicked.
48 | - [ ] Make sure backups can be uploaded to DropBox when the icon is clicked.
49 | - [ ] Make sure backups can be downloaded when the icon is clicked.
50 | - [ ] Make sure backup contents can be listed when the icon is clicked.
51 | - [ ] Make sure an encrypted backup can be unencrypted when the icon is clicked.
52 |
53 | # Manage Remote Backups
54 | - [ ] Dropbox backups are listed.
55 | - [ ] Dropbox backups can be deleted when the icon is clicked.
56 | - [ ] Dropbox backups can be downloaded when the icon is clicked.
57 | - [ ] Dropbox backup contents can be listed when the icon is clicked.
58 | - [ ] Encrypted Dropbox backups can be unencrypted when the icon is clicked.
59 |
60 | # Scheduling Backups
61 | - [ ] Create a Scheduled Profile
62 | - [ ] Check the correct recurrence of a scheduled Profile based on the Wordpress cronjob execution
63 |
64 | # Restore Backups
65 | - [ ] Restore all files from a local backup.
66 | - [ ] Restore database from a local backup.
67 | - [ ] Migrate files from a backup to a different domain.
68 | - [ ] Migrate the database from a backup to a different domain.
69 |
70 | # Watchful Backups
71 | - [ ] Site connects/validates in Watchful (test `Refresh data` success).
72 | - [ ] XCloner backup works as expected in Watchful when using the `Start Backup` button.
73 |
74 | # Other tests
75 | - [ ] Trigger any backup profile from the XCloner CLI.
76 | - [ ] Trigger any backup profile from the WP CLI.
77 | - [ ] Check if enabling/disabling logs in XCloner settings works as expected.
78 | - [ ] Check if XCloner version has been incremented from previous release.
79 | - [ ] Check if release has changelog notes.
80 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-wp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [[ -z "$SVN_USERNAME" ]] && [[ -z "$BUILD_ONLY" ]]; then
4 | echo "x Missing SVN_USERNAME env variable"
5 | exit 1
6 | fi
7 |
8 | if [[ -z "$SVN_PASSWORD" ]] && [[ -z "$BUILD_ONLY" ]]; then
9 | echo "x Missing SVN_PASSWORD env variable"
10 | exit 1
11 | fi
12 |
13 | if [[ -z "$VERSION" ]]; then
14 | VERSION="${GITHUB_REF#refs/tags/}"
15 | VERSION="${VERSION#v}"
16 | fi
17 |
18 | rx='^([0-9]+\.){2}(\*|[0-9]+)(-.*)?$'
19 | if [[ $VERSION =~ $rx ]]; then
20 | echo "ℹ VERSION is $VERSION"
21 | elif [[ -z "$BUILD_ONLY" ]]; then
22 | echo "x Unable to validate version: '$VERSION'"
23 | exit 1
24 | fi
25 |
26 | CURRENT_DIR=$(pwd)
27 | SLUG="xcloner-backup-and-restore"
28 |
29 | SVN_URL="https://plugins.svn.wordpress.org/${SLUG}/"
30 | SVN_DIR="${CURRENT_DIR}/${SLUG}-svn"
31 | BUILD_DIR="${CURRENT_DIR}/${SLUG}-build"
32 |
33 | echo "➤ Building Webpack bundle"
34 | export NODE_OPTIONS=--openssl-legacy-provider
35 | npm install || exit 1
36 | npm run build-prod || exit 1
37 |
38 | echo "➤ Copying files to build directory"
39 | rsync -av --delete "${CURRENT_DIR}/${SLUG}/" "${BUILD_DIR}/"
40 |
41 | echo "➤ Install composer dependencies without dev dependencies"
42 | cd "${BUILD_DIR}" || exit 1
43 | composer install --no-dev --prefer-dist -o --no-interaction || exit 1
44 | cd "${CURRENT_DIR}" || exit 1
45 |
46 | if [[ -n "$BUILD_ONLY" ]]; then
47 | echo "✓ Plugin built!"
48 | exit 0
49 | fi
50 |
51 | echo "➤ Checking out SVN repository..."
52 | svn checkout "${SVN_URL}/trunk/" "${SVN_DIR}/trunk/"
53 | cd "${CURRENT_DIR}" || exit 1
54 |
55 | echo "➤ Coping files to SVN repository..."
56 | rsync -r --exclude-from=".distignore" "${BUILD_DIR}/" "${SVN_DIR}/trunk/"
57 |
58 | echo "➤ Adding files to SVN repository..."
59 | cd "${SVN_DIR}/trunk" || exit 1
60 | svn st | grep '^?' | awk '{print $2}' | xargs -r svn add
61 | svn st | grep '^!' | awk '{print $2}' | xargs -r svn rm
62 |
63 | echo "➤ Committing files to SVN repository..."
64 | svn commit -m "v${VERSION}" --no-auth-cache --non-interactive --username "${SVN_USERNAME}" --password "${SVN_PASSWORD}" --config-option=servers:global:http-timeout=300 || exit 1
65 |
66 | echo "➤ Coping tag to SVN repository..."
67 | cd "${SVN_DIR}" || exit 1
68 | svn cp "${SVN_URL}/trunk" "${SVN_URL}/tags/${VERSION}" -m "Tagging v${VERSION}" --no-auth-cache --non-interactive --username "${SVN_USERNAME}" --password "${SVN_PASSWORD}" --config-option=servers:global:http-timeout=300 || exit 1
69 |
70 | echo "✓ Plugin deployed!"
71 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to WordPress.org
2 | on: workflow_dispatch
3 | jobs:
4 | deploy:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Checkout code
8 | uses: actions/checkout@master
9 | - name: Setup PHP
10 | uses: shivammathur/setup-php@v2
11 | with:
12 | php-version: '7.3'
13 | tools: composer
14 | - name: Execute script to deploy on WordPress.org
15 | run: ${{ github.workspace }}/.github/workflows/deploy-wp.sh
16 | env:
17 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
18 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
--------------------------------------------------------------------------------
/.github/workflows/update-tested-up-to.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [[ -z "$SVN_USERNAME" ]]; then
4 | echo "x Missing SVN_USERNAME env variable"
5 | exit 1
6 | fi
7 |
8 | if [[ -z "$SVN_PASSWORD" ]]; then
9 | echo "x Missing SVN_PASSWORD env variable"
10 | exit 1
11 | fi
12 |
13 | SLUG="xcloner-backup-and-restore"
14 | README_FILE_PATH="./xcloner-backup-and-restore/README.txt"
15 | SVN_URL="https://plugins.svn.wordpress.org/${SLUG}/"
16 | SVN_DIR="./svn-${SLUG}"
17 |
18 | echo "➤ Checking out SVN repository..."
19 | svn checkout "$SVN_URL" "$SVN_DIR" --depth immediates
20 |
21 | svn update --set-depth infinity "$SVN_DIR/trunk"
22 |
23 | echo "➤ Coping README file to SVN repository..."
24 | rsync -rc "$README_FILE_PATH" "${SVN_DIR}/trunk" --delete --delete-excluded
25 |
26 | echo "➤ Adding files to SVN repository..."
27 | cd "$SVN_DIR"
28 | svn add . --force > /dev/null
29 |
30 | echo "➤ Committing files to SVN repository..."
31 | svn commit -m "Update tested up to" --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"
32 |
33 | echo "✓ Updated WordPress tested up to version!"
34 |
--------------------------------------------------------------------------------
/.github/workflows/update-tested-up-to.yml:
--------------------------------------------------------------------------------
1 | name: Update tested up to version
2 | on: workflow_dispatch
3 | jobs:
4 | deploy-wp:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 | - name: Update "tested up to version" to WordPress SVN
9 | run: |
10 | sudo apt-get update && sudo apt-get install -y subversion
11 | ${{ github.workspace }}/.github/workflows/update-tested-up-to.sh
12 | env:
13 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
14 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | xcloner-backup-and-restore/vendor/
3 | .idea/
4 |
5 | docker-compose.override.yml
6 |
7 | /xcloner-backup-and-restore-build/
8 | /xcloner-backup-and-restore-svn/
9 | /xcloner-backup-and-restore*.zip
10 |
11 | .env
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XCloner WordPress Plugin - Backup and Restore
2 |
3 | [](https://twitter.com/WatchfulDashbrd)
4 | [](LICENSE.txt)
5 | [](https://scrutinizer-ci.com/g/ovidiul/XCloner-WordPress/?branch=master)
6 | [](https://scrutinizer-ci.com/g/ovidiul/XCloner-WordPress/build-status/master)
7 |
8 | Backup your WordPress site, restore to any web location, send your backups to Dropbox, Amazon S3, Azure, FTP, SFTP and many others with XCloner backup plugin.
9 |
10 |
11 | XCloner is a Backup and Restore plugin that is perfectly integrated with WordPress.
12 |
13 | XCloner design was specifically created to Generate custom backups of any LAMP website through custom admin inputs, and to be able to Restore the clone on any other location with the help of the automatic Restore script we provide!
14 |
15 | XCloner Backup tool uses Open Source standards like TAR, Mysql and CSV formats so you can rest assured your backups can be restored in a variety of ways, giving you more flexibility and full control.
16 |
17 | ## Features
18 |
19 | * Backup and Restore your WordPress site easily
20 | * Create compressed and uncompressed backups using TAR open source format
21 | * Create encrypted backups archives with AES-128-CBC algorithm
22 | * Create automated backups from your Scheduled Backups Section
23 | * Received email notifications of created backups
24 | * Generate automatic backups based on cronjobs, it can run daily, weekly, monthly or even hourly
25 | * Restore your backups on any other location, XCloner will attempt to extract the backup archive files for you, as well as import the mysql dump and update the WordPress config details
26 | * Upload your backups to Remote Storage locations supporting FTP, SFTP, Dropbox, AWS, Azure Blob and many more to come
27 | * Watch every step of XCloner through it's built in debugger
28 | * Although we have optimized XCloner to run properly on most hosts, we give Developers options to customize its running speed and avoid backup timeouts, all from the XCloner Config-> System Options
29 | * Ability to split backups into multiple smaller parts if a certain size limit is reached
30 |
31 | ## Installation
32 |
33 | 1. Upload the plugin directory to wp-content/plugins directory
34 | 2. Activate the plugin
35 | 3. Access the plugin Dashboard from the Admin Sidebar -> Site Backup Menu
36 |
37 | ## UPGRADE
38 |
39 | You can do it easily from the WordPress backend.
40 |
41 | ## Frequently Asked Questions
42 |
43 | Where does XCloner keep it's database backups?
44 |
45 | XCloner stores them in separate mysql dump files, inside a folder called xcloner-XXXXX inside the backup archive root path, where XXXXX is a hash number that is identical with the last 5 characters of the backup name,
46 | so if the backup name is backup_localhost-2017-02-16_15-36-sql-1c6c6.tgz , the mysql backup file will be stored in xcloner-1c6c6/ folder.
47 |
48 | How do I restore my backup?
49 |
50 | XCloner provide an easy-to-use restore script available in the Site Backup -> Restore Backups menu, the process is being described there as well.
51 |
52 | If the XCloner Restore option fails, you can manually restore your backup as follows:
53 |
54 | 1. extract the backup archive files to your new location
55 | 2. locate the xcloner-XXXXX folder inside your backup root folder, and look for the mysql backup in database-sql and import it through phpmyadmin
56 | 3. update your wp-config.php file to reflect the new mysql details
57 |
58 | How do I know which files were include in the backup?
59 |
60 | The XCloner Manager Backups Panel provides an easy utility to view each backup content files list. It also stores a copy of the archived backup files inside the xcloner-XXXXX/backup_files.csv file in an easy to read CSV format.
61 |
62 | Do you have a log for the created backup?
63 |
64 | Yes, if XCloner Logger option is enabled, it will store a log file inside the xcloner-XXXXX folder inside the backup archive, file is named xcloner-xxxxx.log
65 |
66 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | DATE=$(date +"%Y%m%d%H%M")
2 | SLUG="xcloner-backup-and-restore"
3 | BUILD_ONLY="true"
4 | BUILD_SCRIPT_PATH="./.github/workflows/deploy-wp.sh"
5 | BUILD_DIR="xcloner-backup-and-restore-build"
6 |
7 | export BUILD_ONLY
8 |
9 | echo "Building plugin"
10 |
11 | bash "${BUILD_SCRIPT_PATH}"
12 |
13 | echo "Creating archive"
14 | cd "${BUILD_DIR}" || exit 1
15 | mkdir "${SLUG}"
16 | mv ./* "${SLUG}"
17 | zip -r "xcloner-backup-and-restore-${DATE}.zip" "${SLUG}" || exit 1
18 | mv "xcloner-backup-and-restore-${DATE}.zip" ../
19 | cd ..
20 |
21 | echo "Removing build directory"
22 | rm -rf "${BUILD_DIR}"
23 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | name: xcloner-testing
2 |
3 | services:
4 | wordpress:
5 | depends_on:
6 | - db
7 | build:
8 | context: .
9 | dockerfile: docker/Dockerfile
10 | volumes:
11 | - ./xcloner-backup-and-restore:/src/xcloner-backup-and-restore:ro
12 | ports:
13 | - "${WORDPRESS_PORT:-8080}:80"
14 | environment:
15 | WORDPRESS_DEBUG: "${WORDPRESS_DEBUG:-false}"
16 | WORDPRESS_DB_HOST: "${WORDPRESS_DB_HOST:-db}"
17 | WORDPRESS_DB_USER: "${WORDPRESS_DB_USER:-wordpress}"
18 | WORDPRESS_DB_PASSWORD: "${WORDPRESS_DB_PASSWORD:-wordpress}"
19 | WORDPRESS_DB_NAME: "${WORDPRESS_DB_NAME:-wordpress}"
20 | WORDPRESS_URL: "${WORDPRESS_URL:-http://localhost:8080}"
21 | WORDPRESS_TITLE: "${WORDPRESS_TITLE:-WordPress}"
22 | WORDPRESS_ADMIN_USER: "${WORDPRESS_ADMIN_USER:-admin}"
23 | WORDPRESS_ADMIN_PASSWORD: "${WORDPRESS_ADMIN_PASSWORD:-password}"
24 | WORDPRESS_ADMIN_EMAIL: "${WORDPRESS_ADMIN_EMAIL:-example@example.com}"
25 | XCLONER_GDRIVE_CLIENT_ID: "${XCLONER_GDRIVE_CLIENT_ID:-}"
26 | XCLONER_GDRIVE_REDIRECT_URL: "${XCLONER_GDRIVE_REDIRECT_URL:-}"
27 |
28 | db:
29 | image: mariadb:10.5.8
30 | volumes:
31 | - db_data:/var/lib/mysql
32 | environment:
33 | MYSQL_ROOT_PASSWORD: "${WORDPRESS_DB_PASSWORD:-wordpress}"
34 | MYSQL_DATABASE: "${WORDPRESS_DB_NAME:-wordpress}"
35 | MYSQL_USER: "${WORDPRESS_DB_USER:-wordpress}"
36 | MYSQL_PASSWORD: "${WORDPRESS_DB_PASSWORD:-wordpress}"
37 | healthcheck:
38 | test: "/usr/bin/mysql --user=wordpress --password=wordpress --execute \"SHOW DATABASES;\""
39 | interval: 3s
40 | timeout: 1s
41 | retries: 10
42 |
43 | volumes:
44 | db_data: {}
45 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM wordpress:latest
2 |
3 | RUN apt-get update
4 | RUN apt-get install -y inotify-tools rsync wait-for-it
5 |
6 | COPY docker/entrypoint.sh /usr/local/bin/
7 | RUN chmod +x /usr/local/bin/entrypoint.sh
8 |
9 | RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
10 | RUN chmod +x wp-cli.phar
11 | RUN mv wp-cli.phar /usr/local/bin/wp
12 |
13 | ENTRYPOINT ["entrypoint.sh"]
14 | CMD ["apache2-foreground"]
15 |
--------------------------------------------------------------------------------
/docker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #!/usr/bin/env bash
3 | set -Eeuo pipefail
4 |
5 | if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then
6 | uid="$(id -u)"
7 | gid="$(id -g)"
8 | if [ "$uid" = '0' ]; then
9 | case "$1" in
10 | apache2*)
11 | user="${APACHE_RUN_USER:-www-data}"
12 | group="${APACHE_RUN_GROUP:-www-data}"
13 |
14 | # strip off any '#' symbol ('#1000' is valid syntax for Apache)
15 | pound='#'
16 | user="${user#$pound}"
17 | group="${group#$pound}"
18 | ;;
19 | *) # php-fpm
20 | user='www-data'
21 | group='www-data'
22 | ;;
23 | esac
24 | else
25 | user="$uid"
26 | group="$gid"
27 | fi
28 |
29 | if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then
30 | # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory)
31 | if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then
32 | chown "$user:$group" .
33 | fi
34 |
35 | echo >&2 "WordPress not found in $PWD - copying now..."
36 | if [ -n "$(find -mindepth 1 -maxdepth 1 -not -name wp-content)" ]; then
37 | echo >&2 "WARNING: $PWD is not empty! (copying anyhow)"
38 | fi
39 | sourceTarArgs=(
40 | --create
41 | --file -
42 | --directory /usr/src/wordpress
43 | --owner "$user" --group "$group"
44 | )
45 | targetTarArgs=(
46 | --extract
47 | --file -
48 | )
49 | if [ "$uid" != '0' ]; then
50 | # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted"
51 | targetTarArgs+=( --no-overwrite-dir )
52 | fi
53 | # loop over "pluggable" content in the source, and if it already exists in the destination, skip it
54 | # https://github.com/docker-library/wordpress/issues/506 ("wp-content" persisted, "akismet" updated, WordPress container restarted/recreated, "akismet" downgraded)
55 | for contentPath in \
56 | /usr/src/wordpress/.htaccess \
57 | /usr/src/wordpress/wp-content/*/*/ \
58 | ; do
59 | contentPath="${contentPath%/}"
60 | [ -e "$contentPath" ] || continue
61 | contentPath="${contentPath#/usr/src/wordpress/}" # "wp-content/plugins/akismet", etc.
62 | if [ -e "$PWD/$contentPath" ]; then
63 | echo >&2 "WARNING: '$PWD/$contentPath' exists! (not copying the WordPress version)"
64 | sourceTarArgs+=( --exclude "./$contentPath" )
65 | fi
66 | done
67 | tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}"
68 | echo >&2 "Complete! WordPress has been successfully copied to $PWD"
69 | fi
70 |
71 | wpEnvs=( "${!WORDPRESS_@}" )
72 | if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then
73 | for wpConfigDocker in \
74 | wp-config-docker.php \
75 | /usr/src/wordpress/wp-config-docker.php \
76 | ; do
77 | if [ -s "$wpConfigDocker" ]; then
78 | echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})"
79 | # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables)
80 | awk '
81 | /put your unique phrase here/ {
82 | cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1"
83 | cmd | getline str
84 | close(cmd)
85 | gsub("put your unique phrase here", str)
86 | }
87 | { print }
88 | ' "$wpConfigDocker" > wp-config.php
89 | if [ "$uid" = '0' ]; then
90 | # attempt to ensure that wp-config.php is owned by the run user
91 | # could be on a filesystem that doesn't allow chown (like some NFS setups)
92 | chown "$user:$group" wp-config.php || true
93 | fi
94 | break
95 | fi
96 | done
97 | fi
98 | fi
99 |
100 | SRC_PATH="${SRC_PATH-/src/xcloner-backup-and-restore/}"
101 | DEST_PATH="${DEST_PATH-/var/www/html/wp-content/plugins/xcloner-backup-and-restore/}"
102 |
103 | sync() {
104 | rsync "${SRC_PATH}" "${DEST_PATH}" -r --delete || true
105 | chown www-data:www-data -R /var/www/html
106 | }
107 |
108 | watcher() {
109 | inotifywait -e modify,create,delete,move -r "${SRC_PATH}" -q --format '%w%f' | while read FILE; do
110 | sync
111 | watcher
112 | done
113 | }
114 | sync
115 | watcher &
116 |
117 | wait-for-it "${WORDPRESS_DB_HOST}:3306" --timeout=0 --strict -- echo "Database is up"
118 |
119 | wp core install --url="${WORDPRESS_URL}" --title="${WORDPRESS_TITLE}" --admin_user="${WORDPRESS_ADMIN_USER}" --admin_password="${WORDPRESS_ADMIN_PASSWORD}" --admin_email="${WORDPRESS_ADMIN_EMAIL}" --allow-root
120 | wp plugin activate xcloner-backup-and-restore --allow-root
121 |
122 | exec "$@"
123 |
--------------------------------------------------------------------------------
/docs/local-dev.md:
--------------------------------------------------------------------------------
1 | # Local Development
2 |
3 | ## Install For Development
4 |
5 | - `git clone git@github.com:watchfulli/XCloner-Wordpress.git`
6 | - `npm install`
7 | - Install JavaScript Dependencies:
8 | - If testing:
9 | - `npm run build-prod` will build for production.
10 | - `npm run build` does not do anything.
11 | - If doing development:
12 | - `npm run start` Starts watcher
13 | - Install Composer Dependencies
14 | - If installing for testing:
15 | - `docker run --rm -it --volume "$(pwd)":/app prooph/composer:7.3 install --no-dev`
16 | - If installing for development:
17 | - `docker run --rm -it --volume "$(pwd)":/app prooph/composer:7.3 install`
18 |
19 | ## Local Development Environment
20 | A [docker-compose](https://docs.docker.com/samples/wordpress/)-based local development environment is provided.
21 |
22 | - Start server
23 | - `docker-compose up -d`
24 | - If you get errors about port already being allocated, you can either:
25 | - Kill all containers and try again: `docker kill $(docker ps -q) && docker-compose up -d`
26 | - Change the port in docker-compose.yml.
27 | - Access Site
28 | - [http://localhost:6123](http://localhost:6123)
29 | - Run WP CLI command:
30 | - `docker-compose run wordpress-cli wp user create admin admin@example.com --role=admin user_pass=pass`
31 |
32 | ## WordPress Tests
33 |
34 | There is a special phpunit container for running WordPress tests, with WordPress and MySQL configured.
35 |
36 | - Enter container
37 | - `docker-compose run phpunit`
38 | - Test
39 | - `composer test:wordpress`
40 |
41 | ## Debug Logging
42 |
43 | Because most of what xCloner does happens via asynchronous requests, logging PHP errors is important for identifying bugs.
44 |
45 | By default, xCloner registers its own error handlers. This will prevent WordPress default error logging with WP_DEBUG_LOG from working as expected.
46 |
47 | You can use that log, or you can disable it in xCloner's "Settings" screen.
48 |
49 | - @todo find or create documentation about the PHP logging feature in xCloner.
50 | - [Recent post about WordPress debug logging from Delicious Brains](https://deliciousbrains.com/why-use-wp-debug-log-wordpress-development/)
51 | - [Post about WordPress debug logging I wrote for Elegant Themes awhile ago](https://www.elegantthemes.com/blog/tips-tricks/using-the-wordpress-debug-log)
52 |
--------------------------------------------------------------------------------
/docs/release-process.md:
--------------------------------------------------------------------------------
1 | # Release Process
2 |
3 | ## Starting Release
4 |
5 | ### Releases Tracking WordPress Version Updates
6 |
7 | The git workflow ".version.yml" runs once a day, using a [cron trigger](https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule). This workflow checks if the current value of "Tested up to" is the less than the latest version of WordPress. If it is not, this workflow will do the following:
8 |
9 | - Create a new branch.
10 | - Increment the "Stable tag" by 1 patch version.
11 | - Set the "Tested up to" value to the latest version.
12 | - Create a pull request title "UPDATE For WordPress $VERSION" where $VERSION is the latest version of WordPress.
13 |
14 | The test and analysis pipelines will run on the pull request. If they pass, advance to manual testing of this version. If not, we will need to examine why those pipelines failed before moving forward. Work to fix this should be done in a branch based off of the PR's branch.
15 |
16 | ### Other Releases
17 |
18 | If a release is being done for other reasons, a pull request to update the - branch should be made. The rest of this workflow.
19 |
20 | ## Manual Testing
21 |
22 | To test the pull request for the new version:
23 |
24 | - Checkout the repo locally, at the same branch as the pull request.
25 | - Build plugin the same way as in "deploy.yml".
26 | - `npm install`
27 | - `npm run build-prod`
28 | - `composer install --no-dev --prefer-dist -o`
29 |
30 | ## Trigger Release To WordPress.org/plugins
31 |
32 | When the release is ready:
33 |
34 | - Merge the pull request to the master branch
35 | - Apply and push a tag to the latest commit of master branch
36 | - Tag must be the same as the value of "Stable tag".
37 | - `git tag 1.0.0 && git push --tags`
38 | - This will trigger the "deploy.yml" workflow.
39 | - This should create a new release in [WordPress plugin repo](https://wordpress.org/plugins/xcloner-backup-and-restore/).
40 |
--------------------------------------------------------------------------------
/docs/reporting-bugs.md:
--------------------------------------------------------------------------------
1 | # Reporting Bugs
2 |
3 | Whenever you find a bug, [please open a GitHub issue for it](https://github.com/watchfulli/XCloner-Wordpress/issues/new). If you are opening an issue after reading a support thread on WordPress.org, please include a link to that thread. Also, indicate if you have reproduced the bug yourself, or if you are only passing on a report.
4 |
5 | ## What To Include
6 |
7 | Begin by stating what you were doing, what you expected to happen and what happened instead. Please include a list of steps to reproduce the error.
8 |
9 | In the issue, please note what versions of the following you are testing with:
10 | - WordPress
11 | - xCloner
12 | - PHP
13 |
14 | Please do not write "latest" version, use a version number always. If you are testing a branch from the Github repo, please note which branch, at which commit you have checked out. Also indicate if you installed using the process documented in [the local development documentation](./local-dev.md).
15 |
16 |
17 | ### Error Logging.
18 |
19 | Please always include what PHP errors happened with WP_DEBUG enabled and what JavaScript console errors happened. If they didn't, or you don't know, include that. The [local dev](./local-dev.md) documentation includes notes about setting up debug logging, which is probably neccasary for testing.
20 |
21 | For JavaScript console errors, please provide __the text of any errors__. Please do not include a screenshot of the terminal or all of the text in the JavaScript console. Please do not include warnings, or other text in the JavaScript console, unless you belive it is relevant.
22 |
--------------------------------------------------------------------------------
/docs/testing-cli-commands.md:
--------------------------------------------------------------------------------
1 | # CLI Commands For Testing
2 |
3 |
4 | ## `latest-wordpress`
5 |
6 | Gets latest version of WordPress via API. Other commands will use same API lookup if this doesn't run first.
7 |
8 | Examples:
9 | - `docker-compose run wordpress-cli wp latest-wordpress`
10 | ## `is-tested-up-to`
11 |
12 | Checks if the plugin's tested up to version is greater than or equal to latest version of WordPress.
13 |
14 | Examples:
15 | - `docker-compose run wordpress-cli wp is-tested-up-to`
16 |
17 | ## `update-version`
18 |
19 | Gets latest version of WordPress. Sets the "Tested up to" value in README.txt to latest version of WordPress. Sets stable tag in README.txt and version in xcloner.php to one minor version higher.
20 |
21 | Examples:
22 | - `docker-compose run wordpress-cli wp update-version`
23 |
24 | Probably need to run this first:
25 |
26 | ```bash
27 | sudo chmod 777 xcloner.php
28 | sudo chmod 777 README.txt
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/testing-pull-requests.md:
--------------------------------------------------------------------------------
1 | # Testing Pull Requests
2 |
3 | This is documentation for testing pull requests (PRs) for xcloner.
4 |
5 | https://github.com/watchfulli/XCloner-Wordpress/pulls
6 |
7 | When testing, you must install the plugin using the process documented in [the local development documentation](./local-dev.md). If you do not run composer update, as instructed after checking out the branch, your testing will not be valid. It is OK to subsitute your own local environment for the one that is included.
8 |
9 | ## Setting Up To Test
10 |
11 | 1. Checkout the repo from [Github](https://github.com/watchfulli/XCloner-Wordpress)
12 | 2. If you've already cloned it, reset your current branch:
13 | - `git reset HEAD --hard`
14 | 3. Identify which branch the PR the branch is for.
15 | 4. Switch to that branch
16 | - `git fetch origin name-of-branch`
17 | - `git checkout name-of-branch`
18 | - Please not activate the plugin yet
19 | 5. Run the installation steps documented in [the local development documentation](./local-dev.md) to simulate a production build:
20 | - `npm install`
21 | - Ensure you have the latest JavaScript dependecies install.
22 | - `npm run build-prod`
23 | - Ensure the JavaScript and CSS assets are built.
24 | - `docker run --rm -it --volume "$(pwd)":/app prooph/composer:7.3 install --no-dev`
25 | - Ensures the PHP dependencies are installed correctly
26 | - Installation uses a Docker container so that we use a consistent PHP version (7.3) to install.
27 | - `docker-compose up -d`
28 | - Starts or restarts the server
29 | 6. In your test WordPress site, activate the plugin.
30 | 7. Attempt to reproduce the bug, using the steps listed in the original issue that the [bug was reported in](./reporting-bugs.md)
31 | 8. If the bug is no longer present, comment on the issue explaining how you tested.
32 | - Make sure to include your version of PHP and WordPress.
33 | 9. If the bug is still present, comment on the issue explaining how you tested and what PHP and JavaScript errors you encountered.
34 | - Make sure to include your version of PHP and WordPress.
35 |
--------------------------------------------------------------------------------
/docs/workflows.md:
--------------------------------------------------------------------------------
1 | # Github Action Workflows
2 |
3 | There are several Github actions:
4 |
5 | 1. analysis.yml
6 | - This runs [phpstan](https://phpstan.org/) and [checks backwards compatibility with older versions of php](https://github.com/PHPCompatibility/PHPCompatibilityWP).
7 | - This runs on all pull requests.
8 | 2. test.yml
9 | - This runs [phpunit](https://phpunit.de/) tests.
10 | - These tests can run locally. See [WordPress Tests section of local dev docs](./local-dev.md)
11 | - This runs on all pull requests.
12 | 3. deploy.yml
13 | - This [releases updates to WordPress.org](https://github.com/10up/action-wordpress-plugin-deploy).
14 | - This runs when a new tag is added.
15 | 4. version.yml
16 | - This checks if the "Tested up to" value is older than latest version of WordPress.
17 | - See [release process docs](./release-process.md)
18 | - This runs once a day.
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xcloner-backup-and-restore",
3 | "version": "3.1.4",
4 | "description": "XCloner Backup and Restore plugin",
5 | "main": "xcloner.php",
6 | "directories": {
7 | "example": "examples",
8 | "lib": "lib"
9 | },
10 | "scripts": {
11 | "build": "echo \"Error: no build specified\"",
12 | "build-prod": "webpack --config webpack.prod.js",
13 | "start": "webpack --config webpack.dev.js --watch --info-verbosity verbose",
14 | "test": "echo \"Error: no test specified\" && exit 1"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/ovidiul/XCloner-Wordpress.git"
19 | },
20 | "keywords": [
21 | "backup"
22 | ],
23 | "author": "Watchful.net",
24 | "license": "GPL-3.0-or-later",
25 | "bugs": {
26 | "url": "https://github.com/ovidiul/XCloner-Wordpress/issues"
27 | },
28 | "homepage": "https://github.com/ovidiul/XCloner-Wordpress#readme",
29 | "devDependencies": {
30 | "terser-webpack-plugin": "^4.1.0",
31 | "uglify-js": "^3.10.3",
32 | "webpack": "^4.44.1",
33 | "webpack-cli": "^3.3.12",
34 | "webpack-merge": "^5.1.3",
35 | "webpack-merge-and-include-globally": "^2.1.25"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/phpstan-baseline.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | ignoreErrors:
3 | -
4 | message: "#^Variable \\$remote_storage might not be defined\\.$#"
5 | count: 1
6 | path: xcloner-backup-and-restore/admin/partials/remote_storage/aws.php
7 |
8 | -
9 | message: "#^Variable \\$gdrive_auth_url might not be defined\\.$#"
10 | count: 1
11 | path: xcloner-backup-and-restore/admin/partials/remote_storage/gdrive.php
12 |
13 | -
14 | message: "#^Variable \\$gdrive_construct might not be defined\\.$#"
15 | count: 1
16 | path: xcloner-backup-and-restore/admin/partials/remote_storage/gdrive.php
17 |
18 | -
19 | message: "#^Variable \\$remote_storage might not be defined\\.$#"
20 | count: 1
21 | path: xcloner-backup-and-restore/admin/partials/remote_storage/gdrive.php
22 |
23 | -
24 | message: "#^Variable \\$this might not be defined\\.$#"
25 | count: 2
26 | path: xcloner-backup-and-restore/admin/partials/xcloner_console_page.php
27 |
28 | -
29 | message: "#^Variable \\$this might not be defined\\.$#"
30 | count: 3
31 | path: xcloner-backup-and-restore/admin/partials/xcloner_generate_backups_page.php
32 |
33 | -
34 | message: "#^Variable \\$this might not be defined\\.$#"
35 | count: 5
36 | path: xcloner-backup-and-restore/admin/partials/xcloner_init_page.php
37 |
38 | -
39 | message: "#^Variable \\$this might not be defined\\.$#"
40 | count: 4
41 | path: xcloner-backup-and-restore/admin/partials/xcloner_manage_backups_page.php
42 |
43 | -
44 | message: "#^Variable \\$this might not be defined\\.$#"
45 | count: 1
46 | path: xcloner-backup-and-restore/admin/partials/xcloner_remote_storage_page.php
47 |
48 | -
49 | message: "#^Constant AUTH_KEY not found\\.$#"
50 | count: 1
51 | path: xcloner-backup-and-restore/admin/partials/xcloner_restore_page.php
52 |
53 | -
54 | message: "#^Variable \\$this might not be defined\\.$#"
55 | count: 4
56 | path: xcloner-backup-and-restore/admin/partials/xcloner_restore_page.php
57 |
58 | -
59 | message: "#^Variable \\$this might not be defined\\.$#"
60 | count: 2
61 | path: xcloner-backup-and-restore/admin/partials/xcloner_scheduled_backups_page.php
62 |
63 | -
64 | message: "#^Call to an undefined method Xcloner\\:\\:get_xcloner_scheduler\\(\\)\\.$#"
65 | count: 1
66 | path: xcloner-backup-and-restore/includes/class-xcloner-deactivator.php
67 |
68 | -
69 | message: "#^Call to an undefined method Xcloner\\:\\:get_xcloner_filesystem\\(\\)\\.$#"
70 | count: 1
71 | path: xcloner-backup-and-restore/includes/class-xcloner-deactivator.php
72 |
73 | -
74 | message: "#^Call to an undefined method Xcloner\\:\\:get_xcloner_settings\\(\\)\\.$#"
75 | count: 2
76 | path: xcloner-backup-and-restore/includes/class-xcloner.php
77 |
78 | -
79 | message: "#^Constant WP_CONTENT_DIR not found\\.$#"
80 | count: 1
81 | path: xcloner-backup-and-restore/includes/class-xcloner.php
82 |
83 | -
84 | message: "#^Constant WP_PLUGIN_DIR not found\\.$#"
85 | count: 1
86 | path: xcloner-backup-and-restore/includes/class-xcloner.php
87 |
88 | -
89 | message: "#^Instantiated class Xcloner_Public not found\\.$#"
90 | count: 1
91 | path: xcloner-backup-and-restore/includes/class-xcloner.php
92 |
93 | -
94 | message: "#^Method Xcloner\\:\\:onedrive_auth_token\\(\\) with return type void returns false but should not return anything\\.$#"
95 | count: 1
96 | path: xcloner-backup-and-restore/includes/class-xcloner.php
97 |
98 | -
99 | message: "#^PHPDoc tag @param has invalid value \\(\\$args\\)\\: Unexpected token \"\\$args\", expected type at offset 83$#"
100 | count: 1
101 | path: xcloner-backup-and-restore/includes/class-xcloner.php
102 |
103 | -
104 | message: "#^PHPDoc tag @param has invalid value \\(\\$property\\)\\: Unexpected token \"\\$property\", expected type at offset 59$#"
105 | count: 1
106 | path: xcloner-backup-and-restore/includes/class-xcloner.php
107 |
108 | -
109 | message: "#^PHPDoc tag @param has invalid value \\(\\$schedules\\)\\: Unexpected token \"\\$schedules\", expected type at offset 18$#"
110 | count: 1
111 | path: xcloner-backup-and-restore/includes/class-xcloner.php
112 |
113 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | includes:
2 | - phpstan-baseline.neon
3 |
4 | parameters:
5 | level: 3
6 | paths:
7 | - xcloner-backup-and-restore/admin
8 | - xcloner-backup-and-restore/includes
9 |
--------------------------------------------------------------------------------
/webpack.dev.js:
--------------------------------------------------------------------------------
1 | // Webpack uses this to work with directories
2 | const path = require("path");
3 | const TerserPlugin = require("terser-webpack-plugin");
4 |
5 | // This is the main configuration object.
6 | // Here you write different options and tell Webpack what to do
7 | module.exports = {
8 | // Path to your entry point. From this file Webpack will begin his work
9 | entry: {
10 | index: "./xcloner-backup-and-restore/admin/js/index.js",
11 | },
12 |
13 | // Path and filename of your result bundle.
14 | // Webpack will bundle all JavaScript into this file
15 | output: {
16 | path: path.resolve(__dirname, "xcloner-backup-and-restore/dist"),
17 | filename: "./admin/js/[name].min.js",
18 | },
19 |
20 | optimization: {
21 | minimize: false,
22 | minimizer: [new TerserPlugin()],
23 | },
24 |
25 | // Default mode for Webpack is production.
26 | // Depending on mode Webpack will apply different things
27 | // on final bundle. For now we don't need production's JavaScript
28 | // minifying and other thing so let's set mode to development
29 | //mode: 'development'
30 | mode: "development",
31 | devtool: 'inline-source-map',
32 | };
33 |
--------------------------------------------------------------------------------
/webpack.prod.js:
--------------------------------------------------------------------------------
1 | // Webpack uses this to work with directories
2 | const path = require("path");
3 | const TerserPlugin = require("terser-webpack-plugin");
4 | const webpack = require('webpack');
5 |
6 | // This is the main configuration object.
7 | // Here you write different options and tell Webpack what to do
8 | module.exports = {
9 | // Path to your entry point. From this file Webpack will begin his work
10 | entry: {
11 | index: "./xcloner-backup-and-restore/admin/js/index.js",
12 | },
13 |
14 | // Path and filename of your result bundle.
15 | // Webpack will bundle all JavaScript into this file
16 | output: {
17 | path: path.resolve(__dirname, "xcloner-backup-and-restore"),
18 | filename: "./admin/js/[name].min.js",
19 | },
20 |
21 | optimization: {
22 | minimize: true,
23 | minimizer: [new TerserPlugin(
24 | {
25 | extractComments: {
26 | banner: (licenseFile) => {
27 | return `\n
28 | For license information please see ${path.basename(licenseFile)}\n
29 | To view source code please see https://github.com/watchfulli/XCloner-Wordpress/\n`;
30 | },
31 | }
32 | }
33 | )],
34 | },
35 |
36 | plugins: [
37 | new webpack.BannerPlugin('You can review the source code here: https://github.com/watchfulli/XCloner-Wordpress/')
38 | ],
39 | mode: "production",
40 | devtool: 'source-map',
41 | };
42 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/CHANGELOG.txt:
--------------------------------------------------------------------------------
1 | = 4.7.6 =
2 | * Update "tested up to" version
3 |
4 | = 4.7.5 =
5 | * Move changelog to a separate file (https://github.com/watchfulli/XCloner-Wordpress/issues/315)
6 |
7 | = 4.7.4 =
8 | * Prevent direct access to Composer vendor files to avoid security issues
9 |
10 | = 4.7.3 =
11 | * Update "tested up to" version
12 |
13 | = 4.7.2 =
14 | * Update "tested up to" version
15 |
16 | = 4.7.1 =
17 | * Update "tested up to" version
18 |
19 | = 4.7.0 =
20 | * Fix typo on Google drive integration #288
21 | * Review authentication on Google drive integration to drop unsupported oob authentication #264
22 | * Update "tested up to" version
23 |
24 | = 4.6.5 =
25 | * Update "tested up to" version
26 |
27 | = 4.6.4 =
28 | * Update "tested up to" version
29 |
30 | = 4.6.3 =
31 | * Update "tested up to" version
32 |
33 | = 4.6.2 =
34 | * fix: Add CLI support for backup archive files listing: https://github.com/watchfulli/XCloner-Wordpress/issues/138
35 | * fix: PHP deprecated messages: https://github.com/watchfulli/XCloner-Wordpress/issues/170
36 |
37 | = 4.6.1 =
38 | * fix: Backup archives not containing all files: https://github.com/watchfulli/XCloner-Wordpress/issues/179
39 | * fix: File not found error while scanning for files: https://github.com/watchfulli/XCloner-Wordpress/issues/266
40 |
41 | = 4.6.0 =
42 | * Split UI of local restore and site cloning: https://github.com/watchfulli/XCloner-Wordpress/issues/258
43 |
44 | = 4.5.2 =
45 | * Removed duplicate code
46 |
47 | = 4.5.1 =
48 | * Removed unused dependencies
49 |
50 | = 4.5.0 =
51 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/166
52 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/167
53 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/173
54 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/237
55 |
56 | = 4.4.8 =
57 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/242
58 |
59 | = 4.4.7 =
60 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/239
61 |
62 | = 4.4.6 =
63 | * https://github.com/watchfulli/XCloner-Wordpress/issues/241
64 |
65 | = 4.4.5 =
66 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/240
67 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/234
68 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/225
69 |
70 | = 4.4.4 =
71 | * fix: missing escapes and sanitizations
72 |
73 | = 4.4.3 =
74 | * remove PHP Short Tags to be compliant with WordPress guidelines
75 |
76 | = 4.4.2 =
77 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/227
78 | * fix: https://github.com/watchfulli/XCloner-Wordpress/issues/231
79 |
80 | = 4.4.1 =
81 | * minor code review
82 |
83 | = 4.4.0 =
84 | * remove remote restore feature to be compliant with WordPress guidelines
85 |
86 | = 4.3.7 =
87 | * security fixes
88 |
89 | = 4.3.6 =
90 | * security fixes
91 |
92 | = 4.3.5 =
93 | * security fixes
94 |
95 | = 4.2.16 =
96 | * Backblaze remote storage UI text changes
97 | * Improved Google Drive integration
98 | * http(s) url email backup fix
99 | * design changes
100 | * security fixes
101 |
102 | = 4.2.15 =
103 |
104 | * frontend popup display conflict fix
105 | * design changes
106 | * remote storage direct download option addon
107 | * replace modal from generate backup screen with a new follow up tab
108 | * S3 uplaod fix
109 | * WP-CLI --quiet flag addon, --encrypt/--decrypt addon
110 | * CSRF nonces implementation API
111 |
112 | = 4.2.14 =
113 |
114 | * CSRF restore vulnerability fix
115 |
116 | = 4.2.13 =
117 |
118 | * conflict fix bootstrap modal display
119 | * WP 5.5 compatibility check and update
120 |
121 | = 4.2.12 =
122 |
123 | * Google Drive authorization fix
124 |
125 | = 4.2.11 =
126 |
127 | * OneDrive file upload size limit fix
128 |
129 | = 4.2.10 =
130 |
131 | * Add `Local Storage` to the `Remote Storage` area
132 | * Cleanup uploaded archive after restore
133 | * Add WP-CLI support
134 | * Add Microsoft OneDrive support to remote storage
135 | * BUG: Load webdav vendor lib only if webdav is activated
136 | * Add support for Backblaze application keys
137 | * BUG: Google Drive upload issue
138 |
139 | = 4.2.9 =
140 |
141 | * scheduler fix call init
142 | * google drive support fix
143 | * PHP 7.1 minimum requirement
144 | * PHP 7.x bug fix
145 | * PHP 7.x minimum support activation
146 |
147 | = 4.2.1 =
148 |
149 | ** Implemented enhancements: **
150 | * Rename `Scheduled Backups` menu to `Schedules & Profiles`
151 |
152 | ** Fixed bugs: **
153 | * Fixed `redeclare deactivate\_plugin` bug in CLI
154 |
155 | = 4.2.0 =
156 |
157 | ** Implemented enhancements: **
158 |
159 | * Improve error when connecting to remote site using restore script from another site
160 | * Improve error message when accessing restore script directly
161 | * Encrypt database password during restore
162 | * Update default regex exclusions
163 | * Replace youtube links
164 | * Add additional cleanup & quota options for backup storage
165 | * Add standalone CLI for making backups
166 | * Move `send to remote destination` option to the `Backup Options` tab
167 |
168 | ** Fixed bugs: **
169 |
170 | * Select All Backups delete does not work
171 | * JS Error during restoration
172 | * Ajax error when viewing empty storage area
173 | * Javascript error when running a backup, and clicking "Send Backup to remote storage"
174 | * SFTP bug
175 | * Live DB restore replaces WP Options table
176 |
177 | = 4.1.5 =
178 | * SFTP upoad fix
179 |
180 | = 4.1.4 =
181 | * thinkovi references replace
182 | * plugin pre auto update text changelog
183 | * author name and uri change
184 | * standalone library addon support
185 |
186 | = 4.1.3 =
187 | * database include tables fix
188 |
189 | = 4.1.2 =
190 | * improved default backup storage path security
191 | * improved remote storage security
192 |
193 | = 4.1.2 =
194 | * vendor lib updates
195 | * flysystem azure storage Upgrade
196 |
197 | = 4.1.1 =
198 | * log tmp directories fix, tracking only ERROR reports from php
199 | * security improvement backup log name
200 | * database restore resume fix
201 | * memory limit fix
202 |
203 | = 4.1.0 =
204 | * added AES-128-CBC backup encryption and decryption option
205 | * manage backup fixes
206 | * scheduled backup screen fixes and addon backup encryption option
207 | * automated backups encryption option addon
208 | * generate backups encrypt option addon
209 |
210 | = 4.0.9 =
211 | * remote storage password encryption addon for database
212 | * vendor cleanup packages
213 | * database silent fail fix
214 | * copyright changes
215 | * jstree fix database display
216 | * microtime float div fix
217 | * manage backups data order fix
218 |
219 | = 4.0.8 =
220 | * updated vendor library dependencies, AWS, phpseclib
221 | * TAR compression fix
222 | * 7.2 compatibility checks and fixes
223 |
224 | = 4.0.7 =
225 | * added log fixes for Wordpress cron
226 | * remove storage fixes
227 |
228 | = 4.0.6 =
229 | * S3 prefix addon for defining folders
230 | * S3 custom endpoint addon to support minio.io
231 | * code fixes
232 |
233 | = 4.0.5 =
234 | * Dropbox API update to V2
235 | * Code fixes and text changes
236 |
237 | = 4.0.4 =
238 | * remote storage view fix
239 | * added automatic backups option before WP automatic update
240 | * deactivate exception handling fix
241 | * restore pages improvements
242 | * old XCloner backup format compatibility fixes
243 |
244 | = 4.0.3 =
245 | * added differential backups with the option to only backup files modified after a certain date
246 | * added localhost restore option with direct access to the restore restore
247 | * added schedule name fixes
248 | * added restore filter All Files, Only Plugins Files, Only Theme Files, Only Uploads Files, Only Database Backup
249 | * added remote backup list archive option on restore page
250 | * tmp directory cleanup on deactivate
251 | * sftp text fixes
252 |
253 | = 4.0.2 =
254 | * added WebDAV remote storage support
255 | * added Google Drive Suppor through XCloner-Google-Drive plugin
256 | * added depedency injection code refactoring
257 | * added TAR PAX support on restore
258 | * improving code quality scrutinizer
259 | * fixing phpversion requirement
260 | * adding Backblaze remote storage support
261 | * added Remote Storage Manage Backups dropdown selection
262 | * fixed windows opendir error
263 | * added total archived files to notifications email
264 | * timezone scheduler fix
265 | * added default error sending to admin when no notification email is set
266 |
267 |
268 | = 4.0.1 =
269 | * Code rewritten from ground up to make use of latest code standards
270 | * Added support for Dropbox, Amazon S3, Azure Blob and SFTP storage
271 | * Added a new restore script
272 | * Added an improved backup and system logger
273 | * New Setting Panel
274 | * New Manage Backups Panel with the options to Delete, Transfer to Remote Storage, Download and List Backup archive contents
275 | * Added mail notifications for scheduled backups
276 | * Added a new Cron Scheduler to make use of Wordpress System Cron option
277 | * Improved user input sanitization
278 | * Improved recursive file scanning and archiving
279 | * Improved Mysql Backup dump
280 | * Added Multiple Cleanup options both for local storage and remote
281 | * Added Improved Backup Compressing option
282 |
283 | = 3.1.5 =
284 | * Config variables save sanitization addon
285 |
286 | = 3.1.4 =
287 | * DropPHP DropBox library update, upload fixes for files larger than 150MB
288 |
289 | = 3.1.3 =
290 | * XSS fix
291 |
292 | = 3.1.2 =
293 | * vulnerability fix
294 |
295 | = 3.1.1 =
296 | * added CSRF protection
297 |
298 | = 3.1.0 =
299 | * added Wordpress login-less integration
300 | * plugin settings are now saved to database
301 | * security audit and hardening
302 |
303 | = 3.0.8 =
304 | * added russian language support
305 |
306 | = 3.0.7 =
307 | * added sftp support for backup transfer, thanks Todd Bluhm - dynamicts.com
308 |
309 | = 3.0.6 =
310 | * added php 5.4 compatibility
311 |
312 | = 3.0.4 =
313 | * LFI vulnerability fix
314 |
315 | = 3.0.3 =
316 | * added amazon ssl option box
317 | * moved the compress option to the System tab, don't use it unless you know what you are doing!
318 |
319 | = 3.0.1 =
320 | * several important security and bug fixes
321 |
322 | = 3.0 =
323 | * incremental database backup
324 | * incremental file system scan
325 | * backup size limit and option to split it into additional archives, default 2GB
326 | * exclude files larger than a certain size option
327 | * incremental files restore
328 | * JQuery Start interface
329 |
330 | = 2.2.1 =
331 | * Added JSON AJAX interface to the Generate Backup process
332 | * Added incremental filesystem scan
333 | * several bug fixes
334 | * php >=5.2.0 version check
335 |
336 | = 2.1.2 =
337 | * Added Amazon S3 cron storage support
338 |
339 | = 2.1 =
340 | * Initial release
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/btn_google_signin_dark_pressed_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/btn_google_signin_dark_pressed_web.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/database-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/database-icon.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/file-icon-d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/file-icon-d.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/file-icon-f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/file-icon-f.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/file-icon-l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/file-icon-l.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/file-icon-root.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/file-icon-root.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/assets/table-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/assets/table-icon.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/class-xcloner-admin.php:
--------------------------------------------------------------------------------
1 |
24 | */
25 | class Xcloner_Admin
26 | {
27 |
28 | /**
29 | * The ID of this plugin.
30 | *
31 | * @since 1.0.0
32 | * @access private
33 | * @var string $plugin_name The ID of this plugin.
34 | */
35 | private $plugin_name;
36 |
37 | /**
38 | * @var Xcloner
39 | */
40 | private $xcloner_container;
41 |
42 | /**
43 | * Initialize the class and set its properties.
44 | *
45 | * Xcloner_Admin constructor.
46 | * @param Xcloner $xcloner_container
47 | */
48 | public function __construct(Xcloner $xcloner_container)
49 | {
50 | $this->plugin_name = Xcloner::PLUGIN_NAME;
51 | $this->xcloner_container = $xcloner_container;
52 | }
53 |
54 | /**
55 | * @return Xcloner
56 | */
57 | public function get_xcloner_container()
58 | {
59 | return $this->xcloner_container;
60 | }
61 |
62 | /**
63 | * Register the stylesheets for the admin area.
64 | *
65 | * @since 1.0.0
66 | */
67 | public function enqueue_styles($hook)
68 | {
69 |
70 | if (!stristr($hook, "page_" . $this->plugin_name) || (isset($_GET['option']) && $_GET['option'] == "com_cloner")) {
71 | return;
72 | }
73 |
74 | /**
75 | * This function is provided for demonstration purposes only.
76 | *
77 | * An instance of this class should be passed to the run() function
78 | * defined in Xcloner_Loader as all of the hooks are defined
79 | * in that particular class.
80 | *
81 | * The Xcloner_Loader will then create the relationship
82 | * between the defined hooks and the functions defined in this
83 | * class.
84 | */
85 |
86 | wp_enqueue_style($this->plugin_name . "_materialize", plugin_dir_url(__FILE__) . 'css/materialize.min.css', array());
87 | wp_enqueue_style($this->plugin_name . "_materialize.icons", '//fonts.googleapis.com/icon?family=Material+Icons', array());
88 | wp_enqueue_style($this->plugin_name . "_jquery.datatables", plugin_dir_url(__FILE__) . 'css/jquery.dataTables.min.css', array());
89 | wp_enqueue_style($this->plugin_name . "_jquery.datatables.responsive", plugin_dir_url(__FILE__) . 'css/responsive.dataTables.css', array());
90 | wp_enqueue_style($this->plugin_name . "_jstree", dirname(plugin_dir_url(__FILE__)) . '/vendor/vakata/jstree/dist/themes/default/style.min.css', array());
91 | wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/xcloner-admin.css', array());
92 | }
93 |
94 | /**
95 | * Register the JavaScript for the admin area.
96 | *
97 | * @since 1.0.0
98 | */
99 | public function enqueue_scripts($hook)
100 | {
101 |
102 | if (!stristr($hook, "page_" . $this->plugin_name)) {
103 | return;
104 | }
105 |
106 | /**
107 | * This function is provided for demonstration purposes only.
108 | *
109 | * An instance of this class should be passed to the run() function
110 | * defined in Xcloner_Loader as all of the hooks are defined
111 | * in that particular class.
112 | *
113 | * The Xcloner_Loader will then create the relationship
114 | * between the defined hooks and the functions defined in this
115 | * class.
116 | */
117 |
118 | add_thickbox();
119 | wp_enqueue_script('plugin-install');
120 | wp_enqueue_script('updates');
121 | wp_enqueue_script($this->plugin_name . "_jquery.datatables", plugin_dir_url(__FILE__) . 'js/jquery.dataTables.min.js', array('jquery'));
122 | wp_enqueue_script($this->plugin_name . "_jquery.datatables.respnsive", plugin_dir_url(__FILE__) . 'js/dataTables.responsive.js', array('jquery'));
123 | wp_enqueue_script($this->plugin_name . "_vakata", dirname(plugin_dir_url(__FILE__)) . '/vendor/vakata/jstree/dist/jstree.min.js', array('jquery'));
124 |
125 | wp_enqueue_script($this->plugin_name, dirname(plugin_dir_url(__FILE__)) . '/admin/js/index.min.js', array('jquery'));
126 | }
127 |
128 | public function xcloner_init_page()
129 | {
130 | require_once("partials/xcloner_init_page.php");
131 | }
132 |
133 | /**
134 | * Returns the XCloner Storage Page
135 | */
136 | public function xcloner_remote_storage_page()
137 | {
138 | $xcloner_sanitization = $this->get_xcloner_container()->get_xcloner_sanitization();
139 | $remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
140 |
141 | if (isset($_POST['action'])) {
142 | $_POST['action'] = $xcloner_sanitization->sanitize_input_as_string($_POST['action']);
143 | $remote_storage->save($_POST['action']);
144 | }
145 |
146 | if (isset($_POST['authentification_code']) && $_POST['authentification_code'] != "") {
147 | $_POST['authentification_code'] = $xcloner_sanitization->sanitize_input_as_string($_POST['authentification_code']);
148 |
149 | $remote_storage->gdrive_set_access_token($_POST['authentification_code']);
150 | }
151 |
152 | if (isset($_POST['connection_check']) && $_POST['connection_check']) {
153 | $remote_storage->check($_POST['action']);
154 | }
155 |
156 | require_once("partials/xcloner_remote_storage_page.php");
157 |
158 | }
159 |
160 | public function xcloner_scheduled_backups_page()
161 | {
162 | $requirements = $this->xcloner_container->get_xcloner_requirements();
163 |
164 | if (!$requirements->check_backup_ready_status()) {
165 | require_once("partials/xcloner_init_page.php");
166 |
167 | return false;
168 | }
169 |
170 | require_once("partials/xcloner_scheduled_backups_page.php");
171 |
172 | return true;
173 | }
174 |
175 | public function xcloner_manage_backups_page()
176 | {
177 | require_once("partials/xcloner_manage_backups_page.php");
178 |
179 | }
180 |
181 | public function xcloner_debugger_page()
182 | {
183 | require_once("partials/xcloner_console_page.php");
184 |
185 | }
186 |
187 | public function xcloner_restore_site()
188 | {
189 | require_once("partials/xcloner_restore_page.php");
190 | }
191 |
192 | public function xcloner_clone_site()
193 | {
194 | require_once("partials/xcloner_restore_page.php");
195 | }
196 |
197 | public function xcloner_generate_backups_page()
198 | {
199 | $requirements = $this->xcloner_container->get_xcloner_requirements();
200 |
201 | if (!$requirements->check_backup_ready_status()) {
202 | require_once("partials/xcloner_init_page.php");
203 |
204 | return false;
205 | }
206 |
207 | require_once("partials/xcloner_generate_backups_page.php");
208 |
209 | return true;
210 | }
211 |
212 | public function xcloner_settings_page()
213 | {
214 | // check user capabilities
215 | if (!current_user_can('manage_options')) {
216 | return;
217 | }
218 |
219 | // add error/update messages
220 |
221 | // check if the user have submitted the settings
222 | // wordpress will add the "settings-updated" $_GET parameter to the url
223 | if (isset($_GET['settings-updated'])) {
224 | // add settings saved message with the class of "updated"
225 | add_settings_error('wporg_messages', 'wporg_message', __('Settings Saved', 'wporg'), 'updated');
226 | }
227 |
228 | // show error/update messages
229 | settings_errors('wporg_messages');
230 | ?>
231 |
232 | get_xcloner_container()->get_xcloner_sanitization();
234 | $active_tab = "general_options";
235 |
236 | if (isset($_GET['tab'])) {
237 | $active_tab = $xcloner_sanitization->sanitize_input_as_string($_GET['tab']);
238 | }
239 |
240 | ?>
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
251 |
252 |
253 |
254 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
276 |
277 |
278 |
279 | tbody > tr > td.child,
2 | table.dataTable.dtr-inline.collapsed > tbody > tr > th.child,
3 | table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty {
4 | cursor: default !important;
5 | }
6 | table.dataTable.dtr-inline.collapsed > tbody > tr > td.child:before,
7 | table.dataTable.dtr-inline.collapsed > tbody > tr > th.child:before,
8 | table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty:before {
9 | display: none !important;
10 | }
11 | table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
12 | table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
13 | position: relative;
14 | padding-left: 30px;
15 | cursor: pointer;
16 | }
17 | table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:before,
18 | table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child:before {
19 | top: 9px;
20 | left: 4px;
21 | height: 14px;
22 | width: 14px;
23 | display: block;
24 | position: absolute;
25 | color: white;
26 | border: 2px solid white;
27 | border-radius: 14px;
28 | box-shadow: 0 0 3px #444;
29 | box-sizing: content-box;
30 | text-align: center;
31 | font-family: 'Courier New', Courier, monospace;
32 | line-height: 14px;
33 | content: '+';
34 | background-color: #31b131;
35 | }
36 | table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child:before,
37 | table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child:before {
38 | content: '-';
39 | background-color: #d33333;
40 | }
41 | table.dataTable.dtr-inline.collapsed > tbody > tr.child td:before {
42 | display: none;
43 | }
44 | table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child,
45 | table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child {
46 | padding-left: 27px;
47 | }
48 | table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child:before,
49 | table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child:before {
50 | top: 5px;
51 | left: 4px;
52 | height: 14px;
53 | width: 14px;
54 | border-radius: 14px;
55 | line-height: 14px;
56 | text-indent: 3px;
57 | }
58 | table.dataTable.dtr-column > tbody > tr > td.control,
59 | table.dataTable.dtr-column > tbody > tr > th.control {
60 | position: relative;
61 | cursor: pointer;
62 | }
63 | table.dataTable.dtr-column > tbody > tr > td.control:before,
64 | table.dataTable.dtr-column > tbody > tr > th.control:before {
65 | top: 50%;
66 | left: 50%;
67 | height: 16px;
68 | width: 16px;
69 | margin-top: -10px;
70 | margin-left: -10px;
71 | display: block;
72 | position: absolute;
73 | color: white;
74 | border: 2px solid white;
75 | border-radius: 14px;
76 | box-shadow: 0 0 3px #444;
77 | box-sizing: content-box;
78 | text-align: center;
79 | font-family: 'Courier New', Courier, monospace;
80 | line-height: 14px;
81 | content: '+';
82 | background-color: #31b131;
83 | }
84 | table.dataTable.dtr-column > tbody > tr.parent td.control:before,
85 | table.dataTable.dtr-column > tbody > tr.parent th.control:before {
86 | content: '-';
87 | background-color: #d33333;
88 | }
89 | table.dataTable > tbody > tr.child {
90 | padding: 0.5em 1em;
91 | }
92 | table.dataTable > tbody > tr.child:hover {
93 | background: transparent !important;
94 | }
95 | table.dataTable > tbody > tr.child ul {
96 | display: inline-block;
97 | list-style-type: none;
98 | margin: 0;
99 | padding: 0;
100 | }
101 | table.dataTable > tbody > tr.child ul li {
102 | border-bottom: 1px solid #efefef;
103 | padding: 0.5em 0;
104 | }
105 | table.dataTable > tbody > tr.child ul li:first-child {
106 | padding-top: 0;
107 | }
108 | table.dataTable > tbody > tr.child ul li:last-child {
109 | border-bottom: none;
110 | }
111 | table.dataTable > tbody > tr.child span.dtr-title {
112 | display: inline-block;
113 | min-width: 75px;
114 | font-weight: bold;
115 | }
116 |
117 | div.dtr-modal {
118 | position: fixed;
119 | box-sizing: border-box;
120 | top: 0;
121 | left: 0;
122 | height: 100%;
123 | width: 100%;
124 | z-index: 100;
125 | padding: 10em 1em;
126 | }
127 | div.dtr-modal div.dtr-modal-display {
128 | position: absolute;
129 | top: 0;
130 | left: 0;
131 | bottom: 0;
132 | right: 0;
133 | width: 50%;
134 | height: 50%;
135 | overflow: auto;
136 | margin: auto;
137 | z-index: 102;
138 | overflow: auto;
139 | background-color: #f5f5f7;
140 | border: 1px solid black;
141 | border-radius: 0.5em;
142 | box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
143 | }
144 | div.dtr-modal div.dtr-modal-content {
145 | position: relative;
146 | padding: 1em;
147 | }
148 | div.dtr-modal div.dtr-modal-close {
149 | position: absolute;
150 | top: 6px;
151 | right: 6px;
152 | width: 22px;
153 | height: 22px;
154 | border: 1px solid #eaeaea;
155 | background-color: #f9f9f9;
156 | text-align: center;
157 | border-radius: 3px;
158 | cursor: pointer;
159 | z-index: 12;
160 | }
161 | div.dtr-modal div.dtr-modal-close:hover {
162 | background-color: #eaeaea;
163 | }
164 | div.dtr-modal div.dtr-modal-background {
165 | position: fixed;
166 | top: 0;
167 | left: 0;
168 | right: 0;
169 | bottom: 0;
170 | z-index: 101;
171 | background: rgba(0, 0, 0, 0.6);
172 | }
173 |
174 | @media screen and (max-width: 767px) {
175 | div.dtr-modal div.dtr-modal-display {
176 | width: 95%;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/css/xcloner-admin.css:
--------------------------------------------------------------------------------
1 | /**
2 | * All of the CSS for your admin-specific functionality should be
3 | * included in this file.
4 | */
5 | /* fallback */
6 |
7 | html {
8 | font-family: GillSans, Calibri, Trebuchet, sans-serif;
9 | }
10 |
11 | /*
12 | @font-face {
13 | font-family: 'Material Icons';
14 | font-style: normal;
15 | font-weight: 400;
16 | src: url(../fonts/MaterialIcons-Regular.eot);
17 | src: local('Material Icons'),
18 | local('MaterialIcons-Regular'),
19 | url(../fonts/MaterialIcons-Regular.woff2) format('woff2'),
20 | url(../fonts/MaterialIcons-Regular.woff) format('woff'),
21 | url(../fontsMaterialIcons-Regular.ttf) format('truetype');
22 | }*/
23 |
24 | h1 {
25 | font-size: 23px;
26 | }
27 |
28 | h2 {
29 | font-size: 18px;
30 | }
31 |
32 | .input-field {
33 | margin-top: 0px;
34 | }
35 |
36 | td, th {
37 | padding-top: 0px !important;
38 | }
39 |
40 | .form-table th {
41 | padding-top: 10px !important;
42 | }
43 |
44 | a.nav-tab.col {
45 | padding: 10px;
46 | }
47 |
48 | span.shorten_string {
49 | cursor: pointer;
50 | }
51 |
52 | .card-panel {
53 | min-height: 60px;
54 | }
55 |
56 | .dashboard .additional_system_info {
57 | display: none;
58 | }
59 |
60 | .nav-tab-wrapper li {
61 | margin-bottom: 0px;
62 | }
63 |
64 | .nav-tab-wrapper-content .tab-content {
65 | display: none;
66 | }
67 |
68 | .nav-tab-wrapper-content .tab-content.active {
69 | display: block;
70 | }
71 |
72 | .input-field label.active {
73 | font-size: 1rem;
74 | }
75 |
76 | .xcloner-debugger .console {
77 | height: 450px;
78 | min-height: 300px;
79 | overflow: auto;
80 | }
81 |
82 | #error_modal textarea {
83 | height: 150px;
84 | }
85 |
86 | #error_modal .msg {
87 | font-size: 14px;
88 | }
89 |
90 | #generate_backup .backup-status, #generate_backup ul.backup-status > li {
91 | display: none;
92 | }
93 |
94 | ul.backup-name {
95 | margin-top: 1.78rem;
96 | }
97 |
98 | #generate_backup .status-body ul.backup-name li, #generate_backup ul.logged-databases li {
99 | font-weight: bold;
100 | }
101 |
102 | #generate_backup .backup-done .collapsible-body {
103 | margin-top: 1.83rem;
104 | }
105 |
106 | #generate_backup .status-body > ul, #generate_backup .status-body ul.logged-tables {
107 | margin: 5px 10px;
108 | max-height: 200px;
109 | overflow-y: auto;
110 | margin-top: 1.78rem;
111 | }
112 |
113 | #generate_backup .action-buttons .cancel,
114 | #generate_backup .action-buttons .restart {
115 | display: none;
116 | }
117 |
118 | .modal-footer .modal-close.btn-flat {
119 | color: #fff;
120 | }
121 |
122 | .collapsible-body {
123 | padding: 0px 10px;
124 | }
125 |
126 | .select-wrapper + label {
127 | font-size: 1rem;
128 | }
129 |
130 | .input-field>label:not(.label-icon).active {
131 | -webkit-transform: translateY(-14px) scale(1);
132 | transform: translateY(-14px) scale(1);
133 | }
134 |
135 | #schedule_backup .server-time h2 {
136 | color: #fff;
137 | }
138 |
139 | #schedule_backup_success {
140 | display: none;
141 | }
142 |
143 | #scheduled_backups_wrapper .dataTables_length,
144 | #manage_backups_wrapper .dataTables_length {
145 | display: none;
146 | }
147 |
148 | table#scheduled_backups {
149 | font-size: 16px;
150 | }
151 |
152 | #scheduled_backups td, #scheduled_backups th {
153 | padding-top: 8px !important;
154 | }
155 |
156 | #scheduled_backups i.status {
157 | color: #fff;
158 | }
159 |
160 | .site-backup_page_xcloner_scheduled_backups_page #server_time h2 {
161 | color: #fff;
162 | margin: 9px 0px;
163 | padding: 10px 10px 5px 10px;
164 | }
165 |
166 | textarea.materialize-textarea {
167 | overflow: auto;
168 | resize: auto;
169 | }
170 |
171 | #scheduled_backups .edit, #scheduled_backups .status.active, #scheduled_backups .delete,
172 | #manage_backups .download, #manage_backups .cloud-upload, #manage_backups .delete, #manage_backups .list-backup-content,
173 | .backup-done .download, .backup-done .cloud-upload, .backup-done .delete, .backup-done .list-backup-content,
174 | #manage_backups .copy-remote-to-local, #manage_backups .expand-multipart,
175 | #manage_backups .backup-encryption, #manage_backups .backup-decryption {
176 | color: #4db6ac;
177 | }
178 |
179 | #scheduled_backups .status.inactive {
180 | color: #d32f2f;
181 | }
182 |
183 | table.dataTable thead th, table.dataTable tfoot th {
184 | padding-left: 10px;
185 | }
186 |
187 | table.dataTable tr.odd {
188 | background-color: #fff;
189 | }
190 |
191 | table.dataTable tr.even {
192 | background-color: #f3f3f3;
193 | }
194 |
195 | #manage_backups ul.multipart {
196 | margin-left: 20px;
197 | display: none;
198 | }
199 |
200 | #manage_backups ul.multipart li {
201 | padding: 5px;
202 | list-style-type: square;
203 | }
204 |
205 | a.expand-multipart.remove {
206 | display: none;
207 | }
208 |
209 | .remote-storage .label label {
210 | font-size: 16px;
211 | }
212 |
213 | .remote-storage .label {
214 | padding-top: 25px;
215 | }
216 |
217 | .remote-storage .collapsible-header {
218 | padding: 10px;
219 | display: block;
220 | line-height: 25px;
221 | }
222 |
223 | #generate_backup p {
224 | margin: 0px;
225 | }
226 |
227 | #generate_backup .collapsible-header,
228 | .xcloner-debugger .collapsible-header{
229 | display: block;
230 | }
231 |
232 | #manage_backups td.checkbox {
233 | vertical-align: top;
234 | }
235 |
236 | #remote_storage_modal {
237 | min-height: 350px;
238 | }
239 |
240 | #remote_storage_modal .label label {
241 | font-size: 16px;
242 | }
243 |
244 | #remote_storage_modal .label {
245 | padding-top: 25px;
246 | }
247 |
248 | #remote_storage_modal .status {
249 | display: none;
250 | }
251 |
252 | #remote_storage_modal .status-text.error {
253 | color: red;
254 | }
255 |
256 | #remote_storage_modal .status-text {
257 | font-weight: bold;
258 | }
259 |
260 | #backup-status h5 {
261 | font-size: 18px;
262 | }
263 |
264 | #backup-status .row .item .title {
265 | width: 100px;
266 | display: inline-block;
267 | font-weight: bold;
268 | }
269 |
270 | .xcloner-restore li.steps {
271 | display: none;
272 | }
273 |
274 | .xcloner-restore .steps.show {
275 | display: block;
276 | }
277 |
278 | .xcloner-restore li .collapsible-body {
279 | padding: 25px 10px 15px 10px;
280 | }
281 |
282 | .xcloner-restore select.browser-default {
283 | height: 36px;
284 | font-size: 18px;
285 | }
286 |
287 | .xcloner-restore .steps .progress {
288 | display: none;
289 | }
290 |
291 | .xcloner-restore .status > div {
292 | margin: 10px 0px 0px 0px;
293 | }
294 |
295 | .xcloner-restore .toggler {
296 | display: inline-block;
297 | }
298 |
299 | .xcloner-restore .toggler .normal {
300 | display: block;
301 | }
302 |
303 | .xcloner-restore .toggler .cancel {
304 | display: none;
305 | }
306 |
307 | .xcloner-restore .toggler.cancel .normal {
308 | display: none;
309 | }
310 |
311 | .xcloner-restore .toggler.cancel .cancel {
312 | display: block;
313 | }
314 |
315 | .xcloner-restore ul.text-steps li {
316 | list-style-type: decimal;
317 | padding:5px 0px;
318 | }
319 |
320 | .xcloner-restore ul.text-steps li.warning {
321 | color: red;
322 | }
323 |
324 | .xcloner-restore ul.text-steps ul li {
325 | list-style-type: disc;
326 | }
327 |
328 | .xcloner-restore ul.text-steps ul {
329 | margin: 10px;
330 | }
331 |
332 | .xcloner-restore ul.text-steps {
333 | margin-left: 50px;
334 | }
335 |
336 | .xcloner-restore .restore-remote-backup-step .files-list {
337 | max-height: 250px;
338 | overflow: auto;
339 | margin: 10px 5px;
340 | }
341 |
342 | #backup_cotent_modal .modal-content .files-list span {
343 | cursor: pointer;
344 | }
345 |
346 | .xcloner-restore .query-box {
347 | display: none;
348 | }
349 |
350 | .xcloner-restore .query-box .query-list {
351 | height: 10rem;
352 | }
353 |
354 | .xcloner-restore .restore-remote-database-step h5 {
355 | margin-top: -10px;
356 | margin-bottom: 25px;
357 | }
358 |
359 | .regex_pattern {
360 | cursor: pointer;
361 | font-weight: bold;
362 | }
363 |
364 | .jstree-icon.jstree-checkbox.jstree-checkbox-disabled {
365 | opacity: 0.3;
366 | }
367 |
368 | #xcloner_regex_exclude {
369 | height: 5rem;
370 | }
371 |
372 | ul.xcloner_regex_exclude_limit li:nth-of-type(n+2) {
373 | display: none;
374 | }
375 |
376 | .xcloner-restore .btn.waves-effect.waves-light.grey {
377 | margin-top: -2px;
378 | }
379 |
380 | .xcloner-restore #xcloner_restore_finish {
381 | display: none;
382 | }
383 |
384 | ul.files-list li {
385 | padding: 0px;
386 | white-space: pre;
387 | }
388 |
389 | ul.files-list.error{
390 | color: red;
391 | }
392 |
393 | #manage_backups_wrapper #manage_backups_filter {
394 | min-width: 277px;
395 | }
396 |
397 | #generate_backup_form .progress, .xcloner-restore .progress {
398 | width: 100% !important;
399 | height: 4px !important;
400 | }
401 |
402 | i.backup_warning {
403 | color: orange;
404 | }
405 |
406 | .col.remote-storage-selection {
407 | padding-top: 0px;
408 | margin-bottom: -54px;
409 | }
410 |
411 | .remote-storage #authentification_code {
412 | display: none;
413 | }
414 |
415 | .dataTables_wrapper .dataTables_filter input {
416 | margin-left: 0px;
417 | }
418 |
419 | #backup_options .row{
420 | min-height: 30px;
421 | }
422 |
423 | .input-field .switch label {
424 | color: #000;
425 | }
426 |
427 | .wp-core-ui .select-wrapper select {
428 | border: 0px;
429 | }
430 |
431 | #save_schedule .switch {
432 | margin-top: 20px;
433 | }
434 |
435 | .collapsible-header i {
436 | vertical-align: middle;
437 | }
438 |
439 | #backup-status .title{
440 | display: inline;
441 | }
442 |
443 | .wp-core-ui select {
444 | max-width: initial;
445 | }
446 |
447 | .xcloner-menu.dropdown-trigger i.material-icons{
448 | vertical-align: middle;
449 | }
450 |
451 | .xcloner-menu.dropdown-content {
452 | min-width: 250px;
453 | }
454 |
455 | h1.xcloner-menu {
456 | margin: 1.68rem 0 1.68rem 0;
457 | }
458 |
459 | .xcloner-logo {
460 | max-height: 75px;
461 | max-width: 225px;
462 | float: right;
463 | margin-top: 15px;
464 | }
465 |
466 | .row.remote-storage .collapsible.popout>li {
467 | margin: 0px;
468 | }
469 |
470 | #generate_backup_form .nav-tab-wrapper-content {
471 | margin-top: 15px;
472 | }
473 |
474 | .row .nav-tab-wrapper{
475 | border-bottom: 0px;
476 | }
477 |
478 | .form-table tr{
479 | border-bottom: 0px;
480 | }
481 |
482 | #gdrive input#authentification_code::placeholder {
483 | color: red;
484 | }
485 |
486 | a:focus {
487 | box-shadow: none;
488 | }
489 |
490 | @media only screen and (min-width: 993px) {
491 | .dashboard .backup-ready {
492 | float: right;
493 | }
494 | }
495 |
496 |
497 | @media only screen and (max-width: 993px) {
498 | .xcloner-logo {
499 | display: none
500 | }
501 |
502 | .col.remote-storage-selection {
503 | padding-top: 0px;
504 | margin-bottom: 0px;
505 | }
506 | }
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.eot
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.woff
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Bold.woff2
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.eot
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.woff
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Light.woff2
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.eot
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.woff
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Medium.woff2
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.eot
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.woff
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.eot
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.woff
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/fonts/roboto/Roboto-Thin.woff2
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/Sorting icons.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/Sorting icons.psd
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/banners/CF Banner 728x90 blue.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/banners/CF Banner 728x90 blue.jpg
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/banners/CF Banner 728x90 red.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/banners/CF Banner 728x90 red.jpg
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/favicon.ico
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/sort_asc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/sort_asc.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/sort_asc_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/sort_asc_disabled.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/sort_both.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/sort_both.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/sort_desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/sort_desc.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/sort_desc_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/images/sort_desc_disabled.png
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/images/xcloner-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/index.php:
--------------------------------------------------------------------------------
1 | option[value="' + response.recurrence + '"]')
83 | .prop("selected", true);
84 | this.edit_modal
85 | .find('#backup_type>option[value="' + response.backup_type + '"]')
86 | .prop("selected", true);
87 | this.edit_modal
88 | .find(
89 | '#schedule_storage>option[value="' + response.remote_storage + '"]'
90 | )
91 | .prop("selected", true);
92 | //var date = new Date(response.start_at);
93 | this.edit_modal.find("#schedule_start_date").val(response.start_at);
94 |
95 | if (
96 | response.backup_params.backup_encrypt !== undefined &&
97 | response.backup_params.backup_encrypt == 1
98 | ) {
99 | this.edit_modal.find("#backup_encrypt").attr("checked", "checked");
100 | }
101 |
102 | if (
103 | response.backup_params.backup_delete_after_remote_transfer !== undefined &&
104 | response.backup_params.backup_delete_after_remote_transfer == 1
105 | ) {
106 | this.edit_modal.find("#backup_delete_after_remote_transfer").attr("checked", "checked");
107 | }
108 |
109 | var tables = jQuery.parseJSON(response.table_params);
110 |
111 | var tables_list = "";
112 |
113 | for (var db in tables) {
114 | for (var i in tables[db])
115 | tables_list += db + "." + tables[db][i] + "\n";
116 | }
117 |
118 | this.edit_modal.find("#table_params").val(tables_list);
119 |
120 | var files = jQuery.parseJSON(response.excluded_files);
121 | var exclude_files_list = "";
122 | for (var i in files) {
123 | exclude_files_list += files[i] + "\n";
124 | }
125 |
126 | this.edit_modal.find("#excluded_files").val(exclude_files_list);
127 |
128 | jQuery(".col select").formSelect();
129 |
130 | M.updateTextFields();
131 |
132 | edit_schedule_modal_instance.open();
133 | }
134 |
135 | save_schedule(form, dataTable) {
136 | var data = jQuery(form).serialize();
137 | var $this = this;
138 |
139 | jQuery
140 | .ajax({
141 | url: XCLONER_AJAXURL,
142 | dataType: "json",
143 | type: "POST",
144 | data: data,
145 | error: function (err) {
146 | //show_ajax_error("Communication Error", "", err)
147 | //console.log(err);
148 | alert("Error saving schedule!");
149 | },
150 | })
151 | .done(function (json) {
152 | if (json.error !== undefined) {
153 | alert("Error saving schedule!" + json.error);
154 | return;
155 | }
156 |
157 | edit_schedule_modal_instance.close();
158 | //location.reload();
159 | dataTable.ajax.reload();
160 | });
161 | }
162 |
163 | IsJsonString(str) {
164 | try {
165 | JSON.parse(str);
166 | } catch (e) {
167 | return false;
168 | }
169 | return true;
170 | }
171 |
172 | //end class
173 | }
174 |
175 | var xcloner_scheduler = new Xcloner_Scheduler();
176 |
177 | jQuery("select[required]").css({
178 | display: "block",
179 | height: 0,
180 | padding: 0,
181 | width: 0,
182 | position: "absolute",
183 | });
184 |
185 | let dataTable = jQuery("#scheduled_backups").DataTable({
186 | responsive: true,
187 | bFilter: false,
188 | order: [[3, "desc"]],
189 | buttons: ["selectAll", "selectNone"],
190 | language: {
191 | emptyTable: "No schedules available",
192 | buttons: {
193 | selectAll: "Select all items",
194 | selectNone: "Select none",
195 | },
196 | },
197 | columnDefs: [
198 | { targets: "no-sort", orderable: false },
199 | { className: "hide-on-med-and-down", targets: [3, 5] },
200 | ],
201 | ajax: XCLONER_AJAXURL + "&action=get_scheduler_list",
202 | fnDrawCallback: function (oSettings) {
203 | jQuery(this)
204 | .off("click", ".edit")
205 | .on("click", ".edit", function () {
206 | var hash = jQuery(this).attr("href");
207 | var id = hash.substr(1);
208 | var data = xcloner_scheduler.get_schedule_by_id(id);
209 | });
210 |
211 | jQuery(this)
212 | .off("click", ".delete")
213 | .on("click", ".delete", function () {
214 | var hash = jQuery(this).attr("href");
215 | var id = hash.substr(1);
216 | if (confirm("Are you sure you want to delete it?")) {
217 | var data = xcloner_scheduler.delete_schedule_by_id(
218 | id,
219 | this,
220 | dataTable
221 | );
222 | }
223 | });
224 |
225 | jQuery("span.shorten_string").each(function () {
226 | doShortText(jQuery(this));
227 | });
228 | jQuery("span.shorten_string").click(function () {
229 | jQuery(this).toggleClass("full");
230 | doShortText(jQuery(this));
231 | });
232 | },
233 | });
234 |
235 | jQuery("#save_schedule").on("submit", function () {
236 | xcloner_scheduler.save_schedule(jQuery(this), dataTable);
237 |
238 | return false;
239 | });
240 |
241 | var date_picker;
242 | var date_picker_allowed;
243 |
244 | if (typeof jQuery(".timepicker").pickatime === "function") {
245 | jQuery(".timepicker").pickatime({
246 | default: "now",
247 | min: [7, 30],
248 | twelvehour: false, // change to 12 hour AM/PM clock from 24 hour
249 | donetext: "OK",
250 | autoclose: false,
251 | vibrate: true, // vibrate the device when dragging clock hand
252 | });
253 | }
254 |
255 | if (typeof jQuery(".timepicker").pickadate === "function") {
256 | date_picker = jQuery(".datepicker").pickadate({
257 | format: "d mmmm yyyy",
258 | selectMonths: true, // Creates a dropdown to control month
259 | selectYears: 15, // Creates a dropdown of 15 years to control year
260 | min: +0.1,
261 | onSet: function () {
262 | //this.close();
263 | },
264 | });
265 |
266 | date_picker_allowed = jQuery(".datepicker_max_today").pickadate({
267 | format: "yyyy-mm-dd",
268 | selectMonths: true, // Creates a dropdown to control month
269 | selectYears: 15, // Creates a dropdown of 15 years to control year
270 | max: +0.1,
271 | onSet: function () {
272 | //this.close();
273 | },
274 | });
275 | }
276 | });
277 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/aws.php:
--------------------------------------------------------------------------------
1 |
7 |
21 |
22 |
23 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | " id="aws_key" type="text"
40 | name="xcloner_aws_key" class="validate" value=""
41 | autocomplete="off">
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | " id="aws_secret" type="text"
51 | name="xcloner_aws_secret" class="validate"
52 | value=""
53 | autocomplete="off">
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | " id="aws_region"
63 | type="text" name="xcloner_aws_region" class="validate"
64 | value="" autocomplete="off">
65 |
66 |
67 |
68 | get_aws_regions();
70 | foreach ($aws_regions as $key => $region) { ?>
71 | >
72 |
73 | =
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | "
88 | id="aws_endpoint" type="text" name="xcloner_aws_endpoint" class="validate"
89 | value="" autocomplete="off">
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | "
98 | id="aws_region" type="text" name="xcloner_aws_region" class="validate"
99 | value="" autocomplete="off">
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | " id="aws_bucket_name"
110 | type="text" name="xcloner_aws_bucket_name" class="validate"
111 | value="" autocomplete="off">
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | "
122 | id="aws_prefix" type="text" name="xcloner_aws_prefix" class="validate"
123 | value="" autocomplete="off">
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
133 | save
134 |
135 |
136 |
137 |
139 | import_export
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/azure.php:
--------------------------------------------------------------------------------
1 |
7 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | https://azure.microsoft.com/en-us/services/storage/blobs/') ?>
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | "
39 | id="azure_account_name" type="text" name="xcloner_azure_account_name" class="validate"
40 | value="" autocomplete="off">
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | " id="azure_api_key"
51 | type="text" name="xcloner_azure_api_key" class="validate"
52 | value="" autocomplete="off">
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | " id="azure_container"
62 | type="text" name="xcloner_azure_container" class="validate"
63 | value="">
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
73 | save
74 |
75 |
76 |
77 |
79 |
80 | import_export
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/backblaze.php:
--------------------------------------------------------------------------------
1 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | https://secure.backblaze.com/b2_buckets.htm') ?>
30 |
31 |
32 | If you specify only the bucket name , you must use the master key .
33 | However, if you specify both bucket name and bucket id , you do not need the master key and can use a single-bucket key .
34 |
35 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 | "
45 | id="backblaze_account_id" type="text" name="xcloner_backblaze_account_id" class="validate"
46 | value="" autocomplete="off">
47 |
48 |
49 |
50 |
51 |
52 |
53 |
55 |
56 |
57 | "
58 | id="backblaze_application_key" type="text" name="xcloner_backblaze_application_key" class="validate"
59 | value=""
60 | autocomplete="off">
61 |
62 |
63 |
64 |
65 |
66 |
68 |
69 |
70 | "
71 | id="backblaze_bucket_name" type="text" name="xcloner_backblaze_bucket_name" class="validate"
72 | value="" autocomplete="off">
73 |
74 |
75 |
76 |
77 |
78 |
80 |
81 |
82 | "
83 | id="backblaze_bucket_id" type="text" name="xcloner_backblaze_bucket_id" class="validate"
84 | value="" autocomplete="off">
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
94 | save
95 |
96 |
97 |
98 |
101 | import_export
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/dropbox.php:
--------------------------------------------------------------------------------
1 |
7 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | https://www.dropbox.com/developers/apps") ?>
29 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
38 |
39 | "
40 | id="dropbox_access_token" type="text" name="xcloner_dropbox_access_token" class="validate"
41 | value="" autocomplete="off">
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | "
52 | id="dropbox_app_secret" type="text" name="xcloner_dropbox_app_secret" class="validate"
53 | value=""
54 | autocomplete="off">
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | " id="dropbox_prefix"
64 | type="text" name="xcloner_dropbox_prefix" class="validate"
65 | value="">
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
75 | save
76 |
77 |
78 |
79 |
81 | import_export
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/ftp.php:
--------------------------------------------------------------------------------
1 |
7 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | "
35 | type="text" name="xcloner_ftp_hostname" class="validate"
36 | value="">
37 |
38 |
39 | " id="ftp_port" type="text"
40 | name="xcloner_ftp_port" class="validate"
41 | value="">
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | " id="ftp_username"
51 | type="text" name="xcloner_ftp_username" class="validate"
52 | value="" autocomplete="off">
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | " id="ftp_password"
63 | type="text" name="xcloner_ftp_password" class="validate"
64 | value=""
65 | autocomplete="off">
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | " id="ftp_root"
75 | type="text" name="xcloner_ftp_path" class="validate"
76 | value="">
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | " id="ftp_timeout"
136 | type="text" name="xcloner_ftp_timeout" class="validate"
137 | value="">
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
147 | save
148 |
149 |
150 |
151 |
153 | import_export
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/gdrive.php:
--------------------------------------------------------------------------------
1 | get_xcloner_container()->get_xcloner_remote_storage();
8 |
9 | $gdrive_auth_url = "";
10 |
11 | if (method_exists($remote_storage, "gdrive_get_auth_url")) {
12 | $gdrive_auth_url = $remote_storage->gdrive_get_auth_url();
13 | }
14 |
15 | $gdrive_construct = $remote_storage->gdrive_construct();
16 | ?>
17 |
32 |
33 |
34 |
35 |
36 |
46 |
47 |
62 |
63 |
64 |
73 |
74 | "
75 | id="gdrive_target_folder" type="text" name="xcloner_gdrive_target_folder" class="validate"
76 | value="" autocomplete="off">
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
86 |
87 |
105 |
106 |
107 |
108 |
109 |
111 | save
112 |
113 |
114 |
115 |
117 | import_export
118 |
119 |
120 |
121 |
122 |
123 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watchfulli/XCloner-Wordpress/ef00242abfee3a5734206d8a450c649ddc6e6536/xcloner-backup-and-restore/admin/partials/remote_storage/index.html
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/local.php:
--------------------------------------------------------------------------------
1 |
7 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | " id="aws_key"
26 | type="text" name="xcloner_start_path" class="validate"
27 | value="" autocomplete="off">
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | " id="aws_key"
37 | type="text" name="xcloner_store_path" class="validate"
38 | value="" autocomplete="off">
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
48 | save
49 |
50 |
51 |
52 |
54 | import_export
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/onedrive.php:
--------------------------------------------------------------------------------
1 |
7 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | Microsoft Azure App Registrations and get your Client ID and Client Secret. More details on setting up the code flow authentication can be found here .
29 | Make sure to also add the %s to the Authentication->Redirect URIs area', 'xcloner-backup-and-restore'), 'https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade', 'https://docs.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/graph-oauth?view=odsp-graph-online#code-flow', get_admin_url()) ?>
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | "
40 | id="onedrive_client_id" type="text" name="xcloner_onedrive_client_id" class="validate"
41 | value="" autocomplete="off">
42 |
43 |
44 |
45 |
46 |
47 |
49 |
50 |
51 | "
52 | id="onedrive_client_secret" type="text" name="xcloner_onedrive_client_secret" class="validate"
53 | value=""
54 | autocomplete="off">
55 |
56 |
57 |
58 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | "
76 | id="onedrive_path" type="text" name="xcloner_onedrive_path" class="validate"
77 | value="">
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
87 | save
88 |
89 |
90 |
91 |
93 | import_export
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/sftp.php:
--------------------------------------------------------------------------------
1 |
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | "
30 | id="sftp_host" type="text" name="xcloner_sftp_hostname" class="validate"
31 | value="">
32 |
33 |
34 | "
35 | id="sftp_port" type="text" name="xcloner_sftp_port" class="validate"
36 | value="">
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | "
46 | id="sftp_username" type="text" name="xcloner_sftp_username" class="validate"
47 | value="" autocomplete="off">
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | "
58 | id="ftp_spassword" type="text" name="xcloner_sftp_password" class="validate"
59 | value=""
60 | autocomplete="off">
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | "
83 | id="sftp_root" type="text" name="xcloner_sftp_path" class="validate"
84 | value="">
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | "
94 | id="sftp_timeout" type="text" name="xcloner_sftp_timeout" class="validate"
95 | value="">
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
105 | save
106 |
107 |
108 |
109 |
112 | import_export
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/remote_storage/webdav.php:
--------------------------------------------------------------------------------
1 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | https://secure.backblaze.com/b2_buckets.htm')?>
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | "
40 | id="webdav_url" type="text" name="xcloner_webdav_url" class="validate"
41 | value="" autocomplete="off">
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | "
51 | id="webdav_username" type="text" name="xcloner_webdav_username" class="validate"
52 | value="" autocomplete="off">
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | "
62 | id="webdav_password" type="text" name="xcloner_webdav_password"
63 | class="validate"
64 | value=""
65 | autocomplete="off">
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | "
75 | id="webdav_target_folder" type="text" name="xcloner_webdav_target_folder"
76 | class="validate"
77 | value=""
78 | autocomplete="off">
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
88 | save
89 |
90 |
91 |
92 |
95 | import_export
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/xcloner_console_page.php:
--------------------------------------------------------------------------------
1 | get_xcloner_container()->get_xcloner_settings();
4 | $logger = $this->get_xcloner_container()->get_xcloner_logger();
5 | $logger_content = $logger->getLastDebugLines();
6 | ?>
7 |
8 |
9 |
10 |
11 |
12 |
13 | get_xcloner_option('xcloner_enable_log')) : ?>
14 |
15 |
16 |
18 |
19 |
20 | \n", esc_html($logger_content));
23 | }
24 | ?>
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/xcloner_header.php:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
11 |
62 |
63 |
68 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/admin/partials/xcloner_remote_storage_page.php:
--------------------------------------------------------------------------------
1 | get_xcloner_container()->get_xcloner_remote_storage();
3 | ?>
4 |
5 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | "
23 | id="xcloner_{type}cleanup_retention_limit_days" type="text"
24 | name="xcloner_{type}cleanup_retention_limit_days" class="validate"
25 | value="">
26 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 | "
37 | id="xcloner_{type}cleanup_retention_limit_archives" type="number"
38 | name="xcloner_{type}cleanup_retention_limit_archives" class="validate"
39 | value="">
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | "
52 | id="xcloner_{type}cleanup_capacity_limit" type="number" name="xcloner_{type}cleanup_capacity_limit"
53 | class="validate" value="">
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | "
66 | id="xcloner_{type}cleanup_exclude_days" type="text" name="xcloner_{type}cleanup_exclude_days"
67 | class="validate" value="">
68 |
69 |
70 |
78 |
144 |
145 |
184 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "watchfulli/xcloner-wordpress",
3 | "license": "GPL-2.0-or-later",
4 | "description": "WordPress backup plugin for XCloner",
5 | "require": {
6 | "as247/flysystem-onedrive": "^1.0",
7 | "gliterd/backblaze-b2": "^1.5",
8 | "league/flysystem": "^1.0",
9 | "league/flysystem-aws-s3-v3": "^1.0",
10 | "league/flysystem-azure-blob-storage": "^0.1.6",
11 | "league/flysystem-sftp": "^1.0",
12 | "league/flysystem-webdav": "^1.0",
13 | "mhetreramesh/flysystem-backblaze": "^1.6",
14 | "monolog/monolog": "^1.22",
15 | "nao-pon/flysystem-google-drive": "^1.1",
16 | "splitbrain/php-archive": "^1.0",
17 | "srmklive/flysystem-dropbox-v2": "^1.0",
18 | "vakata/jstree": "^3.3"
19 | },
20 | "prefer-stable": true,
21 | "require-dev": {
22 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7",
23 | "phpcompatibility/phpcompatibility-wp": "*",
24 | "phpstan/extension-installer": "^1.1",
25 | "phpstan/phpstan": "^1.0",
26 | "phpunit/phpunit": "^7.0",
27 | "squizlabs/php_codesniffer": "3.*",
28 | "symfony/process": "^5.4",
29 | "szepeviktor/phpstan-wordpress": "^1.0",
30 | "yoast/phpunit-polyfills": "^1.0"
31 | },
32 | "scripts": {
33 | "test": "vendor/bin/phpunit --config=phpunit-integration.xml",
34 | "pre-autoload-dump": "Watchfulli\\XClonerCore\\Xcloner_Composer_Actions::cleanup",
35 | "post-autoload-dump": "Watchfulli\\XClonerCore\\Xcloner_Composer_Actions::prevent_vendor_direct_access"
36 | },
37 | "config": {
38 | "preferred-install": "dist",
39 | "sort-packages": true,
40 | "optimize-autoloader": true,
41 | "allow-plugins": {
42 | "bamarni/composer-bin-plugin": true,
43 | "dealerdirect/phpcodesniffer-composer-installer": true,
44 | "phpstan/extension-installer": true
45 | }
46 | },
47 | "extra": {
48 | "custom-commands": {
49 | "commands": [
50 | "ImaginaryMachines\\IsStableTagLatestTag"
51 | ]
52 | },
53 | "google/apiclient-services": [
54 | "Drive"
55 | ],
56 | "aws/aws-sdk-php": [
57 | "S3"
58 | ]
59 | },
60 | "autoload": {
61 | "psr-4": {
62 | "Watchfulli\\XClonerCore\\": "lib/"
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/index.php:
--------------------------------------------------------------------------------
1 | '.sprintf(__("XCloner requires minimum PHP version %s in order to run correctly. We have detected your version as %s"), Xcloner_Activator::xcloner_minimum_version, phpversion()).'', __("XCloner Activation Error"), array('response' => 500,
32 | 'back_link' => true
33 | ));
34 | }
35 |
36 | $charset_collate = $wpdb->get_charset_collate();
37 |
38 | $installed_ver = get_option("xcloner_db_version");
39 |
40 | $xcloner_db_version = Xcloner_Activator::xcloner_db_version;
41 |
42 | $xcloner_scheduler_table = $wpdb->prefix."xcloner_scheduler";
43 |
44 | if ($installed_ver != $xcloner_db_version) {
45 | $xcloner_schedule_sql = "CREATE TABLE `".$xcloner_scheduler_table."` (
46 | `id` int(11) NOT NULL AUTO_INCREMENT,
47 | `name` varchar(255) NOT NULL,
48 | `recurrence` varchar(25) NOT NULL,
49 | `params` text NOT NULL,
50 | `start_at` datetime,
51 | `remote_storage` varchar(10) DEFAULT NULL,
52 | `hash` varchar(10) DEFAULT NULL,
53 | `status` int(1) NOT NULL,
54 | `last_backup` varchar(100) DEFAULT NULL,
55 | PRIMARY KEY (`id`)
56 | ) " . $charset_collate.";
57 | ";
58 |
59 | require_once(ABSPATH.'wp-admin/includes/upgrade.php');
60 | dbDelta($xcloner_schedule_sql);
61 |
62 | update_option("xcloner_db_version", $xcloner_db_version);
63 | }
64 |
65 | if (get_option('xcloner_backup_compression_level') === false) {
66 | update_option('xcloner_backup_compression_level', 0);
67 | }
68 |
69 | if (get_option('xcloner_enable_log') === false) {
70 | update_option('xcloner_enable_log', 1);
71 | }
72 |
73 | if (get_option('xcloner_force_tmp_path_site_root') === false) {
74 | update_option('xcloner_force_tmp_path_site_root', 1);
75 | }
76 |
77 | if (get_option('xcloner_system_settings_page') === false) {
78 | update_option('xcloner_system_settings_page', 100);
79 | }
80 |
81 | if (get_option('xcloner_files_to_process_per_request') === false) {
82 | update_option('xcloner_files_to_process_per_request', 250);
83 | }
84 |
85 | if (get_option('xcloner_database_records_per_request') === false) {
86 | update_option('xcloner_database_records_per_request', 10000);
87 | }
88 |
89 | if (get_option('xcloner_exclude_files_larger_than_mb') === false) {
90 | update_option('xcloner_exclude_files_larger_than_mb', 0);
91 | }
92 |
93 | if (get_option('xcloner_split_backup_limit') === false) {
94 | update_option('xcloner_split_backup_limit', 2048);
95 | }
96 |
97 | if (get_option('xcloner_size_limit_per_request') === false) {
98 | update_option('xcloner_size_limit_per_request', 50);
99 | }
100 |
101 | if (get_option('xcloner_cleanup_retention_limit_days') === false) {
102 | update_option('xcloner_cleanup_retention_limit_days', 60);
103 | }
104 |
105 | if (get_option('xcloner_cleanup_retention_limit_archives') === false) {
106 | update_option('xcloner_cleanup_retention_limit_archives', 100);
107 | }
108 |
109 | if (get_option('xcloner_directories_to_scan_per_request') === false) {
110 | update_option('xcloner_directories_to_scan_per_request', 25);
111 | }
112 |
113 | if (!get_option('xcloner_regex_exclude')) {
114 | update_option('xcloner_regex_exclude', "(wp-content\/updraft|wp-content\/uploads\/wp_all_backup|wp-content\/ai1wm-backups|wp-content\/plugins\/akeebabackupwp\/app\/backups)(.*)\.(.*)$(?set_archive_name($archive_name);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_Composer_Actions.php:
--------------------------------------------------------------------------------
1 | isFile() && $file->getExtension() == 'php') {
28 | $contents = file_get_contents($file->getPathname());
29 |
30 | $check_to_add = "if (!defined('ABSPATH') && PHP_SAPI !== 'cli') { die(); }";
31 |
32 | if (strpos($contents, $check_to_add) !== false) {
33 | continue;
34 | }
35 |
36 | $contents = preg_replace('/namespace\s+([a-zA-Z0-9_\\\\]+);/m', "namespace $1;\n\n$check_to_add\n", $contents, 1);
37 |
38 | if (
39 | strpos($contents, $check_to_add) === false
40 | )
41 | {
42 | $contents = preg_replace('/namespace\s+([a-zA-Z0-9_\\\\]+)\s*{/', "namespace $1\n{\n$check_to_add", $contents, 1);
43 | }
44 |
45 | if (
46 | strpos($contents, 'declare(strict_types=1);') !== false &&
47 | strpos($contents, $check_to_add) === false
48 | ) {
49 | $contents = str_replace(
50 | "declare(strict_types=1);",
51 | "declare(strict_types=1);\n\n$check_to_add\n",
52 | $contents
53 | );
54 | }
55 |
56 | if (strpos($contents, $check_to_add) === false) {
57 | $contents = "" . $contents;
58 | }
59 |
60 | file_put_contents($file->getPathname(), $contents);
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_Deactivator.php:
--------------------------------------------------------------------------------
1 | get_xcloner_filesystem()->cleanup_tmp_directories();
17 | } catch (Exception $e) {
18 | $xcloner_plugin->trigger_message_notice($e->getMessage());
19 | }
20 |
21 | $xcloner_scheduler = $xcloner_plugin->get_xcloner_scheduler();
22 | $xcloner_scheduler->deactivate_wp_cron_hooks();
23 | }
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_File_Transfer.php:
--------------------------------------------------------------------------------
1 |
13 | *
14 | * This program is free software; you can redistribute it and/or modify
15 | * it under the terms of the GNU General Public License as published by
16 | * the Free Software Foundation; either version 2 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful,
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | *
24 | * You should have received a copy of the GNU General Public License
25 | * along with this program; if not, write to the Free Software
26 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 | * MA 02110-1301, USA.
28 | *
29 | * @link https://github.com/ovidiul/XCloner-Wordpress
30 | *
31 | * @modified 7/25/18 1:46 PM
32 | *
33 | */
34 | class Xcloner_File_Transfer extends Xcloner_Filesystem
35 | {
36 |
37 | /**
38 | * Target url web address of the restore script
39 | *
40 | * @var string
41 | */
42 | private $target_url;
43 | /**
44 | * Transfer data limit in bytes
45 | *
46 | * @var int
47 | */
48 | private $transfer_limit = 1048576; // Bytes 1MB= 1048576 300KB = 358400.
49 |
50 |
51 | /**
52 | * Set target method
53 | *
54 | * @param $target_url
55 | *
56 | * @return mixed
57 | */
58 | public function set_target($target_url)
59 | {
60 | return $this->target_url = $target_url;
61 | }
62 |
63 | /**
64 | * @param $file
65 | * @param int $start
66 | * @param string $hash
67 | *
68 | * @return bool|int
69 | * @throws Exception
70 | */
71 | public function transfer_file($file, $start = 0, $hash = "")
72 | {
73 | if (!$this->target_url) {
74 | throw new Exception("Please setup a target url for upload");
75 | }
76 |
77 |
78 | $fp = $this->get_storage_filesystem()->readStream($file);
79 |
80 | fseek($fp, $start);
81 |
82 | $binary_data = fread($fp, $this->transfer_limit);
83 |
84 | $tmp_filename = "xcloner_upload_" . substr(md5(time()), 0, 5);
85 |
86 | $this->get_tmp_filesystem()->write($tmp_filename, $binary_data);
87 |
88 | $tmp_file_path = $this->get_tmp_filesystem_adapter()->applyPathPrefix($tmp_filename);
89 |
90 | $send_array = array();
91 |
92 | $send_array['file'] = $file;
93 | $send_array['start'] = $start;
94 | $send_array['xcloner_action'] = "write_file";
95 | $send_array['hash'] = $hash;
96 | #$send_array['blob'] = $binary_data;
97 | $send_array['blob'] = $this->curl_file_create($tmp_file_path, 'application/x-binary', $tmp_filename);
98 |
99 | //$data = http_build_query($send_array);
100 |
101 | $this->get_logger()->info(sprintf(
102 | "Sending curl request to %s with %s data of file %s starting position %s using temporary file %s",
103 | $this->target_url,
104 | $this->transfer_limit,
105 | $file,
106 | $start,
107 | $tmp_filename
108 | ));
109 |
110 |
111 | $ch = curl_init();
112 | curl_setopt($ch, CURLOPT_URL, $this->target_url);
113 |
114 | curl_setopt($ch, CURLOPT_POST, 1);
115 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
116 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
117 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
118 | curl_setopt($ch, CURLOPT_TIMEOUT, 1200);
119 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
120 |
121 | curl_setopt($ch, CURLOPT_POSTFIELDS, $send_array);
122 | curl_setopt($ch, CURLOPT_VERBOSE, true);
123 |
124 | $original_result = curl_exec($ch);
125 |
126 |
127 | $this->get_tmp_filesystem()->delete($tmp_filename);
128 |
129 | $result = json_decode($original_result);
130 |
131 | if (!$result) {
132 | throw new Exception("We have received no valid response from the remote host, original message: " . $original_result);
133 | }
134 |
135 | if ($result->status != 200) {
136 | throw new Exception($result->response);
137 | }
138 |
139 | if (ftell($fp) >= $this->get_storage_filesystem()->getSize($file)) {
140 | $this->get_logger()->info(sprintf(
141 | "Upload done for file %s to target url %s, transferred a total of %s bytes",
142 | $file,
143 | $this->target_url,
144 | ftell($fp)
145 | ));
146 | $this->remove_tmp_filesystem();
147 |
148 | return false;
149 | }
150 |
151 | return ftell($fp);
152 | }
153 |
154 | /**
155 | * @param string $filename
156 | * @param string $mimetype
157 | * @param string $postname
158 | *
159 | * @return CURLFile|string
160 | */
161 | private function curl_file_create($filename, $mimetype = '', $postname = '')
162 | {
163 | if (!function_exists('curl_file_create')) {
164 | return "@$filename;filename="
165 | . ($postname ?: basename($filename))
166 | . ($mimetype ? ";type=$mimetype" : '');
167 | } else {
168 | return curl_file_create($filename, $mimetype, $postname);
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_Loader.php:
--------------------------------------------------------------------------------
1 |
10 | *
11 | * This program is free software; you can redistribute it and/or modify
12 | * it under the terms of the GNU General Public License as published by
13 | * the Free Software Foundation; either version 2 of the License, or
14 | * (at your option) any later version.
15 | *
16 | * This program is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU General Public License
22 | * along with this program; if not, write to the Free Software
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 | * MA 02110-1301, USA.
25 | *
26 | * @link https://github.com/ovidiul/XCloner-Wordpress
27 | *
28 | * @modified 7/25/18 1:46 PM
29 | *
30 | */
31 |
32 |
33 | /**
34 | * Register all actions and filters for the plugin.
35 | *
36 | * Maintain a list of all hooks that are registered throughout
37 | * the plugin, and register them with the WordPress API. Call the
38 | * run function to execute the list of actions and filters.
39 | *
40 | * @package Xcloner
41 | * @subpackage Xcloner/includes
42 | * @author Liuta Ovidiu
43 | */
44 | class Xcloner_Loader
45 | {
46 |
47 | /**
48 | * The array of actions registered with WordPress.
49 | *
50 | * @since 1.0.0
51 | * @access protected
52 | * @var array $actions The actions registered with WordPress to fire when the plugin loads.
53 | */
54 | protected $actions;
55 |
56 | /**
57 | * The array of filters registered with WordPress.
58 | *
59 | * @since 1.0.0
60 | * @access protected
61 | * @var array $filters The filters registered with WordPress to fire when the plugin loads.
62 | */
63 | protected $filters;
64 |
65 | /**
66 | * @var Xcloner
67 | */
68 | private $xcloner_container;
69 |
70 |
71 | /**
72 | * Initialize the collections used to maintain the actions and filters.
73 | *
74 | * Xcloner_Loader constructor.
75 | * @param Xcloner $xcloner_container
76 | */
77 | public function __construct(Xcloner $xcloner_container)
78 | {
79 |
80 | $this->actions = array();
81 | $this->filters = array();
82 |
83 | $this->xcloner_container = $xcloner_container;
84 |
85 | }
86 |
87 | /**
88 | * Add a new action to the collection to be registered with WordPress.
89 | *
90 | * @param string $hook The name of the WordPress action that is being registered.
91 | * @param array $callback The name of the function definition on the $component.
92 | * @param int $priority Optional. he priority at which the function should be fired. Default is 10.
93 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
94 | * @since 1.0.0
95 | */
96 | public function add_action($hook, $callback, $priority = 10, $accepted_args = 1)
97 | {
98 | $this->actions = $this->add($this->actions, $hook, $callback[0], $callback[1], $priority, $accepted_args);
99 | }
100 |
101 | /**
102 | * Add a new filter to the collection to be registered with WordPress.
103 | *
104 | * @param string $hook The name of the WordPress filter that is being registered.
105 | * @param object $component A reference to the instance of the object on which the filter is defined.
106 | * @param string $callback The name of the function definition on the $component.
107 | * @param int $priority Optional. he priority at which the function should be fired. Default is 10.
108 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
109 | * @since 1.0.0
110 | */
111 | public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1)
112 | {
113 | $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args);
114 | }
115 |
116 | /**
117 | * A utility function that is used to register the actions and hooks into a single
118 | * collection.
119 | *
120 | * @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
121 | * @param string $hook The name of the WordPress filter that is being registered.
122 | * @param object $component A reference to the instance of the object on which the filter is defined.
123 | * @param string $callback The name of the function definition on the $component.
124 | * @param int $priority The priority at which the function should be fired.
125 | * @param int $accepted_args The number of arguments that should be passed to the $callback.
126 | * @return array The collection of actions and filters registered with WordPress.
127 | * @since 1.0.0
128 | * @access private
129 | */
130 | private function add($hooks, $hook, $component, $callback, $priority, $accepted_args)
131 | {
132 |
133 | $hooks[] = array(
134 | 'hook' => $hook,
135 | 'component' => $component,
136 | 'callback' => $callback,
137 | 'priority' => $priority,
138 | 'accepted_args' => $accepted_args
139 | );
140 |
141 | return $hooks;
142 |
143 | }
144 |
145 | /**
146 | * Register the filters and actions with WordPress.
147 | *
148 | * @since 1.0.0
149 | */
150 | public function run()
151 | {
152 | foreach ($this->filters as $hook) {
153 | add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
154 | }
155 |
156 | foreach ($this->actions as $hook) {
157 | add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
158 | }
159 |
160 | }
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_Logger.php:
--------------------------------------------------------------------------------
1 | get_xcloner_settings()) {
25 | $xcloner_settings = new Xcloner_Settings($xcloner_container);
26 | } else {
27 | $xcloner_settings = $xcloner_container->get_xcloner_settings();
28 | }
29 |
30 | $hash = $xcloner_settings->get_hash();
31 | if ($hash == "-" . $xcloner_settings->get_server_unique_hash(5)) {
32 | $hash = "";
33 | }
34 |
35 | $logger_path = $xcloner_settings->get_xcloner_store_path() . DS . $xcloner_settings->get_logger_filename();
36 | $logger_path_tmp = "";
37 |
38 | if ($hash) {
39 | $logger_path_tmp = $xcloner_settings->get_xcloner_tmp_path() . DS . $xcloner_settings->get_logger_filename(1);
40 | }
41 |
42 | $this->logger_path = $logger_path;
43 |
44 | if (!is_dir($xcloner_settings->get_xcloner_store_path()) or !is_writable($xcloner_settings->get_xcloner_store_path())) {
45 | $logger_path = 'php://stderr';
46 | $logger_path_tmp = "";
47 | }
48 |
49 | if (!$xcloner_settings->get_xcloner_option('xcloner_enable_log')) {
50 | $logger_path = 'php://stderr';
51 | $logger_path_tmp = "";
52 | }
53 |
54 | // create a log channel
55 | parent::__construct($logger_name);
56 |
57 | $debug_level = Logger::INFO;
58 |
59 | if (defined('WP_DEBUG') && WP_DEBUG) {
60 | $debug_level = Logger::DEBUG;
61 | }
62 |
63 | if ($logger_path) {
64 | if (!$xcloner_settings->get_xcloner_option('xcloner_enable_log')) {
65 | $stream = new StreamHandler($logger_path, $debug_level);
66 | } else {
67 | $stream = new RotatingFileHandler($logger_path, $this->max_logger_files, $debug_level);
68 | }
69 |
70 | $this->pushHandler($stream);
71 |
72 | $this->main_logger_url = $stream->getUrl();
73 | }
74 |
75 | if ($hash and $logger_path_tmp) {
76 | $this->pushHandler(new StreamHandler($logger_path_tmp, $debug_level));
77 | }
78 |
79 | //return $this;
80 | }
81 |
82 | /**
83 | * @return string|null
84 | */
85 | public function get_main_logger_url()
86 | {
87 | return $this->main_logger_url;
88 | }
89 |
90 | /**
91 | * @param int $totalLines
92 | * @return array|bool
93 | */
94 | public function getLastDebugLines($totalLines = 200)
95 | {
96 | $lines = array();
97 |
98 | if (!file_exists($this->main_logger_url) or !is_readable($this->main_logger_url)) {
99 | return false;
100 | }
101 |
102 | $fp = fopen($this->main_logger_url, 'r');
103 | fseek($fp, -1, SEEK_END);
104 | $pos = ftell($fp);
105 | $lastLine = "";
106 |
107 | // Loop backword until we have our lines or we reach the start
108 | while ($pos > 0 && count($lines) < $totalLines) {
109 | $C = fgetc($fp);
110 | if ($C == "\n") {
111 | // skip empty lines
112 | if (trim($lastLine) != "") {
113 | $lines[] = $lastLine;
114 | }
115 | $lastLine = '';
116 | } else {
117 | $lastLine = $C . $lastLine;
118 | }
119 | fseek($fp, $pos--);
120 | }
121 |
122 | $lines = array_reverse($lines);
123 |
124 | return $lines;
125 | }
126 |
127 | /**
128 | * Info message logging
129 | *
130 | * @param [type] $msg
131 | * @param boolean $print
132 | * @return void
133 | */
134 | public function print_info($message, $context = array())
135 | {
136 | if (php_sapi_name() == "cli" && !WP_DEBUG && !defined('XCLONER_DISABLE_OUTPUT')) {
137 | echo sprintf("[%s] %s \n", date("Y-m-d H:i:s"), $message);
138 | }
139 | return parent::info($message, $context);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_Requirements.php:
--------------------------------------------------------------------------------
1 | xcloner_container = $xcloner_container;
14 | $this->xcloner_settings = $xcloner_container->get_xcloner_settings();
15 | }
16 |
17 | public function check_backup_ready_status()
18 | {
19 | if (!$this->check_min_php_version(1)) {
20 | return false;
21 | }
22 |
23 | if (!$this->check_xcloner_start_path(1)) {
24 | return false;
25 | }
26 |
27 | if (!$this->check_xcloner_store_path(1)) {
28 | return false;
29 | }
30 |
31 | if (!$this->check_xcloner_tmp_path(1)) {
32 | return false;
33 | }
34 |
35 | return true;
36 | }
37 |
38 | public function check_min_php_version($return_bool = 0)
39 | {
40 |
41 | if ($return_bool == 1) {
42 | if (version_compare(phpversion(), self::MIN_PHP_VERSION, '<')) {
43 | return false;
44 | } else {
45 | return true;
46 | }
47 | }
48 |
49 | return phpversion();
50 | }
51 |
52 | public function check_xcloner_start_path($return_bool = 0)
53 | {
54 | $path = $this->xcloner_settings->get_xcloner_start_path();
55 |
56 | if ($return_bool) {
57 | if (!file_exists($path)) {
58 | return false;
59 | }
60 |
61 | return is_readable($path);
62 | }
63 |
64 | return $path;
65 | }
66 |
67 | public function check_xcloner_tmp_path($return_bool = 0)
68 | {
69 | $path = $this->xcloner_settings->get_xcloner_tmp_path();
70 |
71 | if ($return_bool) {
72 | if (!file_exists($path)) {
73 | return false;
74 | }
75 |
76 | if (!is_writeable($path)) {
77 | @chmod($path, 0777);
78 | }
79 |
80 | return is_writeable($path);
81 | }
82 |
83 | return $path;
84 | }
85 |
86 | public function check_xcloner_store_path($return_bool = 0)
87 | {
88 | $path = $this->xcloner_settings->get_xcloner_store_path();
89 |
90 | if ($return_bool) {
91 | if (!file_exists($path)) {
92 | return false;
93 | }
94 |
95 | if (!is_writeable($path)) {
96 | @chmod($path, 0777);
97 | }
98 |
99 | return is_writeable($path);
100 | }
101 |
102 | return $path;
103 | }
104 |
105 | public function get_max_execution_time()
106 | {
107 | return ini_get('max_execution_time');
108 | }
109 |
110 | public function get_memory_limit()
111 | {
112 | return ini_get('memory_limit');
113 | }
114 |
115 | public function get_open_basedir()
116 | {
117 | $open_basedir = ini_get('open_basedir');
118 |
119 | if (!$open_basedir) {
120 | $open_basedir = "none";
121 | }
122 |
123 | return $open_basedir;
124 | }
125 |
126 | public function get_free_disk_space()
127 | {
128 | return $this->file_format_size(disk_free_space($this->xcloner_settings->get_xcloner_store_path()));
129 | }
130 |
131 | public function file_format_size($bytes, $decimals = 2)
132 | {
133 | $unit_list = array('B', 'KB', 'MB', 'GB', 'PB');
134 |
135 | if ($bytes == 0) {
136 | return $bytes . ' ' . $unit_list[0];
137 | }
138 |
139 | $unit_count = count($unit_list);
140 | for ($i = $unit_count - 1; $i >= 0; $i--) {
141 | $power = $i * 10;
142 | if (($bytes >> $power) >= 1) {
143 | return round($bytes / (1 << $power), $decimals) . ' ' . $unit_list[$i];
144 | }
145 | }
146 |
147 | return $bytes . ' ' . $unit_list[0];
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/lib/Xcloner_Sanitization.php:
--------------------------------------------------------------------------------
1 |
10 | *
11 | * This program is free software; you can redistribute it and/or modify
12 | * it under the terms of the GNU General Public License as published by
13 | * the Free Software Foundation; either version 2 of the License, or
14 | * (at your option) any later version.
15 | *
16 | * This program is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU General Public License
22 | * along with this program; if not, write to the Free Software
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 | * MA 02110-1301, USA.
25 | *
26 | * @link https://github.com/ovidiul/XCloner-Wordpress
27 | *
28 | * @modified 7/25/18 1:46 PM
29 | *
30 | */
31 |
32 |
33 | /**
34 | * Define the internationalization functionality.
35 | *
36 | * Loads and defines the internationalization files for this plugin
37 | * so that it is ready for translation.
38 | *
39 | * @since 1.0.0
40 | * @package Xcloner
41 | * @subpackage Xcloner/includes
42 | * @author Liuta Ovidiu
43 | */
44 | class Xcloner_i18n
45 | {
46 |
47 | /**
48 | * Load the plugin text domain for translation.
49 | *
50 | * @since 1.0.0
51 | */
52 | public function load_plugin_textdomain()
53 | {
54 |
55 | load_plugin_textdomain(
56 | 'xcloner-backup-and-restore',
57 | false,
58 | dirname(dirname(plugin_basename(__FILE__))) . '/languages/'
59 | );
60 |
61 | }
62 |
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/xcloner-backup-and-restore/uninstall.php:
--------------------------------------------------------------------------------
1 | should_run()) {
43 | try {
44 | $xcloner_cli->run();
45 | } catch (Exception $e) {
46 | echo $e->getMessage() . "\n";
47 | }
48 | return;
49 | }
50 |
51 | // If this file is called directly, and we're not in CLI mode, then exit.
52 | if (!defined('WPINC')) {
53 | die;
54 | }
55 |
56 |
57 | if (function_exists('register_activation_hook')) {
58 | register_activation_hook(__FILE__, [new Xcloner_Activator(), 'activate']);
59 | }
60 |
61 | if (function_exists('register_deactivation_hook')) {
62 | register_deactivation_hook(__FILE__, [new Xcloner_Deactivator(), 'deactivate']);
63 | }
64 |
65 | if (version_compare(phpversion(), Xcloner_Activator::xcloner_minimum_version, '<')) {
66 | ?>
67 |
70 | check_dependencies();
131 |
132 | $xcloner->init();
133 | $xcloner->run();
134 | }
135 |
136 | try {
137 | run_xcloner();
138 | } catch (Exception $e) {
139 | echo $e->getMessage();
140 | }
141 |
--------------------------------------------------------------------------------