=== Luzid Backup to Nextcloud === Contributors: luzidmedia Tags: backup, nextcloud, webdav, cron, rotation Requires at least: 5.8 Tested up to: 6.9 Requires PHP: 7.4 Stable tag: 1.3.2 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Upload WordPress backup files to Nextcloud via WebDAV, with optional rotation and retention management. == Description == **Luzid Backup to Nextcloud** uploads your existing WordPress backup files to a Nextcloud folder via WebDAV. It is designed for two main workflows: 1. **Automate offsite copies**: upload backup archives on a schedule (WordPress Cron). 2. **Manual runs + monitoring**: start uploads manually and follow progress + logs. Typical use cases: * Keep an offsite copy of backup archives generated by popular backup plugins. * Upload backups to a structured Nextcloud folder (per source, per domain). * Reduce storage usage with optional rotation (keep only the last N backup sets per source). Core concepts: * **Sources** – each source represents a folder where backup files are created (UpdraftPlus, BackWPup, WPvivid, All-in-One WP Migration, Duplicator, or custom). * **Upload** – the plugin scans sources for backup files and uploads them to Nextcloud via WebDAV PUT. * **Streaming** – files larger than 2 MB are uploaded via cURL streaming (reads from disk, never loads the entire file into RAM). This prevents memory and timeout issues on shared hosting. * **Schedule** – optional daily/weekly/monthly runs at a fixed time (WordPress Cron; traffic-dependent). * **Rotation** – keep the newest N backup sets and remove older ones on Nextcloud. * **Email Reporting** – get notified on successful or failed transfers. == Features == * Nextcloud WebDAV connection with one-click Save & Test * Password field with visibility toggle and browser autofill protection * Multiple backup sources (known plugins + custom folders) * File filters by extension * Streaming uploads for large files (low RAM usage) * Manual upload with progress modal * Scheduled runs: Daily, Weekly, or Monthly (WordPress Cron) * Email notifications for successful/failed transfers * Log viewer with clear function * Rotation / retention (keep last N backup sets) * Context-aware action buttons per tab * German and English admin UI with integrated How-To guide == Installation == 1. Upload the plugin folder to `/wp-content/plugins/` or install via the WordPress Plugins screen. 2. Activate **Luzid Backup to Nextcloud**. 3. Go to **WP Admin → Luzid WP Tools → Backup to Nextcloud**. == Usage == = 1. Setup (connection) = 1. Fill in WebDAV URL, username, app password, and remote folder. 2. Click **Save & Test** – this saves settings and tests the connection in one step. = 2. Backup Sources = 1. Switch to the **Backup Sources** tab. 2. Enable one or more sources (paths and extensions are pre-filled). 3. Click **Save Settings**. = 3. Manual Upload = 1. Click **Start Manual Upload** (available once a source is enabled). 2. A progress modal shows the upload status. = 4. Schedule + Rotation = * Enable the schedule, choose frequency and time, then save. * Enable rotation and choose how many backup sets to keep. == Frequently Asked Questions == = Does this plugin create backups? = No. It uploads backup archives created by other tools. Configure your backup plugin first. = Why does the schedule not run exactly on time? = WordPress Cron is traffic-based. If the site has no visits around the scheduled time, the run may be delayed. = Should I use a normal password or an app password? = Always use a Nextcloud **App Password** (Settings → Security → Devices & Sessions). = My upload gets stuck on large files = The plugin streams files larger than 2 MB via cURL to avoid PHP memory limits. If uploads still time out, check your hosting provider's PHP `max_execution_time` setting. = Is my Nextcloud password stored securely? = Yes. Since version 1.3.2, the app password is encrypted at rest using AES-256-CBC with your site's unique `AUTH_KEY` from `wp-config.php`. The password is only decrypted in memory when performing WebDAV requests. Existing plaintext passwords are automatically encrypted on the next page load or upload run. = The password field is filled with the wrong password = Click the eye icon next to the password field to reveal and verify the content. The field uses `autocomplete="new-password"` to prevent browser autofill, but some browsers may still fill it. Clear the field and enter your Nextcloud app password manually. == License == This plugin is licensed under the **GNU General Public License v2.0 or later**. == Changelog == = 1.3.2 = * **Security: Password encryption at rest** – The Nextcloud app password is now encrypted in the database using AES-256-CBC with the site's `AUTH_KEY`. Existing plaintext passwords are automatically migrated on first use. Graceful fallback if OpenSSL is not available on the server. = 1.3.1 = * **Fixed: Upload timeout with many files** – `set_time_limit()` is now called before each individual file upload, preventing PHP from killing the process after 20-30 files. Progress bar now updates per file (e.g. "Uploading file 47/187") instead of per source. * **Fixed: Language preference not saved** – Switching to English/German is now persisted in the database. The chosen language stays active across page reloads and redirects. = 1.3.0 = * **Streaming uploads**: Files > 2 MB are now uploaded via cURL streaming (reads from disk, never loads entire file into RAM). Solves timeout and memory issues on shared hosting with large backup files. * **Context-aware buttons**: Each tab shows only the relevant action buttons. Setup shows only "Save & Test"; Backup Sources and Schedule show "Save Settings"; How-To hides all buttons. * **Upload button gating**: "Start Manual Upload" is disabled (greyed out) until at least one backup source is enabled. * **Password field improvements**: Visibility toggle (eye icon), `autocomplete="new-password"` to prevent browser autofill, renamed form field name to avoid browser recognition. * **Removed "Remove password" checkbox**: Passwords are now simply replaced by entering a new one. * **Default source paths**: Backup source paths and file extensions always fall back to sensible defaults (even after reset). Empty fields are never saved – defaults are restored automatically. * **"Delete All Settings" preserves defaults**: Resetting the plugin now keeps default source paths and extensions intact, only clears user configuration, logs, and schedule. * **Guided setup flow**: New hint text on Setup tab guides users through the configuration process. * **Updated How-To guides**: German and English documentation rewritten to match current UI and features. * **Fixed**: `$log` / `$source` / `$s` variable reference bugs from prefix renaming. * **Fixed**: Sources tab fields (path, extensions) now save correctly. = 1.2.9 = * **WordPress.org Review Compliance** – all review team requirements addressed * Fixed: Removed invalid Author URI (luzid.app) * Fixed: Contributors changed from "luzid" to "luzidmedia" * Fixed: Replaced `WP_CONTENT_DIR` constant with `wp_normalize_path( dirname() )` * Fixed: Explicit field extraction from `$_POST` instead of processing the whole stack * Fixed: JS object name `luzidBackup` renamed to `luzid_backup_data` (prefixed) * Fixed: All global variables in admin-page.php prefixed with `luzid_btn_` = 1.2.4 = * Settings now save correctly on first install * WebDAV credentials persist after "Save & Test" * Better fallback handling for tab detection = 1.2.3 = * Replaced cURL with wp_remote_request() for WordPress compliance * All PHPCS warnings resolved = 1.2.2 = * All date() replaced with gmdate() * All wp_redirect() replaced with wp_safe_redirect() * Proper wp_unslash() + sanitize everywhere = 1.2.1 = * Initial public release with full feature set = 1.2.0 = * Beta release == Upgrade Notice == = 1.3.2 = Password encryption at rest. Existing passwords are auto-migrated. Recommended security update. = 1.3.1 = Fixes upload timeout with many files and language persistence. = 1.3.0 = Streaming uploads for large files, improved UI with context-aware buttons, password field improvements.