=== DadsFam Backups ===
Contributors: dadsfam
Tags: backup, restore, database backup, migration, scheduled backup
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 1.11.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Reliable, resumable WordPress backups — full database and files, scheduled or on-demand, with one-click restore. Honest freemium.

== Description ==

**DadsFam Backups** keeps a safety net under your WordPress site. Back up your database and files whenever you like, or set a schedule and forget about it. When something goes wrong, restore in a few clicks.

It's built for real-world hosting. Big sites usually choke other backup plugins because PHP runs out of time or memory halfway through. DadsFam Backups works in small, resumable steps instead — so a backup that's too big to finish in one go simply picks up where it left off until it's done.

= What you get (free) =

* **Full backups** — database + plugins, themes, uploads, and the rest of `wp-content`. Pick exactly what to include.
* **Resumable engine** — large sites back up in bounded chunks and never time out.
* **One-click restore** — restore the database, files, or both, right from the dashboard.
* **Scheduled backups** — daily, weekly or monthly at a time you choose. No server cron setup needed; it runs through WordPress and heals its own schedule.
* **Smart retention** — automatically keep only the most recent N backups.
* **Exclusions** — skip caches, `node_modules`, logs and anything else with simple patterns.
* **Email notifications** — get told when a backup finishes or fails.
* **Activity log** — a clear history of every backup, restore and scheduled run.
* **Secure storage** — backups live in a protected folder (no public web access) and downloads are nonce + capability protected.
* **Off-site copies to Google Drive or OneDrive** — connect an account in one click and every backup gets a second home. Uploads are resumable and continue in the background, so a big archive finishes even on a slow shared host.
* **Restore from the cloud** — lost the server, or deleted the local copy? Pick an off-site backup and it is pulled back onto your site, resuming by itself if the connection drops. Then restore it normally.

= Built honestly =

No nag screens, no crippled free version, no surprise server configuration. The free plugin really backs up and really restores your whole site.

= Going further with Pro =

An optional commercial add-on, DadsFam Backups Pro, adds more off-site destinations (Amazon S3 and S3-compatible, FTP/FTPS, SFTP), encrypted off-site copies and advanced schedules. It is a separate plugin and is not required — Google Drive, OneDrive and cloud restore are all part of this plugin. Pro is at [plugins.dadsfam.co.za](https://plugins.dadsfam.co.za/).

= External services =

Connecting Google Drive or OneDrive is optional and nothing is sent anywhere until you connect an account.

When you do, this plugin uses the DadsFam connection service at `https://connect.dadsfam.co.za` to handle the sign-in. You are sent there to approve access, and it returns a one-time code that this site swaps for an access token server-to-server, so the token never travels through your browser. The service receives the provider you chose and the address to send you back to. Terms of use and privacy policy: [dadsfam.co.za/privacy-policy](https://www.dadsfam.co.za/privacy-policy/) and [plugins.dadsfam.co.za/privacy-policy](https://plugins.dadsfam.co.za/privacy-policy/).

Once connected, your site talks directly to Google (`googleapis.com`) or Microsoft (`graph.microsoft.com`) to upload and download your backups. Nothing passes through DadsFam.

= A word about PRO =

Right, let me be straight with you, because I hate being sold to as much as you do.

Everything above is free and it stays free. Backing your site up on a schedule, restoring it, cloning it to a new domain, downloading the archive, verifying every backup is not corrupt — none of those are premium features. Those are things a backup plugin should just do, and if I put them behind a paywall I would be taking the mickey.

There is a PRO add-on. It exists because I am a dad in Cape Town, and this is one of the things that puts food on the table at my house. That is the honest reason. Not "unlock your potential", not "supercharge your workflow". Just: if this plugin saved your site and you can spare it, PRO helps me keep building.

What PRO adds is the stuff you only want once your backups need to live somewhere other than the same server as your site — sending each one off to Amazon S3, an FTP or SFTP box, Google Drive or OneDrive, encrypting those off-site copies, keeping a set number of them out there, and running on a tighter schedule. That is convenience and peace of mind. It is not the plugin working properly, because the plugin already works properly.

So if the free one does everything you need, brilliant. Genuinely. Use it, and I hope it saves you the afternoon nobody wants — the one where the site is gone and there is no backup. If you get to the point where off-site copies would let you sleep easier, PRO is at plugins.dadsfam.co.za.

Either way, thanks for using something I built. — Zak, DadsFam

PRO adds:

- Off-site backups to Amazon S3 and S3-compatible storage (Wasabi, Backblaze B2, DigitalOcean Spaces, MinIO)
- FTP, FTPS and SFTP destinations
- Google Drive and OneDrive
- Encrypted off-site copies
- Remote retention — keep a set number of backups off-site
- More frequent, advanced backup schedules

== Installation ==

1. In your WordPress admin, go to **Plugins → Add New → Upload Plugin**.
2. Upload the `dadsfam-backups.zip` file and click **Install Now**.
3. Click **Activate**.
4. Open **DadsFam Backups** from the admin menu and create your first backup.

Your server needs the PHP **zip** extension (ZipArchive). Almost all hosts have this; if not, ask your host to enable it.

== Frequently Asked Questions ==

= Where are my backups stored? =
In `wp-content/uploads/dadsfam-backups/`, inside a folder protected from direct web access. You can also download any backup to your computer.

= Will a backup time out on a big site? =
No. The backup runs as a series of small steps and resumes itself, so size isn't a problem. Very large sites just take a few more steps.

= Is it safe to leave the page while a backup runs? =
Yes. Manual backups continue while the tab is open; scheduled backups run entirely in the background.

= Can I restore to a different domain or different table prefix? =
The free version restores to the **same** site it was taken from. Cross-site migration (changing the domain or database prefix) is a Pro feature.

= Does restore overwrite my site? =
Yes — that's the point of a restore. Always take a fresh backup first, and ideally test restores on a staging copy before running them on a live site. By default `wp-config.php` is never overwritten.

= Do I need to set up a server cron job? =
No. Scheduling uses WordPress's own cron and self-heals if it ever goes missing.

== Screenshots ==

1. Open it and you know where you stand. One sentence tells you whether your site is covered, when the last backup ran and where it is being kept — no numbers to interpret, no jargon.
2. It walks you through setting up. Three steps to a properly covered site, ticking themselves off as you go, and the panel disappears for good once you are done.
3. Everything the plugin does, as six things you press. Big targets and plain names — "Put my site back", not "Restore" — each showing its own live status.
4. Watch it work, line by line. A live window onto what the server is actually doing: tables dumped, files added, bytes uploaded. Free, not an add-on.
5. When something goes wrong, it tells you what to do. Four things that actually happen — a broken update, a hack, hosting that vanished, something deleted by mistake — each with the exact steps.
6. Google Drive and OneDrive built in and free. One click to connect, every backup gets a second home, and you can pull one straight back down even if the original server is gone.

== Changelog ==

= 1.11.0 =
* **Rewriting the web address is now your choice, not something that just happens to you.** Restoring a site always rewrote every mention of the old address in the database to the new one. That is right almost every time — but not always, and there was no way to say no. Restoring a client's site onto a test install to look at their data, or putting a site back where it came from, both want the database left alone. The Restore window now asks, with the rewrite ticked by default so the common case is still one click.
* Untick it and the database is restored word-for-word as it was dumped, still referring to the site it came from. The log says plainly which of the two happened, so you are never left guessing why links point where they do.
* The site address itself is still always pointed at the install you are restoring onto, whichever way you set that tick. Without it WordPress would redirect every request back to the original site and you would not be able to reach your own copy — that is a lockout, not an option.

= 1.10.8 =
* **The uploader now adjusts itself to your connection.** Piece size used to be worked out from your host's PHP limits alone, which says nothing about the line the file has to travel down — so on a slow uplink a single 16 MB piece could take minutes, and one blip meant sending all of it again. It now measures the speed it is actually getting and sizes each piece to take about forty seconds: large pieces on a fast line, smaller ones on a poor one, never above what your host accepts or below 1 MB.
* Progress now shows megabytes uploaded, the speed you are getting and roughly how long is left, instead of a bare percentage — and a short panel explains that closing the tab pauses the upload, that nothing is lost if it does stop, and that uploading a backup changes nothing on your site by itself. Closing the tab mid-upload now asks first.
* Fixed: a piece could in principle be written to the wrong place in a resumed upload. The browser sends a piece index alongside the byte offset, and that index was derived from the piece size — so once the size changed mid-upload (on a strict server, or now as it adapts) the index no longer meant what the server would read it as, and a later piece could look like the first one and truncate the file. The server prefers the byte offset, so this could not be reached in normal use, but the index is now simply first-piece or not, which is true whatever the size does.

= 1.10.7 =
* **Fixed: an encrypted backup could not be uploaded.** Importing a `.zip.enc` file — the encrypted copy the plugin itself puts in your off-site storage — was refused with "That is not a .zip file". Your own backup was being told it was not a backup. Encrypted backups now upload normally and are unlocked automatically on arrival using this site's passphrase, the same way a cloud restore already did it. Encryption is detected by reading the file, not by its name, so a renamed backup still works.
* Fixed: housekeeping only ran when a backup finished or when off-site storage was in use. A site with off-site switched off never swept its staging folder, so an interrupted restore or an abandoned upload could sit there indefinitely. It is now hooked to the hourly watchdog that runs on every site regardless of settings.
* The Support tab's "More from DadsFam" has been rebuilt: every plugin now has its own card, the ones available on WordPress.org are marked, and the guide sites and hosting are listed properly instead of being left out.

= 1.10.6 =
* **Fixed: the screen did not catch up when a job finished.** A backup finishing is not the end of the work — it hands over to an off-site upload that finishes later still, and nothing was watching for that. So the panel could sit on "your backup is on its way off-site" long after it had safely arrived, until you reloaded the page yourself. It now refreshes on its own the moment nothing is running any more, whether that is a backup, an upload, or a download from the cloud.
* The refresh happens exactly once per job and never on an idle screen, so a dashboard you have left open does not reload itself for no reason.

= 1.10.5 =
* **Fixed: a site whose backups had all gone off-site was told it had none.** If your local copies are deleted once they are safely uploaded — the recommended setup — the dashboard could announce "your site is not backed up yet" and ask you to make your first backup, on a site with dozens of them. The cause: the list of what is in your cloud storage is deliberately cleared the moment an upload succeeds, and an empty list was being read as an empty cloud. It now falls back to the upload log, which is always right, and says "checking" while it re-reads.
* **Fixed: the guided setup would not go away.** Because of the same fault, the first two steps never ticked off, so the "Finish your safety net" panel kept nagging sites that were already fully set up. It now ticks correctly and disappears as it was meant to.
* **Fixed: pressing Back Up Now did not visibly change anything.** The backup started and the console filled up, but the status panel still said what it said before, so the only way to see it change was to reload the page yourself. It now switches to "Backing up your site now" the instant you press it, and puts itself back if the backup fails.
* **The off-site upload progress bar is back.** Uploads showed only in the console; there is now a proper bar with the destination and the byte count again, sitting in the off-site panel.
* Fixed: the tiles were counting only what is on this server, so the same screen could say "32 backups you can restore" at the top and "1 ready to restore" just below it. Fixed: the "Off-site copies" tile could read "On this server", which is the opposite of what it is for.

= 1.10.4 =
* Added screenshots to this plugin's WordPress.org page so you can see what you are installing before you install it.
* Same plugin as 1.10.3 otherwise — no code changed.

= 1.10.3 =
* **The whole plugin has been redesigned around one question: if your site broke right now, would you be all right?** The Dashboard answers it first, in a sentence, in plain English, before a single number — then the detail sits underneath for anyone who wants it.
* The screen no longer reads as white boxes on a white page: a proper masthead with the navigation built into it, cards that sit off the page instead of being outlined onto it, larger type, and colour that always means the same thing — green is safe, amber is worth a look, red needs you.
* **The live activity console is now part of the free plugin.** The window under the progress bar that shows what the server is actually doing, line by line, while a backup runs — it used to sit in the Pro add-on, which meant anybody on the free plugin watching a long backup had only a bar moving and no idea whether it was working or stuck. That was never right. It is core to how this plugin works and it belongs here.
* It now reports more than it used to: the backup being built, a restore being applied, an off-site upload with its real byte count and percentage, a backup being pulled back down from the cloud, and anything still waiting in the upload queue. A small light in its title bar pulses only while something is genuinely running, so one glance tells you whether the machine is busy or you are just looking at history.
* Fixed along the way: the off-site upload line had silently stopped appearing after off-site storage moved into the free plugin in 1.9.0, because it was still reading an option that nothing writes any more. It works again.
* **New: a guided setup that tells you what "finished" looks like.** Three steps — make a backup, keep a copy off the server, put it on autopilot — with a progress bar and one button pointing at whichever you have not done. It ticks itself off as you go and disappears entirely once you are properly covered, so it never nags a site that is already safe.
* **New: the Dashboard is now six large tiles you press**, each showing its own live state with a green or grey dot, instead of six words in a menu bar. Big targets, plain names — "Put my site back" rather than "Restore".
* **New: "If the worst happens" — a plain-English recovery plan built into the plugin.** Four things that actually go wrong, each one telling you exactly what to do about it: a broken update, a hack, hosting that has vanished, something deleted by mistake. Written to be read by somebody in a panic.
* Choosing what to back up is now six large tiles that light up when ticked, readable at arm's length, instead of six small checkboxes.
* Your backups list now shows each backup as its own row card rather than a line in a grid.
* Everything respects your system's reduced-motion setting.
* Fixed: the Dashboard tab ignored your off-site backups completely. If you had connected Google Drive or OneDrive and let the local copies go, the headline figures still read "0 backups stored" with dashes for the last backup and its size, and there was no sign anywhere on that screen of the copies sitting safely in your cloud storage. The off-site engine itself was working the whole time — it was only the Dashboard that never learned to ask. Those three figures now count every backup you have, wherever it is kept.
* Added: a protection line under the figures that tells you in one sentence whether your most recent backup has actually made it off-site, is still queued to go, or is only on this server.
* Added: an "Off-site backups" panel on the Dashboard listing your five most recent backups and where each one is being kept, so you can see at a glance that the copies are really there without opening the Off-site tab.
* Added: a Support tab. Every way to reach a human, the version and environment details worth quoting when you do, and the handful of checks that answer most questions before they get asked.
* Note for Pro users: the off-site figures on the Dashboard used to be drawn by the Pro add-on, which meant they disappeared for everyone else when off-site storage became free in 1.9.0. They are part of this plugin now. Update DadsFam Backups Pro to 1.6.2 alongside this release.

= 1.10.1 =
* Housekeeping for the WordPress.org plugin review. Google Drive and OneDrive came across from the Pro add-on in 1.9.0, and that code had never been through the review checks — it was written for a self-hosted plugin. Every one of its direct network and file calls now carries a plain explanation of why it is there: ranged, resumable transfers and chunked reads of very large archives are the whole reason this plugin finishes where others time out, and neither can be done with the helpers the review normally expects.
* Fixed: the terms and privacy links in the readme pointed at pages that do not exist. They now point at the real privacy policy, which covers both.
* No change to how the plugin behaves. This release is about the paperwork.

= 1.10.0 =
* Added: thirteen more things an AI assistant can do for you through an MCP plugin such as WPVibe — thirty in total now. It can delete a backup you point at, hand you a private download link, scan the server for backups it does not know about yet, tell you how much room your backups take and how much disk is left, read and rebuild your schedule when its cron event goes missing, clear the activity log, send a test notification email, test an off-site destination that has started failing, list what is actually sitting in your cloud storage, show the upload queue, and stop an upload or a cloud download that is running.
* Restoring is still deliberately not something an assistant can trigger. Neither is starting a restore by any other indirect route. That stays a decision you make yourself, on purpose.
* Deleting a backup and clearing the log are both marked as destructive and ask for confirmation first, so an assistant cannot quietly throw away the thing you were relying on.
* Download links handed out this way are private and time-limited, exactly like the ones from the Backups screen.

= 1.9.0 =
* **Off-site backups are now part of the free plugin.** Connect Google Drive or OneDrive on the new Off-site tab and every backup gets a second home automatically. One click to connect — no API keys, no developer setup, no license.
* **Restore straight from the cloud, free.** Lost the server, or let the local copy go to save space? Pick one of your off-site backups and DadsFam pulls it back onto the site for you, then a Restore button appears. Nothing to download to your computer, nothing to re-upload, no filenames to type.
* The restore screen lists your cloud backups as a proper picker rather than a dropdown: the date and time first and large, then where each one is stored, how big it is, whether it is encrypted, and whether it is already on this site. Pick a row and only the questions that actually apply to that backup appear.
* Uploads and downloads run in slices and continue in the background, so a large backup finishes on a slow shared host instead of hitting the PHP time limit — and picks up from the exact byte if the connection drops or you close the tab.
* Fixed: the dashboard widget called a site "not protected" whenever there was no backup on the server — even with recent copies sitting safely off-site, which is exactly the situation deleting the local copy creates. It now counts off-site copies, says plainly when a backup is held off-site rather than here, and reports how many are stored where.
* Added: choose how many backups to keep at each destination, and optionally delete the local copy once a backup is safely off-site.
* Added: six AI abilities covering the new features, so an assistant connected through an MCP plugin such as WPVibe can list your destinations, send a backup off-site, list every restore point, and pull one back down. Restoring is still never exposed to an assistant — that stays a deliberate step you take yourself.
* **If you use DadsFam Backups Pro:** Google Drive and OneDrive have moved here from Pro, and your existing connections are carried across untouched — nothing to reconnect. Pro keeps Amazon S3, FTP, SFTP, encrypted off-site copies and advanced schedules, and needs updating to 1.6.0 to work with this release. Until you update it, this plugin leaves off-site storage to Pro so nothing is ever uploaded twice.

= 1.8.3 =
* Housekeeping release. An older build (1.7.0) was published to WordPress.org by mistake, which would have rolled sites back to code from several releases earlier. This release republishes the current, correct code so everyone lands back on the right version. If you updated and noticed missing features, updating to 1.8.3 restores them.
* No functional changes from 1.8.2 — the code is identical.

= 1.8.2 =
* Added: a plain-English "A word about PRO" note in the readme — what stays free, why the optional add-on exists, and what it does. No features were moved behind a paywall.
* Housekeeping: the readme now lists the current WordPress and PHP versions it is tested against, and the "learn more about Pro" link points at the live plugins site instead of a page that had moved. No code changes.

= 1.8.1 =
* Hardening: admin actions now fall back to WordPress' own admin-ajax address if the plugin's own settings object ever fails to load, so buttons keep working instead of silently doing nothing. No change to what the plugin does day to day.

= 1.8.0 =
* Housekeeping release, prompted by the WordPress.org plugin review. Everything the plugin registers inside WordPress — its settings, its scheduled events, its hooks and its classes — now carries a full-length `dadsfam_backups` name instead of the old short `dfb` one, so it cannot collide with another plugin or theme on your site.
* Your settings, backup index, history, log and schedule are moved across to the new names automatically the first time the updated plugin loads. Nothing is lost, and your actual backup archives are never touched. A backup that happens to be running mid-update carries on.
* Two things change if you drive the plugin from outside the dashboard. The REST routes move from `/dfb/v1/...` to `/dadsfam-backups/v1/...`, and the WP-CLI command changes from `wp dfb ...` to `wp dadsfam-backups ...`. Update any scripts or monitoring you have pointed at the old ones.
* Add-on hooks were renamed to match (for example `dfb_capability` is now `dadsfam_backups_capability`), so DadsFam Backups Pro must be updated to 1.5.0 at the same time. If one is updated without the other, Pro simply stops loading and tells you — nothing breaks.
* Every folder the plugin reads or writes is now resolved in one place through the WordPress functions for the job, which makes the plugin behave correctly on installs with a moved wp-content folder, a custom uploads path, or Windows-style paths.
* Fixed: the Plugin URI in the plugin header pointed at a page that no longer existed.

= 1.7.1 =
* New: the dashboard headline stats (Backups stored / Last backup / Last size) can now be enriched by add-ons via a new `dadsfam_backups_dashboard_stats` filter, so DadsFam Backups Pro can show what is stored off-site alongside what is on this server. On its own the free plugin looks and behaves exactly as before.

= 1.7.0 =
* Added: AI assistant support. If you connect an AI assistant to your site through an MCP plugin such as WPVibe, it can now check whether a backup is running, run the health checks, list and verify your backups, read the history and log, start or cancel a backup, and read or change your schedule and settings — all through the WordPress Abilities API (WordPress 6.9 and newer).
* Security: every AI action requires the same permission the plugin's own screens use, and restoring a backup is deliberately not exposed to assistants — a restore overwrites your live site, so it stays a deliberate action behind the admin screens.
* Note: the AI interface reuses the plugin's existing REST layer, so the same cooldowns, busy-checks and audit logging apply to an assistant exactly as they do to the API.
* On WordPress versions without the Abilities API, nothing changes and the plugin works exactly as before.

= 1.6.9 =
* Fixed: DadsFam Backups PRO was being left out of a restore. Only this plugin needs holding back during a restore, because it is the code doing the work; PRO is a separate plugin and is now copied across like any other, so a restored or cloned site arrives with it in place.

= 1.6.8 =
* Fixed: "Restore stalled — the server may be hitting a memory or time limit" while copying files. The time allowed for each step was only being checked between folders, not between files, so a single folder holding thousands of files (any uploads month, or a large plugin) was worked through in one go. That runs past the server's time limit, the step is killed before its progress can be written down, and the next attempt begins that same folder all over again — so the restore could never get past it. The clock is now checked for every file, and a step that runs out of time stops exactly where it is and carries on from that same file next time.
* Added: if one individual file really is too large to copy within the time a step is allowed, the restore now stops and says what to change, rather than trying it over and over.

= 1.6.7 =
* Fixed: the checks that keep a restored site loading were running before the cache was cleared, so they were reading the site's settings from before the restore. They could therefore leave a genuinely missing plugin switched on, or switch off one that was perfectly fine. The cache is now cleared first.
* Fixed: updating the plugin while a restore was already running could stop that restore with an error. A restore started on an older version now continues safely.
* Fixed: the free disk space a restore asks for was set too high and could turn away a restore that would have completed without trouble. It now asks for what is genuinely needed.
* Fixed: if a file could not be moved into place, the copy no longer removes the existing file first — the file already on your site is left exactly as it was and the problem is reported instead.
* Fixed: the check that spots a file too large to unpack now records each attempt as it happens, so it still works when a request is cut off by the server rather than by PHP.

= 1.6.6 =
* Added: before a restore unpacks anything, it now checks there is enough free disk space for the job. Running out of room partway through is one of the ways a file ends up half-written, and a half-written PHP file takes a site down. If there isn't room the restore refuses to start and says how much is needed, so nothing has been touched.
* Fixed: if a single file in the backup is too large to unpack within the server's time limit, the restore now stops and explains what to change, instead of quietly trying the same file over and over.

= 1.6.5 =
* Fixed: THE cause of restores that finished and then left the site showing a critical error. Unpacking the backup counted a file as done before it had finished writing it, so if that step ran out of time halfway through a file, the next step carried on from the following one - leaving a half-written file behind permanently. A half-written PHP file is a parse error, which takes the whole site down. Files are now only counted once they are completely written and checked, so an interrupted step simply picks the same file up again.
* Fixed: files are now written to one side and moved into place in a single step, both when unpacking and when copying into the site. An interrupted restore can no longer leave a half-written file where a working one used to be.
* Fixed: every unpacked file is now checked against the size recorded in the backup. If anything is short - which nearly always means the server ran out of disk space, or the backup is damaged - the restore stops immediately with a plain explanation, before your site has been touched.
* Fixed: a file that could not be read from the backup, or could not be written, was previously skipped in silence and simply went missing from the restored site. This now stops the restore and says which file and why.
* Added: any file that could not be written during the copy is now listed in the activity log as an error rather than passing unnoticed.

= 1.6.4 =
* Fixed: if a backup did not record which database table prefix it was made with, the restored tables were left under the old prefix - WordPress then could not find its own data and showed the installer, which looks exactly like the site needing to be set up again. The prefix is now read from the backup itself when it isn't recorded, so the data always lands where this site expects it.
* Changed: the notes about files a restore deliberately leaves alone are now summarised in the activity log rather than listed one per file, so the log stays readable on sites with many of them.
* Changed: if a restored site's theme is missing and the standard WordPress theme isn't installed either, the site now falls back to whichever theme is available instead of being left without one.

= 1.6.3 =
* Fixed: a restore could finish and then leave the site showing nothing but a critical error. The cause was files that WordPress runs on every single request being copied in from the backup - a caching drop-in belonging to a plugin or service that is not on this site will bring the site down before it can even load the dashboard, leaving no way in to undo it. Those files are now left alone.
* Fixed: .htaccess and other server configuration files are no longer copied in from a backup. They belong to the server rather than the site, and one from a different host is a common cause of a blank error page. WordPress rebuilds .htaccess from your permalink settings.
* Fixed: the backup plugin no longer replaces its own files while it is in the middle of restoring, which could interrupt a restore part-way through.
* Added: after a restore, anything the restored database expects but that is not actually on the site is now handled instead of being allowed to crash it. Plugins whose files are missing are left switched off, and if the theme is missing the site falls back to a default one. Every one of these is written to the activity log so you can see exactly what happened and put it right.

= 1.6.2 =
* Changed: uploading a backup is now much faster. The plugin reads what your server actually allows and sends the largest pieces it safely can, instead of always sending small ones. On a server set up to allow it this cuts the number of requests dramatically - and since every request has to load the whole of WordPress before it writes anything, that overhead was most of the wait.
* Changed: each piece is now written straight to disk as it arrives rather than being held in memory first, so larger pieces do not increase memory use.
* Added: if a server refuses a piece for being too large (some setups cap this below the PHP settings), the plugin halves the piece size and carries on instead of failing.
* Note: to benefit, your hosting needs upload_max_filesize and post_max_size raised. The plugin adapts automatically either way - it will never send a piece your server cannot accept.

= 1.6.1 =
* Fixed: uploading a backup no longer starts again from zero when the connection drops. The upload is now given a name based on the file itself, so choosing the same file again picks up exactly where it stopped instead of throwing away what was already sent.
* Fixed: a brief connection glitch no longer cancels the whole upload and delete what had been received. The plugin now waits and retries the piece, up to six times, with a growing pause between attempts, and asks the server how much it already holds before carrying on.
* Added: pieces are now placed by position rather than counted in order, so a piece that arrives twice after a dropped connection cannot be written twice or land in the wrong place. The file is checked as a whole before it is imported.
* Added: if an upload is left unfinished, what was already sent is kept for three days so it can be resumed, then tidied away automatically.

= 1.6.0 =
* NEW: **Pick exactly what to restore.** The restore window now shows a checkbox for each part a backup contains — Database, Plugins, Themes, Uploads (media library), Other wp-content, and WordPress core — so you can bring back just what you need (say, only your uploads, or only plugins) instead of all-or-nothing. Leave everything ticked for a full restore or clone (behaviour unchanged); untick parts for a surgical restore. Only the parts a given backup actually contains are shown.

= 1.5.0 =
* NEW: **One-click site cloning.** Restoring a backup taken on another site already rewrote every URL to this install automatically — now the flow makes it obvious and effortless. Import a backup from another site and a big **"Clone onto this site now"** button appears the moment the upload finishes; the restore screen shows exactly which site the backup is a copy of and which address it will be rewritten to, and in the backups list a foreign backup's action is labelled **"Clone here"**. No wp-config edits, no search-and-replace plugins — copying a live site onto a staging/test subdomain is genuinely a couple of clicks.
* NEW: A short, plain-English **"Copying your live site onto this one?"** guide right on the Import panel.
* NEW: **"Scan for backups on the server."** Dropped a backup .zip onto the server another way — cPanel File Manager, FTP, or copied from off-site storage? One click finds it, adds it to your Backups list, and it's ready to restore or clone. The Import panel now also shows the exact folder to drop files into. No more hand-placing files with no way for the plugin to see them.
* IMPROVED: Clearer wording across the restore/clone flow, and a stale code comment corrected — content URLs across all tables (including serialized data and JSON escaped slashes, the bare host and protocol-relative refs) have been rewritten on cross-site restores for some time; the docs now say so.

= 1.4.0 =
* NEW: **Backup history** — a permanent record of every backup this site has ever completed: when, how big, what was in it, its fingerprint, and (with Pro 1.4.0+) exactly which off-site destinations it was uploaded to. Until now, sites that upload off-site and then delete the local copy lost all memory of their own backups — the list emptied as fast as it filled, and "what backups do I have?" could only be answered by logging into your storage bucket. The archive may live in the bucket; the receipt now lives here. Kept for the last 50 backups, written by hooks only (the backup engine itself is untouched).
* NEW: `GET /dadsfam-backups/v1/history` — the history over the REST API, including a `still_local` flag per entry so you can tell at a glance which backups are on this server and which live off-site only.
* IMPROVED: `GET /dadsfam-backups/v1/health` now also answers the two questions that actually catch dying backup schedules: **how old is my newest backup** (`last_backup_age_hours`) and **when is the next one due** (`next_scheduled_date`, checked across both the free and Pro schedulers). A schedule that silently stopped shows up as a large age and no next run — visible in one call instead of discovered during a disaster.
* IMPROVED: backup listings over the API now include `verified_at_creation` — since 1.2.10 the engine opens and structurally checks every archive as it is finished and destroys any that fail, so a completed backup has, as a matter of fact, passed verification; the API now states it.

= 1.3.0 =
* NEW: a REST API, so backups can be driven and — more importantly — **checked** by something other than a human staring at the dashboard. Routes: `GET /dadsfam-backups/v1/health` (can this site even take a backup right now: zip extension, directory writable and protected, free space against the size of your last one), `GET /dadsfam-backups/v1/status` (what the engine is doing, read-only — it never advances the job), `GET /dadsfam-backups/v1/backups` and `/backups/{id}` (what actually exists on disk), `POST /dadsfam-backups/v1/backup` (start one), `POST /dadsfam-backups/v1/backup/cancel`, `POST /dadsfam-backups/v1/verify/{id}` (open the archive, check its structure, match its SHA-256 — the difference between "the plugin said it worked" and "the file has been opened and it is intact"), and `GET /dadsfam-backups/v1/log`. Every route requires a real capability; the default is the same `manage_options` the dashboard uses, and two new filters (`dadsfam_backups_rest_capability_read`, `dadsfam_backups_rest_capability_write`) let you split read-only monitoring from control.
* SECURITY: the API deliberately cannot restore, download, delete, or write settings. Those are the four routes an attacker would actually want — restore flattens the site, download IS the site plus the database, delete destroys your safety net before destroying you, and settings hold your off-site credentials (point them at someone else's bucket and the site exfiltrates itself, nightly). They stay in wp-admin behind a human who had to log in. API responses are built from a field whitelist, so server paths and credentials cannot leak, and a future field cannot leak by accident either.
* The API does not tick the engine. The engine has been single-writer since 1.2.10 and drives itself from the page-view heartbeat and cron; adding an API driver would buy no speed and re-open exactly the concurrency class of bug 1.2.6–1.2.10 closed. Start a backup, then poll status.
* Starts and verifies are rate-limited (30s and 20s), and every API-initiated start, cancel and verify is written to the log with the account that did it — so on a client site you can tell an automated backup from a human one.

= 1.2.10 =
* CRITICAL: closed the last concurrency hole that made backups grow forever on hosts that kill long requests. When a killed slice left the engine lock behind, several waiting requests could all "steal" it in the same second — the takeover wasn't atomic — and the resulting concurrent slices archived the same files twice, over and over (visible as the file count climbing past the real total and duplicate log lines). The takeover is now an atomic insert exactly one request can win; a RUNNING slice keeps the lock alive every 10 seconds so it can never be mistaken for dead regardless of how long its zip work takes; each slice's work budget is clamped safely under the host's kill wall so leaks stop happening in the first place; and the engine can no longer be driven from AJAX polling requests at all. Backups now have exactly one writer, always, on any host.

= 1.2.9 =
* The finalise fingerprint can now NEVER wedge a backup, on any host. Three guarantees: (1) the SHA-256 checkpoints its position and state every 32 MB WITHIN a call, so a host kill loses at most 32 MB of hashing instead of the whole call; (2) every call is capped by both time and bytes, so calls stay short enough to survive even brutal request limits; (3) a stall-breaker — if three consecutive calls make zero forward progress, the fingerprint is skipped with a clear warning and the backup COMPLETES anyway (verified and fully restorable; only the optional integrity fingerprint is unavailable). A finished backup always beats a perfect hash.

= 1.2.8 =
* The backup no longer swallows OTHER WordPress sites nested inside this site's folder. On cPanel, a subdomain or addon domain's document root often lives inside the main site's directory; the file scanner descended into it and archived that entire second website too — inflating the backup by thousands of files and hundreds of MB, and dragging in that site's unreadable files as warnings. The scanner now detects a nested WordPress installation (its own wp-load.php / wp-settings.php / wp-config.php) and skips it with a clear log line — each site backs itself up with its own copy of the plugin. Note: "a file could not be read and was skipped" warnings are the backup working correctly on permission-blocked files; the backup continues.

= 1.2.7 =
* CRITICAL: fixed backups growing forever ("Archiving files… N / N" climbing past the real file count, archive size ballooning). 1.2.6's page-view heartbeat could run a work slice at the same moment as the dashboard's own slice — the engine's stages assume a single writer, so two concurrent slices archived the same files twice into one zip, over and over. All drivers (dashboard poller, page-view heartbeat, cron) now pass through one atomic engine mutex: only one work slice can ever run at a time, anyone else just reports status, and a mutex left behind by a host-killed request self-heals in 90 seconds. Cancel clears it too. Proven by tests that a heartbeat firing mid-slice can no longer advance the job, and that page views alone still drive a stalled backup to completion with a byte-correct fingerprint.

= 1.2.6 =
* Backups no longer depend on keeping the dashboard tab open and in the foreground. The engine's work steps were only ever driven by the dashboard's polling — switch to another tab, let the browser throttle a background tab (Brave and Chrome both do), close the laptop, or navigate to another admin page, and a running backup silently froze mid-stage forever. A page-view heartbeat now notices a backup that hasn't moved for 20 seconds and advances it on the shutdown of ANY request to the site — a reader opening an article is enough — after detaching so the visitor feels nothing. An atomic lock guarantees two page views can never run the engine twice at once, and a lock left behind by a host-killed request self-heals in 90 seconds. Verified by tests where page views alone drive a stalled backup all the way to completion with a byte-correct fingerprint.

= 1.2.5 =
* Fixed large backups genuinely getting stuck at "Finalising archive — fingerprinting (SHA-256)…". The whole finalise stage (fold the database in, verify, fingerprint) ran inside one request; on hosts that hard-kill long requests, a big archive made that request die mid-fingerprint and the next tick silently started the stage over — an invisible repeat-forever loop frozen on the same message. The finalise now runs as small persisted sub-steps that each execute exactly once, and the SHA-256 fingerprint itself is chunked and resumes across requests (with a live percentage in the progress message), so a killed request costs seconds instead of trapping the backup.

= 1.2.4 =
* The final stage of a large backup no longer looks frozen. After "Archiving files… N / N" the engine does several heavy steps that used to run silently — folding the database into the archive, verifying integrity, and SHA-256 fingerprinting the finished file (which alone can take a minute on a multi-GB backup). The progress bar now narrates each of these steps live instead of appearing hung at the file count.

= 1.2.3 =
* Added an extension point to the "backup completed" email so an add-on can replace the download button with an informational note. Pairs with DadsFam Backups Pro 1.3.5, which uses it so that when you have Pro's "delete local copy after off-site upload" option on, the email no longer shows a download link that would stop working once the local file is removed — it tells you the backup is stored off-site instead. No change in behaviour when used on its own.

= 1.2.2 =
* Added a new dashboard extension point directly beneath the "Create a backup" card, so the Pro add-on's off-site upload panel and progress bar now appear right under the backup you just made (previously it sat above the stats). Pairs with DadsFam Backups Pro 1.2.2.

= 1.2.1 =
* FIXED — the archiving progress could read past 100% on busy sites (e.g. "Archiving files… 26,137 / 17,296 files") when files were added or changed while the backup ran. The counter now shows a sensible total and the final tally matches what was actually archived.

= 1.2.0 =
* The dashboard's "Next scheduled" stat and the WordPress dashboard widget are now Pro-aware: when DadsFam Backups Pro's advanced schedule is running the show, they display the Pro schedule's next run (with a note explaining the free schedule is off on purpose) instead of a confusing "Off".
* New extension points for the Pro add-on: a dashboard area after the quick stats (Pro's new Off-site backups panel renders there), a filterable schedule stat, and extra status lines in the WordPress dashboard widget (Pro reports last off-site upload and any pending uploads).

= 1.1.0 =
* New: backup verification. Every new backup records a SHA-256 fingerprint of the finished file, and a Verify button on each backup checks the file exists, the archive structure is consistent, the manifest is present, and the fingerprint still matches — so you know a backup is genuinely restorable before you need it. Failed and passed verifications are written to the activity log. Older backups (made before this version) are still checked structurally.
* New: WP-CLI commands for people who manage sites from the server: `wp dfb backup` runs a full backup with live progress (ideal for real server cron, which is more dependable than visit-based WP-Cron), `wp dfb list` shows stored backups, and `wp dfb verify <id>` runs the integrity check.
* New: a "Send test email" button under Settings → Email notifications, so you can confirm delivery and see the email design without waiting for a backup to run.
* New: a DadsFam Backups widget on the WordPress dashboard — colour-coded backup health at a glance, last backup age/size, how many backups are stored, and when the next scheduled backup runs.

= 1.0.15 =
* New: the activity log now tracks download activity so you can keep an eye on your backups. It records when a secure email download link is created (and when it will expire), when a backup is downloaded through that link (including whether the person was logged in and their IP address), when a backup is downloaded from the dashboard (and by which user), when someone tries a link that has already expired or been used, and when a one-time link is used up. These appear right in Logs with colour-coded badges.

= 1.0.14 =
* Fixed: the secure download link in backup emails could say "expired or no longer valid" on the very first click. Some email apps quietly rewrite links and dropped part of the web address, so the link arrived incomplete. It is now a simpler single-piece web address that email apps leave intact, so it works on the first click. Links in older emails still work too.

= 1.0.13 =
* New: backup emails are now a clean, mobile-friendly HTML design instead of plain text — branded header, an at-a-glance summary of what was backed up, and a clear button.
* New: success emails can include a secure one-click download link straight to the backup file. No login is needed, it streams large backups reliably (with resume support for dropped connections), and it expires automatically after a set time — 24 hours by default — whether it was used or not. An optional one-time mode is available.
* The download link is protected by a random token (only a hash is stored on your server), and you can change the lifetime, switch on one-time mode, or turn the link off entirely under Settings → Email notifications.

= 1.0.12 =
* Fixed: emoji and other 4-byte characters (e.g. 🎉 and some Asian-language text) could be turned into "?" when restoring a backup. The backup now records the correct character set and the restore enforces it, so your content comes back exactly as it was. Verified character-for-character on a real WordPress restore.
* Fixed: after restoring a backup, a leftover "backup in progress" flag from the moment the backup was taken could block you from starting new backups. Restores now clear that flag, so a backup runs immediately afterwards.
* Added: if a backup ever stops unexpectedly (for example a server timeout), it is now detected and cleared automatically instead of blocking future backups.

= 1.0.11 =
* Migration URL rewrite is now bullet-proof. In addition to the full site address, the restore now also rewrites the bare domain (e.g. http://oldsite.com/...) and protocol-relative links, processed in the correct order so the most specific paths win. This fixes sites that live in a subdirectory and any content that hard-codes the domain, so a migrated site no longer keeps pointing assets at the old address. Verified with a real WordPress-to-WordPress migration across different table prefixes and URLs.

= 1.0.10 =
* Migration clarity. After a restore, the log now reports exactly what happened and flags anything that would break a migrated site: the URL change applied, whether the active theme (and parent theme) files are present, any active plugins whose files are missing, and a PHP version gap between the source and this server. The restore dialog also makes clear that copying a whole site needs BOTH database and files ticked.

= 1.0.9 =
* Backup integrity & completeness pass. Every finished backup is now verified before it's marked successful — the archive must open and contain the database and metadata, or the backup fails clearly instead of leaving you with a bad file. Any file that can't be read at archive time is now logged and counted (no more silent gaps), the completion log shows the exact file count, and a failed archive write (e.g. disk full) stops the backup with a clear message. Confirms a backup truly captured everything: database, plugins, themes, uploads and the rest of wp-content.

= 1.0.8 =
* Fixed "Could not open the file manifest for writing" after a file restore. The backup engine now recreates and verifies its working folder before every write (and retries if a restore removed or replaced it), and a restore no longer overwrites this site's own backup folder. Backups are reliable immediately after a restore.

= 1.0.7 =
* Restore reliability overhaul. Fixed a bug where a restore step running out of time mid-statement could drop part of the database (the cause of incomplete restores). The restore engine now resumes only from completed statements, frees memory between statements, logs any skipped statements, saves progress mid-step, and — like the backup engine — survives server memory/time limits by resuming automatically or stopping with a clear message instead of hanging. Restoring now completes fully and predictably.

= 1.0.6 =
* Complete migration: restoring a backup from another site now also rewrites every site URL throughout the database (posts, options, widgets, theme settings) in a serialization-safe way, so the restored staging copy is fully localized — images, links and settings all point to this site. Combined with automatic prefix remapping and role preservation, a cross-site restore is now a true, complete migration.

= 1.0.5 =
* Restore now works across sites and different table prefixes — free, no restrictions. When you restore a backup from another site, the table prefix is remapped automatically, user roles/capabilities are preserved, and the site URLs are reset to this install so it loads here. Ideal for copying a live site onto a staging site to work on.

= 1.0.4 =
* New: Import a backup. Upload a DadsFam backup .zip (even a large one, or one from another site) on the Backups tab and it is added to your library, ready to restore. Uploads are sent in small pieces so your host's upload size limits don't get in the way. Imported backups are validated and shown with an "Imported" badge.

= 1.0.3 =
* Hardened the backup engine so it can never silently hang. A backup that hits a server memory or time limit now either resumes automatically (if it was making progress) or stops with a clear, actionable message instead of freezing. The database dump is now crash-safe (partial writes are trimmed and progress is saved mid-step so it resumes cleanly), unreadable tables are logged and skipped, and the screen no longer spins forever if the server keeps refusing a step. Default DB batch lowered for safety.

= 1.0.2 =
* Activity log now labels each entry as a Scheduled or Manual backup, so you can confirm at a glance which runs were automatic.

= 1.0.1 =
* Added clean extension points so the Pro add-on plugs straight into this plugin's own menu and tabs — one unified interface, no extra menu.

= 1.0.0 =
* Initial release: resumable full backups (database + files), one-click same-site restore, scheduling with retention, exclusions, email notifications, activity log, and a secure backup store.

== Upgrade Notice ==

= 1.11.0 =
Restoring now lets you choose whether to rewrite the old site's web address in the database. It stays ticked by default, so restores and clones behave exactly as before unless you say otherwise.

= 1.10.8 =
Makes the uploader adapt its piece size to your connection, shows speed and time remaining while it runs, and hardens resumed uploads against a piece landing in the wrong place.

= 1.10.7 =
Important if you use encrypted off-site backups. Uploading a .zip.enc file was refused outright — it now imports and unlocks automatically. Also fixes housekeeping never running on sites with off-site storage switched off.

= 1.10.6 =
The dashboard now catches up on its own when a backup and its off-site upload have finished, instead of waiting for you to reload the page. Recommended for everyone on 1.10.5.

= 1.10.5 =
Important if you send backups off-site. Fixes the dashboard telling you your site was not backed up when in fact everything was safely in your cloud storage, brings back the upload progress bar, and makes Back Up Now visibly do something without a page reload.

= 1.10.4 =
Screenshots on the plugin page. No code changed since 1.10.3 — nothing to do if you are already on it.

= 1.10.3 =
The live activity console is now part of the free plugin, where it always belonged. Plus a rebuilt Dashboard: a guided three-step setup, big pressable tiles, a plain-English recovery plan for when things go wrong, and one sentence telling you whether your site is safe. Also fixes it ignoring your off-site backups — it read "0 backups stored" even with copies safely in Google Drive or OneDrive. The figures now count everything you have, wherever it is kept, and a new panel shows where each backup lives. Adds a Support tab. Pro users should update to 1.6.2 as well.

= 1.10.1 =
Paperwork only — nothing behaves differently. Documents why the off-site code needs direct network and file access, and fixes two dead links in the readme.

= 1.10.0 =
Adds thirteen more AI abilities, so an assistant connected through an MCP plugin can handle almost the whole plugin for you — schedules, storage, off-site destinations, download links and housekeeping. Restoring is still yours alone, and the destructive actions confirm first.

= 1.9.0 =
Off-site backups are now free: connect Google Drive or OneDrive in one click, and pull a backup back down from the cloud when you need it. Pro users — your existing Drive and OneDrive connections carry across untouched; update Pro to 1.6.0 alongside this.

= 1.8.3 =
Please update. An older build (1.7.0) was published by mistake and would roll your site back several releases. 1.8.3 is the current, correct code — updating puts you back on the right version. Your backups and settings are unaffected.

= 1.7.0 =
Adds AI assistant support via the WordPress Abilities API (WP 6.9+): connect Claude or ChatGPT through an MCP plugin like WPVibe to check status and health, list and verify backups, start one, and manage the schedule. Admin-only, and restore is not exposed to assistants. Backups themselves are unchanged.

= 1.2.10 =
CRITICAL: fixes backups duplicating files and growing forever on strict hosts. Update immediately, force-stop any running backup, then back up fresh.

= 1.2.9 =
Final hardening: fingerprinting can no longer stall a backup under any circumstances — worst case it is skipped and the backup completes. Strongly recommended.

= 1.2.8 =
Stops the backup archiving entire nested subdomain/addon-domain WordPress sites inside this site's folder. Backups return to their normal size and speed.

= 1.2.7 =
CRITICAL fix over 1.2.6: stops backups double-archiving and growing forever. Update immediately, force-stop any running backup, then back up fresh.

= 1.2.6 =
Important: backups now keep running even with the dashboard closed or the browser tab in the background — any site traffic advances them automatically.

= 1.2.5 =
Fixes big backups getting stuck forever at the fingerprinting step on hosts with strict request limits — the finalise is now fully resumable with live progress.

= 1.2.4 =
Large backups no longer look frozen at the end — the finalise steps (database fold-in, verify, fingerprint) now report live progress.

= 1.2.3 =
Improves the completion email so Pro can hide a download link that would break when the local copy is auto-deleted after off-site upload. Pairs with Pro 1.3.5.

= 1.2.2 =
Moves the Pro off-site upload panel/progress bar to sit directly under the backup card. Install alongside DadsFam Backups Pro 1.2.2.

= 1.2.1 =
Fixes the file-archiving counter showing more than 100% on active sites. Cosmetic but recommended.

= 1.2.0 =
The dashboard now shows the Pro advanced schedule correctly (no more misleading "Off") and hosts the new Pro Off-site backups panel. Install together with DadsFam Backups Pro 1.1.0 if you run Pro.

= 1.1.0 =
Feature release: backup verification with checksums, WP-CLI commands (wp dfb backup / list / verify), a send-test-email button, and a dashboard health widget. Recommended for all sites.

= 1.0.15 =
New: your activity log now records download activity — who downloaded a backup, whether via the email link or the dashboard, and when links are used or expire.

= 1.0.14 =
Fixes backup-email download links that could show "expired" on the first click. Recommended if you use the email download link.

= 1.0.13 =
New: polished HTML backup emails with an optional secure download link that expires automatically (24 hours by default). Set it up under Settings → Email notifications.

= 1.0.12 =
Important fix for sites that use emoji or non-Latin text: restores now preserve those characters exactly. Also fixes a leftover flag that could block backups after a restore. Recommended for everyone.

= 1.0.0 =
First release of DadsFam Backups.
