Version Description
- not yet released/supported =
- FEATURE: Now restores databases (we recommend the MySQL command-line for versions created with previous versions of UpdraftPlus)
- FEATURE: Rackspace Cloud Files support (http://www.rackspace.com/cloud/files/)
- FEATURE: Built-in multi-uploader, allowing easier restoration of old backup sets
- FEATURE: Allow instant downloading of the most recently modified log file
- FEATURE: Built in drag-and-drop database decrypter for manual decryption
- FEATURE: Deutsch / German translation: thanks to Marcel Herrguth - mherrguth@mrgeneration.de
- FEATURE: Magyar / Hungarian translation: thanks to Szpe Viktor - http://www.szepe.net
- FEATURE: Spanish / Espaol translation: thanks to Fernando Villasmil - villasmil.fernando@gmail.com
- FEATURE: Added encryption (used by default) to Amazon S3 communications
- RELIABILITY: Various algorithm tweaks to help larger sites on lower resources. Largest site a known user has: 1.5Gb
- RELIABILITY/FEATURE: Ship up-to-date SSL certificates, and added expert options to prefer server SSL CA certificates, and to disable peer verification
- SPEED: Batch INSERT commands in database backups, for much faster restoration (typically 95% faster)
- SPEED/RELIABILITY: FTP and FTPS (not SFTP) are now chunked and resumable (both download and upload), subject to your FTP server responding correctly to SIZE
- SPEED: Re-factoring of admin-area and some backup code into separate lazy-loaded files, to reduce memory consumption on sites generally
- FIX: Clear PHP's file stat cache when checking for zip file activity - fixes potential halt on very enormous sites or sites with very low PHP timeouts.
- FIX: Caught some untranslated strings
- FIX: Respect WordPress's WP_MAX_MEMORY_LIMIT constant
- FIX: Remove timezone display from local time - WordPress's get_date_from_gmt function does not completely do what the manual says it does
- FIX: A small typo slipped into 1.5.5 which prevented some Google Drive users from setting up new installations
- TWEAK: In fix-time add-on, fade UI when relevant
- TWEAK: Improved UI of downloader
- TWEAK: Decrease FTP timeouts to improve our chances of getting back an error before PHP aborts
- TWEAK: Tweaked al relevant methods to follow the general SSL CA certificate options
Download this release
Release Info
Developer | DavidAnderson |
Plugin | UpdraftPlus WordPress Backup Plugin |
Version | 1.5.20 |
Comparing to | |
See all releases |
Code changes from version 1.5.5 to 1.5.20
- admin.php +1765 -0
- backup.php +314 -0
- example-decrypt.php +4 -6
- images/rackspacecloud-logo.png +0 -0
- includes/Dropbox/OAuth/Consumer/Curl.php +8 -2
- includes/S3.php +1 -1
- includes/ajax.js +0 -0
- includes/{Dropbox/OAuth/Consumer/ca-bundle.pem → cacert.pem} +2 -27
- includes/cloudfiles/cloudfiles.php +2629 -0
- includes/cloudfiles/cloudfiles_exceptions.php +41 -0
- includes/cloudfiles/cloudfiles_http.php +1582 -0
- includes/ftp.class.php +106 -57
- includes/ud-plupload.js +168 -0
- includes/updraft-restorer.php +259 -41
- languages/updraftplus-de_DE.po +3 -6
- languages/updraftplus-es_ES.mo +0 -0
- languages/updraftplus-es_ES.po +1914 -0
- languages/updraftplus-hu_HU.po +2 -4
- languages/updraftplus.pot +879 -560
- methods/cloudfiles.php +483 -0
- methods/dropbox.php +3 -10
- methods/ftp.php +43 -19
- methods/googledrive.php +7 -1
- methods/s3.php +69 -17
- methods/sftp.php +4 -4
- methods/template.php +2 -2
- methods/webdav.php +1 -1
- options.php +30 -10
- readme.txt +43 -14
- updraftplus.php +294 -1705
admin.php
ADDED
@@ -0,0 +1,1765 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (!defined ('ABSPATH')) die ('No direct access allowed');
|
4 |
+
|
5 |
+
// For the purposes of improving site performance (don't load in 10s of Kilobytes of un-needed code on every page load), admin-area code is being progressively moved here.
|
6 |
+
|
7 |
+
// This gets called in admin_init, earlier than default (so our object can get used by those hooking admin_init). Or possibly in admin_menu.
|
8 |
+
|
9 |
+
global $updraftplus_admin;
|
10 |
+
if (empty($updraftplus_admin)) $updraftplus_admin = new UpdraftPlus_Admin();
|
11 |
+
|
12 |
+
class UpdraftPlus_Admin {
|
13 |
+
|
14 |
+
function __construct() {
|
15 |
+
|
16 |
+
$this->admin_init();
|
17 |
+
|
18 |
+
}
|
19 |
+
|
20 |
+
function admin_init() {
|
21 |
+
|
22 |
+
add_action('admin_head', array($this,'admin_head'));
|
23 |
+
add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
|
24 |
+
add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
|
25 |
+
add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
|
26 |
+
add_action('wp_ajax_plupload_action', array($this,'plupload_action'));
|
27 |
+
add_action('wp_ajax_plupload_action2', array($this,'plupload_action2'));
|
28 |
+
|
29 |
+
global $updraftplus, $wp_version, $pagenow;
|
30 |
+
|
31 |
+
// First, the checks that are on all (admin) pages:
|
32 |
+
|
33 |
+
if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "googledrive" && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid','') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token','') == '') {
|
34 |
+
add_action('admin_notices', array($this,'show_admin_warning_googledrive') );
|
35 |
+
}
|
36 |
+
|
37 |
+
if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "dropbox" && UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token','') == '') {
|
38 |
+
add_action('admin_notices', array($this,'show_admin_warning_dropbox') );
|
39 |
+
}
|
40 |
+
|
41 |
+
if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1024*1024*35) === false) add_action('admin_notices', array($this, 'show_admin_warning_diskspace'));
|
42 |
+
|
43 |
+
// Next, the actions that only come on the UpdraftPlus page
|
44 |
+
if ($pagenow != 'options-general.php' || !isset($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
|
45 |
+
|
46 |
+
if(UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
|
47 |
+
@ini_set('display_errors',1);
|
48 |
+
@error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
|
49 |
+
}
|
50 |
+
|
51 |
+
// LiteSpeed has a generic problem with terminating cron jobs
|
52 |
+
if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false) {
|
53 |
+
if (!is_file(ABSPATH.'.htaccess') || !preg_match('/noabort/i', file_get_contents(ABSPATH.'.htaccess'))) {
|
54 |
+
add_action('admin_notices', array($this, 'show_admin_warning_litespeed'));
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
if (version_compare($wp_version, '3.2', '<')) add_action('admin_notices', array($this, 'show_admin_warning_wordpressversion'));
|
59 |
+
|
60 |
+
wp_enqueue_script('jquery');
|
61 |
+
wp_enqueue_script('jquery-ui-dialog');
|
62 |
+
wp_enqueue_script('plupload-all');
|
63 |
+
wp_register_script('updraftplus-plupload', UPDRAFTPLUS_URL.'/includes/ud-plupload.js', array('jquery'));
|
64 |
+
wp_enqueue_script('updraftplus-plupload');
|
65 |
+
|
66 |
+
}
|
67 |
+
|
68 |
+
function admin_head() {
|
69 |
+
|
70 |
+
global $pagenow;
|
71 |
+
if ($pagenow != 'options-general.php' || !isset($_REQUEST['page']) && 'updraftplus' != $_REQUEST['page']) return;
|
72 |
+
|
73 |
+
$chunk_size = min(wp_max_upload_size()-1024, 1024*1024*2);
|
74 |
+
|
75 |
+
$plupload_init = array(
|
76 |
+
'runtimes' => 'html5,silverlight,flash,html4',
|
77 |
+
'browse_button' => 'plupload-browse-button',
|
78 |
+
'container' => 'plupload-upload-ui',
|
79 |
+
'drop_element' => 'drag-drop-area',
|
80 |
+
'file_data_name' => 'async-upload',
|
81 |
+
'multiple_queues' => true,
|
82 |
+
'max_file_size' => '100Gb',
|
83 |
+
'chunk_size' => $chunk_size.'b',
|
84 |
+
'url' => admin_url('admin-ajax.php'),
|
85 |
+
'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
|
86 |
+
'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
|
87 |
+
'filters' => array(array('title' => __('Allowed Files'), 'extensions' => 'zip,gz,crypt')),
|
88 |
+
'multipart' => true,
|
89 |
+
'multi_selection' => true,
|
90 |
+
'urlstream_upload' => true,
|
91 |
+
// additional post data to send to our ajax hook
|
92 |
+
'multipart_params' => array(
|
93 |
+
'_ajax_nonce' => wp_create_nonce('updraft-uploader'),
|
94 |
+
'action' => 'plupload_action'
|
95 |
+
)
|
96 |
+
);
|
97 |
+
|
98 |
+
?><script type="text/javascript">var updraft_plupload_config=<?php echo json_encode($plupload_init); ?>;</script>
|
99 |
+
<?php
|
100 |
+
$plupload_init['browse_button'] = 'plupload-browse-button2';
|
101 |
+
$plupload_init['container'] = 'plupload-upload-ui2';
|
102 |
+
$plupload_init['drop_element'] = 'drag-drop-area2';
|
103 |
+
$plupload_init['multipart_params']['action'] = 'plupload_action2';
|
104 |
+
$plupload_init['filters'] = array(array('title' => __('Allowed Files'), 'extensions' => 'crypt'));
|
105 |
+
?><script type="text/javascript">var updraft_plupload_config2=<?php echo json_encode($plupload_init); ?>;
|
106 |
+
var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
|
107 |
+
</script>
|
108 |
+
<style type="text/css">
|
109 |
+
.drag-drop #drag-drop-area2 {
|
110 |
+
border: 4px dashed #ddd;
|
111 |
+
height: 200px;
|
112 |
+
}
|
113 |
+
#drag-drop-area2 .drag-drop-inside {
|
114 |
+
margin: 36px auto 0;
|
115 |
+
width: 350px;
|
116 |
+
}
|
117 |
+
#filelist, #filelist2 {
|
118 |
+
width: 100%;
|
119 |
+
}
|
120 |
+
#filelist .file, #filelist2 .file, #ud_downloadstatus .file {
|
121 |
+
padding: 5px;
|
122 |
+
background: #ececec;
|
123 |
+
border: solid 1px #ccc;
|
124 |
+
margin: 4px 0;
|
125 |
+
}
|
126 |
+
#filelist .fileprogress, #filelist2 .fileprogress, #ud_downloadstatus .dlfileprogress {
|
127 |
+
width: 0%;
|
128 |
+
background: #f6a828;
|
129 |
+
height: 5px;
|
130 |
+
}
|
131 |
+
#ud_downloadstatus .raw {
|
132 |
+
margin-top: 8px;
|
133 |
+
clear:left;
|
134 |
+
}
|
135 |
+
#ud_downloadstatus .file {
|
136 |
+
margin-top: 8px;
|
137 |
+
}
|
138 |
+
</style>
|
139 |
+
<?php
|
140 |
+
|
141 |
+
}
|
142 |
+
|
143 |
+
function disk_space_check($space) {
|
144 |
+
global $updraftplus;
|
145 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
146 |
+
$disk_free_space = @disk_free_space($updraft_dir);
|
147 |
+
if ($disk_free_space == false) return -1;
|
148 |
+
return ($disk_free_space > $space) ? true : false;
|
149 |
+
}
|
150 |
+
|
151 |
+
# Adds the settings link under the plugin on the plugin screen.
|
152 |
+
function plugin_action_links($links, $file) {
|
153 |
+
if ($file == 'updraftplus/updraftplus.php'){
|
154 |
+
$settings_link = '<a href="'.site_url().'/wp-admin/options-general.php?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
|
155 |
+
array_unshift($links, $settings_link);
|
156 |
+
// $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
|
157 |
+
// array_unshift($links, $settings_link);
|
158 |
+
$settings_link = '<a href="http://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
|
159 |
+
array_unshift($links, $settings_link);
|
160 |
+
}
|
161 |
+
return $links;
|
162 |
+
}
|
163 |
+
|
164 |
+
|
165 |
+
function show_admin_warning($message, $class = "updated") {
|
166 |
+
echo '<div id="updraftmessage" class="'.$class.' fade">'."<p>$message</p></div>";
|
167 |
+
}
|
168 |
+
|
169 |
+
function show_admin_warning_diskspace() {
|
170 |
+
$this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue.','updraftplus'),'35 Mb'));
|
171 |
+
}
|
172 |
+
|
173 |
+
function show_admin_warning_wordpressversion() {
|
174 |
+
$this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress.'),'3.2'),'updraftplus');
|
175 |
+
}
|
176 |
+
|
177 |
+
function show_admin_warning_litespeed() {
|
178 |
+
$this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('Your website is hosted using the %s web server.','updraftplus'),'LiteSpeed').' <a href="http://updraftplus.com/faqs/i-am-having-trouble-backing-up-and-my-web-hosting-company-uses-the-litespeed-webserver/">'.__('Please consult this FAQ if you have problems backing up.', 'updraftplus').'</a>');
|
179 |
+
}
|
180 |
+
|
181 |
+
function show_admin_warning_dropbox() {
|
182 |
+
$this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus')/':</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-dropbox-auth&updraftplus_dropboxauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Dropbox','Dropbox').'</a>');
|
183 |
+
}
|
184 |
+
|
185 |
+
function show_admin_warning_googledrive() {
|
186 |
+
$this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-googledrive-auth&updraftplus_googleauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Google Drive','Google Drive').'</a>');
|
187 |
+
}
|
188 |
+
|
189 |
+
// This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
|
190 |
+
function prune_updraft_dir_prefix($updraft_dir) {
|
191 |
+
if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
|
192 |
+
if (strpos($updraft_dir, ABSPATH) === 0) {
|
193 |
+
$updraft_dir = substr($updraft_dir, strlen(ABSPATH));
|
194 |
+
}
|
195 |
+
}
|
196 |
+
return $updraft_dir;
|
197 |
+
}
|
198 |
+
|
199 |
+
function updraft_download_backup() {
|
200 |
+
|
201 |
+
@set_time_limit(900);
|
202 |
+
|
203 |
+
global $updraftplus;
|
204 |
+
|
205 |
+
if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
|
206 |
+
|
207 |
+
if (!isset($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || !isset($_REQUEST['type'])) exit;
|
208 |
+
|
209 |
+
$backupable_entities = $updraftplus->get_backupable_file_entities(true);
|
210 |
+
$type_match = false;
|
211 |
+
foreach ($backupable_entities as $type => $info) {
|
212 |
+
if ($_REQUEST['type'] == $type) $type_match = true;
|
213 |
+
}
|
214 |
+
|
215 |
+
if (!$type_match && $_REQUEST['type'] != 'db') exit;
|
216 |
+
|
217 |
+
// Get the information on what is wanted
|
218 |
+
$type = $_REQUEST['type'];
|
219 |
+
$timestamp = $_REQUEST['timestamp'];
|
220 |
+
|
221 |
+
// You need a nonce before you can set job data. And we certainly don't yet have one.
|
222 |
+
$updraftplus->backup_time_nonce();
|
223 |
+
|
224 |
+
$debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
|
225 |
+
|
226 |
+
// Set the job type before logging, as there can be different logging destinations
|
227 |
+
$updraftplus->jobdata_set('job_type', 'download');
|
228 |
+
|
229 |
+
// Retrieve the information from our backup history
|
230 |
+
$backup_history = $updraftplus->get_backup_history();
|
231 |
+
// Base name
|
232 |
+
$file = $backup_history[$timestamp][$type];
|
233 |
+
|
234 |
+
// Where it should end up being downloaded to
|
235 |
+
$fullpath = $updraftplus->backups_dir_location().'/'.$file;
|
236 |
+
|
237 |
+
if (isset($_GET['stage']) && '2' == $_GET['stage']) {
|
238 |
+
$updraftplus->spool_file($type, $fullpath);
|
239 |
+
die;
|
240 |
+
}
|
241 |
+
|
242 |
+
if (isset($_POST['stage']) && 'delete' == $_POST['stage']) {
|
243 |
+
@unlink($fullpath);
|
244 |
+
echo 'deleted';
|
245 |
+
$updraftplus->log('The file has been deleted');
|
246 |
+
die;
|
247 |
+
}
|
248 |
+
|
249 |
+
// TODO: FIXME: Failed downloads may leave log files forever (though they are small)
|
250 |
+
// Note that log() assumes that the data is in _POST, not _GET
|
251 |
+
if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
|
252 |
+
|
253 |
+
$updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type");
|
254 |
+
|
255 |
+
$known_size = isset($backup_history[$timestamp][$type.'-size']) ? $backup_history[$timestamp][$type.'-size'] : 0;
|
256 |
+
|
257 |
+
$service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
|
258 |
+
$updraftplus->jobdata_set('service', $service);
|
259 |
+
|
260 |
+
// Fetch it from the cloud, if we have not already got it
|
261 |
+
|
262 |
+
$needs_downloading = false;
|
263 |
+
|
264 |
+
if(!file_exists($fullpath)) {
|
265 |
+
//if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
|
266 |
+
$needs_downloading = true;
|
267 |
+
$updraftplus->log('File does not yet exist locally - needs downloading');
|
268 |
+
} elseif ($known_size>0 && filesize($fullpath) < $known_size) {
|
269 |
+
$updraftplus->log("The file was found locally (".filesize($fullpath).") but did not match the size in the backup history ($known_size) - will resume downloading");
|
270 |
+
$needs_downloading = true;
|
271 |
+
} elseif ($known_size>0) {
|
272 |
+
$updraftplus->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' Kb)');
|
273 |
+
} else {
|
274 |
+
$updraftplus->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
|
275 |
+
$known_size = filesize($fullpath);
|
276 |
+
}
|
277 |
+
|
278 |
+
// The AJAX responder that updates on progress wants to see this
|
279 |
+
set_transient('ud_dlfile_'.$timestamp.'_'.$type, "downloading:$known_size:$fullpath", 3600);
|
280 |
+
|
281 |
+
if ($needs_downloading) {
|
282 |
+
// Close browser connection so that it can resume AJAX polling
|
283 |
+
header('Content-Length: 0');
|
284 |
+
header('Connection: close');
|
285 |
+
header('Content-Encoding: none');
|
286 |
+
if (session_id()) session_write_close();
|
287 |
+
echo "\r\n\r\n";
|
288 |
+
$this->download_file($file, $service);
|
289 |
+
if (is_readable($fullpath)) {
|
290 |
+
clearstatcache();
|
291 |
+
$updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
|
292 |
+
} else {
|
293 |
+
$updraftplus->log('Remote fetch failed');
|
294 |
+
}
|
295 |
+
}
|
296 |
+
|
297 |
+
// Now, spool the thing to the browser
|
298 |
+
if(is_file($fullpath) && is_readable($fullpath)) {
|
299 |
+
|
300 |
+
// That message is then picked up by the AJAX listener
|
301 |
+
set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'downloaded:'.filesize($fullpath).":$fullpath", 3600);
|
302 |
+
|
303 |
+
} else {
|
304 |
+
|
305 |
+
set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'failed', 3600);
|
306 |
+
set_transient('ud_dlerrors_'.$timestamp.'_'.$type, $updraftplus->errors, 3600);
|
307 |
+
|
308 |
+
echo 'Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.';
|
309 |
+
}
|
310 |
+
|
311 |
+
@fclose($updraftplus->logfile_handle);
|
312 |
+
if (!$debug_mode) @unlink($updraftplus->logfile_name);
|
313 |
+
|
314 |
+
exit;
|
315 |
+
|
316 |
+
}
|
317 |
+
|
318 |
+
function download_file($file, $service=false) {
|
319 |
+
|
320 |
+
global $updraftplus;
|
321 |
+
|
322 |
+
@set_time_limit(900);
|
323 |
+
|
324 |
+
if (!$service) $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
|
325 |
+
|
326 |
+
$updraftplus->log("Requested file from remote service: $service:$file");
|
327 |
+
|
328 |
+
$method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
|
329 |
+
if (file_exists($method_include)) require_once($method_include);
|
330 |
+
|
331 |
+
$objname = "UpdraftPlus_BackupModule_${service}";
|
332 |
+
if (method_exists($objname, "download")) {
|
333 |
+
$remote_obj = new $objname;
|
334 |
+
$remote_obj->download($file);
|
335 |
+
} else {
|
336 |
+
$updraftplus->log("Automatic backup restoration is not available with the method: $service.");
|
337 |
+
$updraftplus->error("$file: ".sprintf(__("The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($updraftplus->backups_dir_location()).")");
|
338 |
+
}
|
339 |
+
|
340 |
+
}
|
341 |
+
|
342 |
+
// Called via AJAX
|
343 |
+
function updraft_ajax_handler() {
|
344 |
+
|
345 |
+
global $updraftplus;
|
346 |
+
|
347 |
+
// Test the nonce (probably not needed, since we're presumably admin-authed, but there's no harm)
|
348 |
+
$nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
|
349 |
+
if (! wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
|
350 |
+
|
351 |
+
if ('lastlog' == $_GET['subaction']) {
|
352 |
+
echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')'));
|
353 |
+
} elseif ('lastbackup' == $_GET['subaction']) {
|
354 |
+
echo $this->last_backup_html();
|
355 |
+
} elseif ('diskspaceused' == $_GET['subaction']) {
|
356 |
+
echo $this->recursive_directory_size($updraftplus->backups_dir_location());
|
357 |
+
} elseif ('historystatus' == $_GET['subaction']) {
|
358 |
+
$rescan = (isset($_GET['rescan']) && $_GET['rescan'] == 1);
|
359 |
+
if ($rescan) $this->rebuild_backup_history();
|
360 |
+
echo $this->existing_backup_table();
|
361 |
+
} elseif ('downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
|
362 |
+
|
363 |
+
$response = array();
|
364 |
+
|
365 |
+
$response['m'] = get_transient('ud_dlmess_'.$_GET['timestamp'].'_'.$_GET['type']).'<br>';
|
366 |
+
|
367 |
+
if ($file = get_transient('ud_dlfile_'.$_GET['timestamp'].'_'.$_GET['type'])) {
|
368 |
+
if ('failed' == $file) {
|
369 |
+
$response['e'] = __('Download failed','updraftplus').'<br>';
|
370 |
+
$errs = get_transient('ud_dlerrors_'.$_GET['timestamp'].'_'.$_GET['type']);
|
371 |
+
if (is_array($errs) && !empty($errs)) {
|
372 |
+
$response['e'] .= '<ul style="list-style: disc inside;">';
|
373 |
+
foreach ($errs as $err) {
|
374 |
+
$response['e'] .= '<li>'.htmlspecialchars($err).'</li>';
|
375 |
+
}
|
376 |
+
$response['e'] .= '</ul>';
|
377 |
+
}
|
378 |
+
} elseif (preg_match('/^downloaded:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
|
379 |
+
$response['p'] = 100;
|
380 |
+
$response['f'] = $matches[2];
|
381 |
+
$response['s'] = (int)$matches[1];
|
382 |
+
$response['t'] = (int)$matches[1];
|
383 |
+
$response['m'] = __('File ready.', 'updraftplus');
|
384 |
+
} elseif (preg_match('/^downloading:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
|
385 |
+
// Convert to bytes
|
386 |
+
$response['f'] = $matches[2];
|
387 |
+
$total_size = (int)max($matches[1], 1);
|
388 |
+
$cur_size = filesize($matches[2]);
|
389 |
+
$response['s'] = $cur_size;
|
390 |
+
$response['t'] = $total_size;
|
391 |
+
$response['m'] .= __("Download in progress", 'updraftplus').' ('.round($cur_size/1024).' / '.round(($total_size/1024)).' Kb)';
|
392 |
+
$response['p'] = round(100*$cur_size/$total_size);
|
393 |
+
} else {
|
394 |
+
$response['m'] .= __('No local copy present.', 'updraftplus');
|
395 |
+
$response['p'] = 0;
|
396 |
+
$response['s'] = 0;
|
397 |
+
$response['t'] = 1;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
echo json_encode($response);
|
402 |
+
|
403 |
+
} elseif ($_POST['subaction'] == 'credentials_test') {
|
404 |
+
$method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
|
405 |
+
|
406 |
+
// Test the credentials, return a code
|
407 |
+
require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
|
408 |
+
|
409 |
+
$objname = "UpdraftPlus_BackupModule_${method}";
|
410 |
+
if (method_exists($objname, "credentials_test")) call_user_func(array('UpdraftPlus_BackupModule_'.$method, 'credentials_test'));
|
411 |
+
}
|
412 |
+
|
413 |
+
die;
|
414 |
+
|
415 |
+
}
|
416 |
+
|
417 |
+
function upload_dir($uploads) {
|
418 |
+
global $updraftplus;
|
419 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
420 |
+
if (is_writable($updraft_dir)) $uploads['path'] = $updraft_dir;
|
421 |
+
return $uploads;
|
422 |
+
}
|
423 |
+
|
424 |
+
// We do actually want to over-write
|
425 |
+
function unique_filename_callback($dir, $name, $ext) {
|
426 |
+
return $name.$ext;
|
427 |
+
}
|
428 |
+
|
429 |
+
function sanitize_file_name($filename) {
|
430 |
+
// WordPress 3.4.2 on multisite (at least) adds in an unwanted underscore
|
431 |
+
return preg_replace('/-db\.gz_\.crypt$/', '-db.gz.crypt', $filename);
|
432 |
+
}
|
433 |
+
|
434 |
+
function plupload_action() {
|
435 |
+
// check ajax noonce
|
436 |
+
|
437 |
+
global $updraftplus;
|
438 |
+
@set_time_limit(900);
|
439 |
+
|
440 |
+
check_ajax_referer('updraft-uploader');
|
441 |
+
|
442 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
443 |
+
if (!is_writable($updraft_dir)) exit;
|
444 |
+
|
445 |
+
add_filter('upload_dir', array($this, 'upload_dir'));
|
446 |
+
add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
|
447 |
+
// handle file upload
|
448 |
+
|
449 |
+
$farray = array( 'test_form' => true, 'action' => 'plupload_action' );
|
450 |
+
|
451 |
+
$farray['test_type'] = false;
|
452 |
+
$farray['ext'] = 'x-gzip';
|
453 |
+
$farray['type'] = 'application/octet-stream';
|
454 |
+
|
455 |
+
if (isset($_POST['chunks'])) {
|
456 |
+
|
457 |
+
} else {
|
458 |
+
$farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
|
459 |
+
}
|
460 |
+
|
461 |
+
$status = wp_handle_upload(
|
462 |
+
$_FILES['async-upload'],
|
463 |
+
$farray
|
464 |
+
);
|
465 |
+
remove_filter('upload_dir', array($this, 'upload_dir'));
|
466 |
+
remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
|
467 |
+
|
468 |
+
if (isset($status['error'])) {
|
469 |
+
echo 'ERROR:'.$status['error'];
|
470 |
+
exit;
|
471 |
+
}
|
472 |
+
|
473 |
+
// If this was the chunk, then we should instead be concatenating onto the final file
|
474 |
+
if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
|
475 |
+
$final_file = $_POST['name'];
|
476 |
+
rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
|
477 |
+
$status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
|
478 |
+
|
479 |
+
// Final chunk? If so, then stich it all back together
|
480 |
+
if ($_POST['chunk'] == $_POST['chunks']-1) {
|
481 |
+
if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
|
482 |
+
for ($i=0 ; $i<$_POST['chunks']; $i++) {
|
483 |
+
$rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
|
484 |
+
if ($rh = fopen($rf, 'rb')) {
|
485 |
+
while ($line = fread($rh, 32768)) fwrite($wh, $line);
|
486 |
+
fclose($rh);
|
487 |
+
@unlink($rf);
|
488 |
+
}
|
489 |
+
}
|
490 |
+
fclose($wh);
|
491 |
+
$status['file'] = $updraft_dir.'/'.$final_file;
|
492 |
+
}
|
493 |
+
}
|
494 |
+
|
495 |
+
}
|
496 |
+
|
497 |
+
if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
|
498 |
+
$file = basename($status['file']);
|
499 |
+
if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz|gz\.crypt)$/i', $file)) {
|
500 |
+
|
501 |
+
@unlink($status['file']);
|
502 |
+
echo 'ERROR:'.__('Bad filename format - this does not look like a file created by UpdraftPlus','updraftplus');
|
503 |
+
exit;
|
504 |
+
}
|
505 |
+
}
|
506 |
+
|
507 |
+
// send the uploaded file url in response
|
508 |
+
echo 'OK:'.$status['url'];
|
509 |
+
exit;
|
510 |
+
}
|
511 |
+
|
512 |
+
function plupload_action2() {
|
513 |
+
|
514 |
+
@set_time_limit(900);
|
515 |
+
global $updraftplus;
|
516 |
+
|
517 |
+
// check ajax nonce
|
518 |
+
check_ajax_referer('updraft-uploader');
|
519 |
+
|
520 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
521 |
+
if (!is_writable($updraft_dir)) exit;
|
522 |
+
|
523 |
+
add_filter('upload_dir', array($this, 'upload_dir'));
|
524 |
+
add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
|
525 |
+
// handle file upload
|
526 |
+
|
527 |
+
$farray = array( 'test_form' => true, 'action' => 'plupload_action2' );
|
528 |
+
|
529 |
+
$farray['test_type'] = false;
|
530 |
+
$farray['ext'] = 'crypt';
|
531 |
+
$farray['type'] = 'application/octet-stream';
|
532 |
+
|
533 |
+
if (isset($_POST['chunks'])) {
|
534 |
+
// $farray['ext'] = 'zip';
|
535 |
+
// $farray['type'] = 'application/zip';
|
536 |
+
} else {
|
537 |
+
$farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
|
538 |
+
}
|
539 |
+
|
540 |
+
$status = wp_handle_upload(
|
541 |
+
$_FILES['async-upload'],
|
542 |
+
$farray
|
543 |
+
);
|
544 |
+
remove_filter('upload_dir', array($this, 'upload_dir'));
|
545 |
+
remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
|
546 |
+
|
547 |
+
if (isset($status['error'])) {
|
548 |
+
echo 'ERROR:'.$status['error'];
|
549 |
+
exit;
|
550 |
+
}
|
551 |
+
|
552 |
+
// If this was the chunk, then we should instead be concatenating onto the final file
|
553 |
+
if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
|
554 |
+
$final_file = $_POST['name'];
|
555 |
+
rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
|
556 |
+
$status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
|
557 |
+
|
558 |
+
// Final chunk? If so, then stich it all back together
|
559 |
+
if ($_POST['chunk'] == $_POST['chunks']-1) {
|
560 |
+
if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
|
561 |
+
for ($i=0 ; $i<$_POST['chunks']; $i++) {
|
562 |
+
$rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
|
563 |
+
if ($rh = fopen($rf, 'rb')) {
|
564 |
+
while ($line = fread($rh, 32768)) fwrite($wh, $line);
|
565 |
+
fclose($rh);
|
566 |
+
@unlink($rf);
|
567 |
+
}
|
568 |
+
}
|
569 |
+
fclose($wh);
|
570 |
+
$status['file'] = $updraft_dir.'/'.$final_file;
|
571 |
+
}
|
572 |
+
}
|
573 |
+
|
574 |
+
}
|
575 |
+
|
576 |
+
if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
|
577 |
+
$file = basename($status['file']);
|
578 |
+
if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i', $file)) {
|
579 |
+
|
580 |
+
@unlink($status['file']);
|
581 |
+
echo 'ERROR:'.__('Bad filename format - this does not look like an encrypted database file created by UpdraftPlus','updraftplus');
|
582 |
+
|
583 |
+
exit;
|
584 |
+
}
|
585 |
+
}
|
586 |
+
|
587 |
+
// send the uploaded file url in response
|
588 |
+
// echo 'OK:'.$status['url'];
|
589 |
+
echo 'OK:'.$file;
|
590 |
+
exit;
|
591 |
+
}
|
592 |
+
|
593 |
+
|
594 |
+
function settings_output() {
|
595 |
+
|
596 |
+
global $updraftplus;
|
597 |
+
|
598 |
+
wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui-1.8.22.custom.css');
|
599 |
+
|
600 |
+
/*
|
601 |
+
we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
|
602 |
+
for the WP_Filesystem. to do this WP outputs a form that we can't insert variables into (apparently). So the values are
|
603 |
+
passed back in as GET parameters. REQUEST covers both GET and POST so this weird logic works.
|
604 |
+
*/
|
605 |
+
if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) {
|
606 |
+
$backup_success = $this->restore_backup($_REQUEST['backup_timestamp']);
|
607 |
+
if(empty($updraftplus->errors) && $backup_success == true) {
|
608 |
+
echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
|
609 |
+
echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
610 |
+
return;
|
611 |
+
} else {
|
612 |
+
echo '<p>Restore failed...</p><ul style="list-style: disc inside;">';
|
613 |
+
foreach ($updraftplus->errors as $err) {
|
614 |
+
if (is_wp_error($err)) {
|
615 |
+
foreach ($err->get_error_messages() as $msg) {
|
616 |
+
echo '<li>'.htmlspecialchars($msg).'<li>';
|
617 |
+
}
|
618 |
+
} elseif (is_string($err)) {
|
619 |
+
echo "<li>".htmlspecialchars($err)."</li>";
|
620 |
+
} else {
|
621 |
+
print "<li>".print_r($err,true)."</li>";
|
622 |
+
}
|
623 |
+
}
|
624 |
+
echo '</ul><b>Actions:</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
625 |
+
return;
|
626 |
+
}
|
627 |
+
//uncomment the below once i figure out how i want the flow of a restoration to work.
|
628 |
+
//echo '<b>'__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">Return to UpdraftPlus Configuration</a>';
|
629 |
+
}
|
630 |
+
$deleted_old_dirs = false;
|
631 |
+
if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_delete_old_dirs') {
|
632 |
+
|
633 |
+
echo '<h1>UpdraftPlus - '.__('Remove old directories','updraftplus').'</h1>';
|
634 |
+
|
635 |
+
$nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
|
636 |
+
if (!wp_verify_nonce($nonce, 'updraft_delete_old_dirs')) die('Security check');
|
637 |
+
|
638 |
+
if($this->delete_old_dirs()) {
|
639 |
+
echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
|
640 |
+
$deleted_old_dirs = true;
|
641 |
+
} else {
|
642 |
+
echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
|
643 |
+
}
|
644 |
+
echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
645 |
+
return;
|
646 |
+
}
|
647 |
+
|
648 |
+
if(isset($_GET['error'])) $this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
|
649 |
+
if(isset($_GET['message'])) $this->show_admin_warning(htmlspecialchars($_GET['message']));
|
650 |
+
|
651 |
+
if(isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir') {
|
652 |
+
if(!$this->create_backup_dir()) {
|
653 |
+
echo '<p>'.__('Backup directory could not be created','updraftplus').'...</p><br/>';
|
654 |
+
}
|
655 |
+
echo '<p>'.__('Backup directory successfully created.','updraftplus').'</p><br/>';
|
656 |
+
echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
657 |
+
return;
|
658 |
+
}
|
659 |
+
|
660 |
+
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup') {
|
661 |
+
// For unknown reasons, the <script> runs twice if put inside the <div>
|
662 |
+
echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"><strong>',__('Schedule backup','updraftplus').':</strong> ';
|
663 |
+
if (wp_schedule_single_event(time()+5, 'updraft_backup_all') === false) {
|
664 |
+
$updraftplus->log("A backup run failed to schedule");
|
665 |
+
echo __("Failed.",'updraftplus')."</div>";
|
666 |
+
} else {
|
667 |
+
echo htmlspecialchars(__('OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the "Last log message" field below.','updraftplus'))." <a href=\"http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/\">".__('Nothing happening? Follow this link for help.','updraftplus')."</a></div><script>setTimeout(function(){updraft_showlastbackup();}, 7000);</script>";
|
668 |
+
$updraftplus->log("A backup run has been scheduled");
|
669 |
+
}
|
670 |
+
}
|
671 |
+
|
672 |
+
// updraft_file_ids is not deleted
|
673 |
+
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $updraftplus->boot_backup(true,true); }
|
674 |
+
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') { $updraftplus->backup_db(); }
|
675 |
+
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
|
676 |
+
$settings = array('updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_wpcore',
|
677 |
+
'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_clientid', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder', 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_sftp_settings', 'updraft_disable_ping', 'updraft_cloudfiles_user', 'updraft_cloudfiles_apikey', 'updraft_cloudfiles_path', 'updraft_cloudfiles_authurl', 'updraft_ssl_useservercerts', 'updraft_ssl_disableverify');
|
678 |
+
foreach ($settings as $s) {
|
679 |
+
UpdraftPlus_Options::delete_updraft_option($s);
|
680 |
+
}
|
681 |
+
$this->show_admin_warning(__("Your settings have been wiped.",'updraftplus'));
|
682 |
+
}
|
683 |
+
|
684 |
+
?>
|
685 |
+
<div class="wrap">
|
686 |
+
<h1><?php echo $updraftplus->plugin_title; ?></h1>
|
687 |
+
|
688 |
+
<?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('Other WordPress plugins','updraftplus');?></a>). <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
|
689 |
+
<br>
|
690 |
+
<?php
|
691 |
+
if(isset($_GET['updraft_restore_success'])) {
|
692 |
+
// If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
|
693 |
+
$this->rebuild_backup_history();
|
694 |
+
echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('Your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.')."</div>";
|
695 |
+
}
|
696 |
+
|
697 |
+
$ws_advert = $updraftplus->wordshell_random_advert(1);
|
698 |
+
if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
|
699 |
+
|
700 |
+
if($deleted_old_dirs) echo '<div style="color:blue" class=\"updated fade\">'.__('Old directories successfully deleted.','updraftplus').'</div>';
|
701 |
+
|
702 |
+
if(!$updraftplus->memory_check(64)) {?>
|
703 |
+
<div style="color:orange"><?php _e("Your PHP memory limit (set by your web hosting company) is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will bhe successful with a 32Mb limit - your experience may vary).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $this->memory_check_current(); ?> Mb</div>
|
704 |
+
<?php
|
705 |
+
}
|
706 |
+
if(1==0 && !$this->execution_time_check(60)) {?>
|
707 |
+
<div style="color:orange"><?php _e("Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:",'updraftplus');?> <?php echo ini_get('max_execution_time').' '.__('seconds','updraftplus')?>.</div>
|
708 |
+
<?php
|
709 |
+
}
|
710 |
+
|
711 |
+
if($this->scan_old_dirs()) {?>
|
712 |
+
<div class="updated fade" style="padding:8px;"><?php _e('You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked).','updraftplus');?>
|
713 |
+
<form method="post" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
|
714 |
+
<?php wp_nonce_field('updraft_delete_old_dirs'); ?>
|
715 |
+
<input type="hidden" name="action" value="updraft_delete_old_dirs" />
|
716 |
+
<input type="submit" class="button-primary" value="<?php _e('Delete Old Directories','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('Are you sure you want to delete the old directories? This cannot be undone.','updraftplus'));?>'))" />
|
717 |
+
</form>
|
718 |
+
</div>
|
719 |
+
<?php
|
720 |
+
}
|
721 |
+
if(!empty($updraftplus->errors)) {
|
722 |
+
foreach($updraftplus->errors as $error) {
|
723 |
+
// ignoring severity
|
724 |
+
echo '<div style="color:red">'.$error['error'].'</div>';
|
725 |
+
}
|
726 |
+
}
|
727 |
+
?>
|
728 |
+
|
729 |
+
<h2 style="clear:left;"><?php _e('Existing Schedule And Backups','updraftplus');?></h2>
|
730 |
+
<table class="form-table" style="float:left; clear: both; width:545px;">
|
731 |
+
<noscript>
|
732 |
+
<tr>
|
733 |
+
<th><?php _e('JavaScript warning','updraftplus');?>:</th>
|
734 |
+
<td style="color:red"><?php _e('This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser.','updraftplus');?></td>
|
735 |
+
</tr>
|
736 |
+
</noscript>
|
737 |
+
<?php
|
738 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
739 |
+
// UNIX timestamp
|
740 |
+
$next_scheduled_backup = wp_next_scheduled('updraft_backup');
|
741 |
+
if ($next_scheduled_backup) {
|
742 |
+
// Convert to GMT
|
743 |
+
$next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
|
744 |
+
// Convert to blog time zone
|
745 |
+
$next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i');
|
746 |
+
} else {
|
747 |
+
$next_scheduled_backup = __('Nothing currently scheduled','updraftplus');
|
748 |
+
}
|
749 |
+
|
750 |
+
$next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
|
751 |
+
if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
|
752 |
+
$next_scheduled_backup_database = ('Nothing currently scheduled' == $next_scheduled_backup) ? $next_scheduled_backup : __("At the same time as the files backup", 'updraftplus');
|
753 |
+
} else {
|
754 |
+
if ($next_scheduled_backup_database) {
|
755 |
+
// Convert to GMT
|
756 |
+
$next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
|
757 |
+
// Convert to blog time zone
|
758 |
+
$next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i');
|
759 |
+
} else {
|
760 |
+
$next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
|
761 |
+
}
|
762 |
+
}
|
763 |
+
$current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');
|
764 |
+
|
765 |
+
$backup_disabled = (is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
|
766 |
+
|
767 |
+
$last_backup_html = $this->last_backup_html();
|
768 |
+
|
769 |
+
?>
|
770 |
+
|
771 |
+
<tr>
|
772 |
+
<th><?php _e('Next scheduled backups','updraftplus');?>:</th>
|
773 |
+
<td>
|
774 |
+
<div style="width: 76px; float:left;"><?php _e('Files','updraftplus'); ?>:</div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup?></div>
|
775 |
+
<div style="width: 76px; clear: left; float:left;"><?php _e('Database','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup_database?></div>
|
776 |
+
<div style="width: 76px; clear: left; float:left;"><?php _e('Time now','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $current_time?></div>
|
777 |
+
</td>
|
778 |
+
</tr>
|
779 |
+
<tr>
|
780 |
+
<th><?php _e('Last finished backup run','updraftplus');?>:</th>
|
781 |
+
<td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
|
782 |
+
</tr>
|
783 |
+
</table>
|
784 |
+
<div style="float:left; width:200px; padding-top: 20px;">
|
785 |
+
<p><button type="button" <?php echo $backup_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now','updraftplus');?></button></p>
|
786 |
+
<div style="position:relative">
|
787 |
+
<div style="position:absolute;top:0;left:0">
|
788 |
+
<?php
|
789 |
+
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
790 |
+
$backup_history = (is_array($backup_history))?$backup_history:array();
|
791 |
+
$restore_disabled = (count($backup_history) == 0) ? 'disabled="disabled"' : "";
|
792 |
+
?>
|
793 |
+
<input type="button" class="button-primary" <?php echo $restore_disabled ?> value="<?php _e('Restore','updraftplus');?>" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('.download-backups').slideDown(); updraft_historytimertoggle(1); jQuery('html,body').animate({scrollTop: jQuery('#updraft_lastlogcontainer').offset().top},'slow');">
|
794 |
+
</div>
|
795 |
+
</div>
|
796 |
+
</div>
|
797 |
+
<br style="clear:both" />
|
798 |
+
<table class="form-table">
|
799 |
+
<tr>
|
800 |
+
<th><?php _e('Last log message','updraftplus');?>:</th>
|
801 |
+
<td>
|
802 |
+
<span id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', __('(Nothing yet logged)','updraftplus'))); ?></span><br>
|
803 |
+
<a href="?page=updraftplus&action=downloadlatestmodlog&wpnonce=<?php echo wp_create_nonce('updraftplus_download') ?>"><?php _e('Download most recently modified log file','updraftplus');?></a>
|
804 |
+
</td>
|
805 |
+
</tr>
|
806 |
+
<tr>
|
807 |
+
<th><?php echo htmlspecialchars(__('Backups, logs & restoring','updraftplus')); ?>:</th>
|
808 |
+
<td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="jQuery('.download-backups').toggle(); updraft_historytimertoggle(0);"><?php echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)); ?> available</a></td>
|
809 |
+
</tr>
|
810 |
+
<tr>
|
811 |
+
<td></td><td class="download-backups" style="display:none; border: 1px dotted;">
|
812 |
+
<p style="max-width: 740px;"><ul style="list-style: disc inside;">
|
813 |
+
<li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
|
814 |
+
<li><strong><?php _e('Restoring','updraftplus');?>:</strong> <?php _e("Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself.",'updraftplus');?> <?php _e('More tasks:','updraftplus');?> <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('upload backup files','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li>
|
815 |
+
<li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
|
816 |
+
<li title="<?php _e('This is a count of the contents of your Updraft directory','updraftplus');?>"><strong><?php _e('Web-server disk space in use by UpdraftPlus','updraftplus');?>:</strong> <span id="updraft_diskspaceused"><em>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a></li></ul>
|
817 |
+
|
818 |
+
<div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
|
819 |
+
<p><em><?php _e("Upload files into UpdraftPlus. Use this to import backups made on a different WordPress installation." ,'updraftplus');?></em></p>
|
820 |
+
<div id="plupload-upload-ui" style="width: 70%;">
|
821 |
+
<div id="drag-drop-area">
|
822 |
+
<div class="drag-drop-inside">
|
823 |
+
<p class="drag-drop-info"><?php _e('Drop backup zips here'); ?></p>
|
824 |
+
<p><?php _ex('or', 'Uploader: Drop zip files here - or - Select Files'); ?></p>
|
825 |
+
<p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
|
826 |
+
</div>
|
827 |
+
</div>
|
828 |
+
<div id="filelist">
|
829 |
+
</div>
|
830 |
+
</div>
|
831 |
+
|
832 |
+
</div>
|
833 |
+
|
834 |
+
<div id="ud_downloadstatus"></div>
|
835 |
+
<script>
|
836 |
+
function updraftplus_diskspace() {
|
837 |
+
jQuery('#updraft_diskspaceused').html('<em><?php _e('calculating...','updraftplus');?></em>');
|
838 |
+
jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'diskspaceused', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>' }, function(response) {
|
839 |
+
jQuery('#updraft_diskspaceused').html(response);
|
840 |
+
});
|
841 |
+
}
|
842 |
+
var lastlog_lastmessage = "";
|
843 |
+
function updraftplus_deletefromserver(timestamp, type) {
|
844 |
+
var pdata = {
|
845 |
+
action: 'updraft_download_backup',
|
846 |
+
stage: 'delete',
|
847 |
+
timestamp: timestamp,
|
848 |
+
type: type,
|
849 |
+
_wpnonce: '<?php echo wp_create_nonce("updraftplus_download"); ?>'
|
850 |
+
};
|
851 |
+
jQuery.post(ajaxurl, pdata, function(response) {
|
852 |
+
if (response == 'deleted') {
|
853 |
+
|
854 |
+
} else {
|
855 |
+
alert('We requested to delete the file, but could not understand the server\'s response '+response);
|
856 |
+
}
|
857 |
+
});
|
858 |
+
}
|
859 |
+
function updraftplus_downloadstage2(timestamp, type) {
|
860 |
+
location.href=ajaxurl+'?_wpnonce=<?php echo wp_create_nonce("updraftplus_download"); ?>×tamp='+timestamp+'&type='+type+'&stage=2&action=updraft_download_backup';
|
861 |
+
}
|
862 |
+
function updraft_downloader(base, nonce, what) {
|
863 |
+
// Create somewhere for the status to be found
|
864 |
+
var stid = base+nonce+'_'+what;
|
865 |
+
if (!jQuery('#'+stid).length) {
|
866 |
+
jQuery('#ud_downloadstatus').append('<div style="clear:left; border: 1px solid; padding: 8px; margin-top: 4px; max-width:840px;" id="'+stid+'"><button onclick="jQuery(\'#'+stid+'\').fadeOut().remove();" type="button" style="float:right; margin-bottom: 8px;">X</button><strong>Download '+what+' ('+nonce+')</strong>:<div class="raw">Begun looking for this entity</div><div class="file" id="'+stid+'_st"><div class="dlfileprogress" style="width: 0;"></div></div>');
|
867 |
+
// <b><span class="dlname">??</span></b> (<span class="dlsofar">?? KB</span>/<span class="dlsize">??</span> KB)
|
868 |
+
setTimeout(function(){updraft_downloader_status(base, nonce, what)}, 300);
|
869 |
+
}
|
870 |
+
// Now send the actual request to kick it all off
|
871 |
+
jQuery.post(ajaxurl, jQuery('#uddownloadform_'+what+'_'+nonce).serialize());
|
872 |
+
// We don't want the form to submit as that replaces the document
|
873 |
+
return false;
|
874 |
+
}
|
875 |
+
var dlstatus_sdata = {
|
876 |
+
action: 'updraft_ajax',
|
877 |
+
subaction: 'downloadstatus',
|
878 |
+
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
|
879 |
+
};
|
880 |
+
dlstatus_lastlog = '';
|
881 |
+
function updraft_downloader_status(base, nonce, what) {
|
882 |
+
// Get the DOM id of the status div (add _st for the id of the file itself)
|
883 |
+
var stid = base+nonce+'_'+what;
|
884 |
+
if (jQuery('#'+stid).length) {
|
885 |
+
// console.log(stid+": "+jQuery('#'+stid).length);
|
886 |
+
dlstatus_sdata.timestamp = nonce;
|
887 |
+
dlstatus_sdata.type = what;
|
888 |
+
jQuery.get(ajaxurl, dlstatus_sdata, function(response) {
|
889 |
+
nexttimer = 1250;
|
890 |
+
if (dlstatus_lastlog == response) { nexttimer = 3000; }
|
891 |
+
try {
|
892 |
+
var resp = jQuery.parseJSON(response);
|
893 |
+
var cancel_repeat = 0;
|
894 |
+
if (resp.e != null) {
|
895 |
+
jQuery('#'+stid+' .raw').html('<strong><?php _e('Error:','updraftplus'); ?></strong> '+resp.e);
|
896 |
+
console.log(resp);
|
897 |
+
} else if (resp.p != null) {
|
898 |
+
jQuery('#'+stid+'_st .dlfileprogress').width(resp.p+'%');
|
899 |
+
//jQuery('#'+stid+'_st .dlsofar').html(Math.round(resp.s/1024));
|
900 |
+
//jQuery('#'+stid+'_st .dlsize').html(Math.round(resp.t/1024));
|
901 |
+
if (resp.m != null) {
|
902 |
+
if (resp.p < 100 || base != 'uddlstatus_') {
|
903 |
+
jQuery('#'+stid+' .raw').html(resp.m);
|
904 |
+
} else {
|
905 |
+
jQuery('#'+stid+' .raw').html('<?php _e('File ready.','updraftplus'); ?> <?php _e('You should:','updraftplus'); ?> <button type="button" onclick="updraftplus_downloadstage2(\''+nonce+'\', \''+what+'\')\">Download to your computer</button> and then, if you wish, <button id="uddownloaddelete_'+nonce+'_'+what+'" type="button" onclick="updraftplus_deletefromserver(\''+nonce+'\', \''+what+'\')\">Delete from your web server</button>');
|
906 |
+
}
|
907 |
+
}
|
908 |
+
dlstatus_lastlog = response;
|
909 |
+
} else if (resp.m != null) {
|
910 |
+
jQuery('#'+stid+' .raw').html(resp.m);
|
911 |
+
} else {
|
912 |
+
alert('<?php _e('Download error: the server sent us a response (JSON) which we did not understand', 'updraftplus'); ?> ('+response+')');
|
913 |
+
cancel_repeat = 1;
|
914 |
+
}
|
915 |
+
if (cancel_repeat == 0) { setTimeout(function(){updraft_downloader_status(base, nonce, what)}, nexttimer); }
|
916 |
+
} catch(err) {
|
917 |
+
alert('<?php _e('Download error: the server sent us a response which we did not understand.', 'updraftplus'); ?> <?php _e("Error:",'updraftplus');?> '+err);
|
918 |
+
}
|
919 |
+
});
|
920 |
+
}
|
921 |
+
}
|
922 |
+
</script>
|
923 |
+
<div id="updraft_existing_backups" style="margin-bottom:12px;">
|
924 |
+
<?php
|
925 |
+
print $this->existing_backup_table($backup_history);
|
926 |
+
?>
|
927 |
+
</div>
|
928 |
+
</td>
|
929 |
+
</tr>
|
930 |
+
</table>
|
931 |
+
|
932 |
+
<div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
|
933 |
+
<p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span id="updraft_restore_date"></span></p>
|
934 |
+
<p><?php _e("Restoring will replace this site's themes, plugins, uploads, database and/or other content directories (according to what is contained in the backup set, and your selection",'updraftplus');?>). <?php _e('Choose the components to restore','updraftplus');?>:</p>
|
935 |
+
<form id="updraft_restore_form" method="post">
|
936 |
+
<fieldset>
|
937 |
+
<input type="hidden" name="action" value="updraft_restore">
|
938 |
+
<input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
|
939 |
+
<?php
|
940 |
+
|
941 |
+
# The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
|
942 |
+
if(@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
|
943 |
+
echo "<p><em>".__('Your web server has PHP\'s so-called safe_mode active.','updraftplus').' '.__('This makes time-outs much more likely. You are recommended to turn safe_mode off, or to restore only one entity at a time, <a href="http://updraftplus.com/faqs/i-want-to-restore-but-have-either-cannot-or-have-failed-to-do-so-from-the-wp-admin-console/">or to restore manually</a>.', 'updraftplus')."</em></p><br/>";
|
944 |
+
}
|
945 |
+
|
946 |
+
$backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
|
947 |
+
foreach ($backupable_entities as $type => $info) {
|
948 |
+
echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label for="updraft_restore_'.$type.'">'.$info['description'].'</label><br></div>';
|
949 |
+
}
|
950 |
+
?>
|
951 |
+
<div><input id="updraft_restore_db" type="checkbox" name="updraft_restore[]" value="db"> <label for="updraft_restore_db"><?php _e('Database','updraftplus'); ?></label><br></div>
|
952 |
+
</fieldset>
|
953 |
+
</form>
|
954 |
+
</div>
|
955 |
+
|
956 |
+
<div id="updraft-backupnow-modal" title="UpdraftPlus - <?php _e('Perform a backup now','updraftplus'); ?>">
|
957 |
+
<p><?php _e("This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background.",'updraftplus');?></p>
|
958 |
+
|
959 |
+
<form id="updraft-backupnow-form" method="post" action="">
|
960 |
+
<input type="hidden" name="action" value="updraft_backup" />
|
961 |
+
</form>
|
962 |
+
|
963 |
+
<p><?php _e('Does nothing happen when you schedule backups?','updraftplus');?> <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for help.','updraft');?></a></p>
|
964 |
+
</div>
|
965 |
+
|
966 |
+
<?php
|
967 |
+
if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
|
968 |
+
?>
|
969 |
+
<h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
|
970 |
+
<table>
|
971 |
+
<tr>
|
972 |
+
<td>
|
973 |
+
<p style="max-width:800px;"><?php echo __('Do you need WordPress Multisite support?','updraftplus').' <a href="http://updraftplus.com/">'. __('Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on.','updraftplus');?></a>.</p>
|
974 |
+
</td>
|
975 |
+
</tr>
|
976 |
+
</table>
|
977 |
+
<?php } ?>
|
978 |
+
<h2><?php _e('Configure Backup Contents And Schedule','updraftplus');?></h2>
|
979 |
+
<?php UpdraftPlus_Options::options_form_begin(); ?>
|
980 |
+
<?php $this->settings_formcontents($last_backup_html); ?>
|
981 |
+
</form>
|
982 |
+
<div style="padding-top: 40px; display:none;" class="expertmode">
|
983 |
+
<hr>
|
984 |
+
<h3><?php _e('Debug Information And Expert Options','updraftplus');?></h3>
|
985 |
+
<p>
|
986 |
+
<?php
|
987 |
+
$peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
|
988 |
+
$memory_usage = memory_get_usage(true)/1024/1024;
|
989 |
+
echo __('Peak memory usage','updraftplus').': '.$peak_memory_usage.' MB<br/>';
|
990 |
+
echo __('Current memory usage','updraftplus').': '.$memory_usage.' MB<br/>';
|
991 |
+
echo __('PHP memory limit','updraftplus').': '.ini_get('memory_limit').' <br/>';
|
992 |
+
?>
|
993 |
+
</p>
|
994 |
+
<p style="max-width: 600px;"><?php _e('The buttons below will immediately execute a backup run, independently of WordPress\'s scheduler. If these work whilst your scheduled backups and the "Backup Now" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the "Backup Now" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them.','updraftplus');?></p>
|
995 |
+
|
996 |
+
<form method="post">
|
997 |
+
<input type="hidden" name="action" value="updraft_backup_debug_all" />
|
998 |
+
<p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Full Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled).','updraftplus'));?>'))" /></p>
|
999 |
+
</form>
|
1000 |
+
<form method="post">
|
1001 |
+
<input type="hidden" name="action" value="updraft_backup_debug_db" />
|
1002 |
+
<p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Database Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites..','updraftplus'));?>'))" /></p>
|
1003 |
+
</form>
|
1004 |
+
<h3><?php _e('Wipe Settings','updraftplus');?></h3>
|
1005 |
+
<p style="max-width: 600px;"><?php _e('This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish.','updraftplus');?></p>
|
1006 |
+
<form method="post">
|
1007 |
+
<input type="hidden" name="action" value="updraft_wipesettings" />
|
1008 |
+
<p><input type="submit" class="button-primary" value="<?php _e('Wipe All Settings','updraftplus'); ?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will delete all your UpdraftPlus settings - are you sure you want to do this?'));?>'))" /></p>
|
1009 |
+
</form>
|
1010 |
+
</div>
|
1011 |
+
|
1012 |
+
<script type="text/javascript">
|
1013 |
+
/* <![CDATA[ */
|
1014 |
+
jQuery(document).ready(function() {
|
1015 |
+
jQuery('#updraft-service').change(function() {
|
1016 |
+
jQuery('.updraftplusmethod').hide();
|
1017 |
+
var active_class = jQuery(this).val();
|
1018 |
+
jQuery('.'+active_class).show();
|
1019 |
+
});
|
1020 |
+
})
|
1021 |
+
jQuery(window).load(function() {
|
1022 |
+
//this is for hiding the restore progress at the top after it is done
|
1023 |
+
setTimeout('jQuery("#updraft-restore-progress").toggle(1000)',3000)
|
1024 |
+
jQuery('#updraft-restore-progress-toggle').click(function() {
|
1025 |
+
jQuery('#updraft-restore-progress').toggle(500)
|
1026 |
+
})
|
1027 |
+
})
|
1028 |
+
/* ]]> */
|
1029 |
+
</script>
|
1030 |
+
<?php
|
1031 |
+
}
|
1032 |
+
|
1033 |
+
//deletes the -old directories that are created when a backup is restored.
|
1034 |
+
function delete_old_dirs() {
|
1035 |
+
global $wp_filesystem;
|
1036 |
+
$credentials = request_filesystem_credentials(wp_nonce_url("options-general.php?page=updraftplus&action=updraft_delete_old_dirs", 'updraft_delete_old_dirs'));
|
1037 |
+
WP_Filesystem($credentials);
|
1038 |
+
if ( $wp_filesystem->errors->get_error_code() ) {
|
1039 |
+
foreach ( $wp_filesystem->errors->get_error_messages() as $message )
|
1040 |
+
show_message($message);
|
1041 |
+
exit;
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
$list = $wp_filesystem->dirlist(WP_CONTENT_DIR);
|
1045 |
+
|
1046 |
+
$return_code = true;
|
1047 |
+
|
1048 |
+
foreach ($list as $item) {
|
1049 |
+
if (substr($item['name'], -4, 4) == "-old") {
|
1050 |
+
//recursively delete
|
1051 |
+
print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($item['name']).": ";
|
1052 |
+
if(!$wp_filesystem->delete(WP_CONTENT_DIR.'/'.$item['name'], true)) {
|
1053 |
+
$return_code = false;
|
1054 |
+
print "<strong>Failed</strong><br>";
|
1055 |
+
} else {
|
1056 |
+
print "<strong>OK</strong><br>";
|
1057 |
+
}
|
1058 |
+
}
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
return $return_code;
|
1062 |
+
}
|
1063 |
+
|
1064 |
+
function create_backup_dir() {
|
1065 |
+
global $wp_filesystem, $updraftplus;
|
1066 |
+
$credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_create_backup_dir");
|
1067 |
+
WP_Filesystem($credentials);
|
1068 |
+
if ( $wp_filesystem->errors->get_error_code() ) {
|
1069 |
+
foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
|
1070 |
+
exit;
|
1071 |
+
}
|
1072 |
+
|
1073 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
1074 |
+
$default_backup_dir = WP_CONTENT_DIR.'/updraft';
|
1075 |
+
$updraft_dir = ($updraft_dir)?$updraft_dir:$default_backup_dir;
|
1076 |
+
|
1077 |
+
if (!$wp_filesystem->mkdir($updraft_dir, 0775)) return false;
|
1078 |
+
|
1079 |
+
return true;
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
function execution_time_check($time) {
|
1083 |
+
$setting = ini_get('max_execution_time');
|
1084 |
+
return ( $setting==0 || $setting >= $time) ? true : false;
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
//scans the content dir to see if any -old dirs are present
|
1088 |
+
function scan_old_dirs() {
|
1089 |
+
$dirArr = scandir(WP_CONTENT_DIR);
|
1090 |
+
foreach($dirArr as $dir) {
|
1091 |
+
if(strpos($dir,'-old') !== false) return true;
|
1092 |
+
}
|
1093 |
+
return false;
|
1094 |
+
}
|
1095 |
+
|
1096 |
+
function last_backup_html() {
|
1097 |
+
|
1098 |
+
global $updraftplus;
|
1099 |
+
|
1100 |
+
$updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
|
1101 |
+
|
1102 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
1103 |
+
|
1104 |
+
if($updraft_last_backup) {
|
1105 |
+
|
1106 |
+
if ($updraft_last_backup['success']) {
|
1107 |
+
// Convert to GMT, then to blog time
|
1108 |
+
$last_backup_text = get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time']), 'D, F j, Y H:i');
|
1109 |
+
} else {
|
1110 |
+
$last_backup_text = implode("<br>",$updraft_last_backup['errors']);
|
1111 |
+
}
|
1112 |
+
|
1113 |
+
if (!empty($updraft_last_backup['backup_nonce'])) {
|
1114 |
+
$potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
|
1115 |
+
if (is_readable($potential_log_file)) $last_backup_text .= "<br><a href=\"?page=updraftplus&action=downloadlog&updraftplus_backup_nonce=".$updraft_last_backup['backup_nonce']."\">".__('Download log file','updraftplus')."</a>";
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
$last_backup_color = ($updraft_last_backup['success']) ? 'green' : 'red';
|
1119 |
+
|
1120 |
+
} else {
|
1121 |
+
$last_backup_text = __('No backup has been completed.','updraftplus');
|
1122 |
+
$last_backup_color = 'blue';
|
1123 |
+
}
|
1124 |
+
|
1125 |
+
return "<span style=\"color:${last_backup_color}\">${last_backup_text}</span>";
|
1126 |
+
|
1127 |
+
}
|
1128 |
+
|
1129 |
+
function settings_formcontents($last_backup_html) {
|
1130 |
+
|
1131 |
+
global $updraftplus;
|
1132 |
+
|
1133 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
1134 |
+
|
1135 |
+
?>
|
1136 |
+
<table class="form-table" style="width:900px;">
|
1137 |
+
<tr>
|
1138 |
+
<th><?php _e('File backup intervals','updraftplus'); ?>:</th>
|
1139 |
+
<td><select id="updraft_interval" name="updraft_interval" onchange="updraft_check_same_times();">
|
1140 |
+
<?php
|
1141 |
+
$intervals = array ("manual" => _x("Manual",'i.e. Non-automatic','updraftplus'), 'every4hours' => __("Every 4 hours",'updraftplus'), 'every8hours' => __("Every 8 hours",'updraftplus'), 'twicedaily' => __("Every 12 hours",'updraftplus'), 'daily' => __("Daily",'updraftplus'), 'weekly' => __("Weekly",'updraftplus'), 'fortnightly' => __("Fortnightly",'updraftplus'), 'monthly' => __("Monthly",'updraftplus'));
|
1142 |
+
foreach ($intervals as $cronsched => $descrip) {
|
1143 |
+
echo "<option value=\"$cronsched\" ";
|
1144 |
+
if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval','manual')) echo 'selected="selected"';
|
1145 |
+
echo ">$descrip</option>\n";
|
1146 |
+
}
|
1147 |
+
?>
|
1148 |
+
</select> <?php echo apply_filters('updraftplus_schedule_showfileconfig', '<input type="hidden" name="updraftplus_starttime_files" value="">'); ?>
|
1149 |
+
<?php
|
1150 |
+
echo __('and retain this many backups', 'updraftplus').': ';
|
1151 |
+
$updraft_retain = UpdraftPlus_Options::get_updraft_option('updraft_retain', 1);
|
1152 |
+
$updraft_retain = ((int)$updraft_retain > 0) ? (int)$updraft_retain : 1;
|
1153 |
+
?> <input type="text" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
|
1154 |
+
</td>
|
1155 |
+
</tr>
|
1156 |
+
<tr>
|
1157 |
+
<th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
|
1158 |
+
<td><select id="updraft_interval_database" name="updraft_interval_database" onchange="updraft_check_same_times();">
|
1159 |
+
<?php
|
1160 |
+
foreach ($intervals as $cronsched => $descrip) {
|
1161 |
+
echo "<option value=\"$cronsched\" ";
|
1162 |
+
if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'))) echo 'selected="selected"';
|
1163 |
+
echo ">$descrip</option>\n";
|
1164 |
+
}
|
1165 |
+
?>
|
1166 |
+
</select> <span id="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbconfig', '<input type="hidden" name="updraftplus_starttime_db" value="">'); ?></span>
|
1167 |
+
<?php
|
1168 |
+
echo __('and retain this many backups', 'updraftplus').': ';
|
1169 |
+
$updraft_retain_db = UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
|
1170 |
+
$updraft_retain_db = ((int)$updraft_retain_db > 0) ? (int)$updraft_retain_db : 1;
|
1171 |
+
?> <input type="text" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
|
1172 |
+
</td>
|
1173 |
+
</tr>
|
1174 |
+
<tr class="backup-interval-description">
|
1175 |
+
<td></td><td><p><?php echo htmlspecialchars(__('If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
|
1176 |
+
<?php echo apply_filters('updraftplus_fixtime_advert', '<p><strong>'.__('To fix the time at which a backup should take place,','updraftplus').' </strong> ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), <a href="http://updraftplus.com/shop/fix-time/">'.htmlspecialchars(__('use the "Fix Time" add-on','updraftplus')).'</a></p>'); ?>
|
1177 |
+
</td>
|
1178 |
+
</tr>
|
1179 |
+
<tr>
|
1180 |
+
<th><?php _e('Include in files backup','updraftplus');?>:</th>
|
1181 |
+
<td>
|
1182 |
+
|
1183 |
+
<?php
|
1184 |
+
$backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
|
1185 |
+
$include_others_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude',UPDRAFT_DEFAULT_OTHERS_EXCLUDE);
|
1186 |
+
# The true (default value if non-existent) here has the effect of forcing a default of on.
|
1187 |
+
foreach ($backupable_entities as $key => $info) {
|
1188 |
+
$included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key", apply_filters("updraftplus_defaultoption_include_".$key, true))) ? 'checked="checked"' : "";
|
1189 |
+
if ('others' == $key) {
|
1190 |
+
?><input id="updraft_include_others" type="checkbox" name="updraft_include_others" value="1" <?php echo $included; ?> /> <label for="updraft_include_<?php echo $key ?>"><?php echo __('Any other directories found inside wp-content but exclude these directories:', 'updraftplus');?></label> <input type="text" name="updraft_include_others_exclude" size="44" value="<?php echo htmlspecialchars($include_others_exclude); ?>"/><br><?php
|
1191 |
+
} else {
|
1192 |
+
echo "<input id=\"updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"updraft_include_$key\"> ".$info['description']."</label><br>";
|
1193 |
+
}
|
1194 |
+
}
|
1195 |
+
?>
|
1196 |
+
<p><?php echo apply_filters('updraftplus_admin_directories_description', __('The above directories are everything, except for WordPress core itself which you can download afresh from WordPress.org.', 'updraftplus').' <a href="http://updraftplus.com/shop/">'.htmlspecialchars(__('Or, get the "More Files" add-on from our shop.', 'updraftplus'))); ?></a> <a href="http://wordshell.net"></p><p>(<?php echo __('Use WordShell for automatic backup, version control and patching', 'updraftplus');?></a>).</p></td>
|
1197 |
+
</td>
|
1198 |
+
</tr>
|
1199 |
+
<tr>
|
1200 |
+
<th><?php _e('Email','updraftplus'); ?>:</th>
|
1201 |
+
<td><input type="text" style="width:260px" name="updraft_email" value="<?php echo UpdraftPlus_Options::get_updraft_option('updraft_email'); ?>" /> <br><?php _e('Enter an address here to have a report sent (and the whole backup, if you choose) to it.','updraftplus'); ?></td>
|
1202 |
+
</tr>
|
1203 |
+
|
1204 |
+
<tr>
|
1205 |
+
<th><?php _e('Database encryption phrase','updraftplus');?>:</th>
|
1206 |
+
<?php
|
1207 |
+
$updraft_encryptionphrase = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
|
1208 |
+
?>
|
1209 |
+
<td><input type="text" name="updraft_encryptionphrase" id="updraft_encryptionphrase" value="<?php echo $updraft_encryptionphrase ?>" style="width:132px" /></td>
|
1210 |
+
</tr>
|
1211 |
+
<tr class="backup-crypt-description">
|
1212 |
+
<td></td><td><p><?php _e('If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back).','updraftplus');?> <a href="#" onclick="jQuery('#updraftplus_db_decrypt').val(jQuery('#updraft_encryptionphrase').val()); jQuery('#updraft-manualdecrypt-modal').slideToggle(); return false;"><?php _e('You can also decrypt a database manually here.','updraftplus');?></a></p>
|
1213 |
+
|
1214 |
+
<div id="updraft-manualdecrypt-modal" style="width: 85%; margin: 16px; display:none; margin-left: 100px;">
|
1215 |
+
<p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
|
1216 |
+
<div id="plupload-upload-ui2" style="width: 80%;">
|
1217 |
+
<div id="drag-drop-area2">
|
1218 |
+
<div class="drag-drop-inside">
|
1219 |
+
<p class="drag-drop-info"><?php _e('Drop encrypted database files (db.crypt.gz files) here to upload them for decryption'); ?></p>
|
1220 |
+
<p><?php _ex('or', 'Uploader: Drop .crypt.db.gz files here to upload them for decryption - or - Select Files'); ?></p>
|
1221 |
+
<p class="drag-drop-buttons"><input id="plupload-browse-button2" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
|
1222 |
+
<p style="margin-top: 18px;"><?php _e('Use decryption key','updraftplus')?>: <input id="updraftplus_db_decrypt" type="text" size="12"></input></p>
|
1223 |
+
</div>
|
1224 |
+
</div>
|
1225 |
+
<div id="filelist2">
|
1226 |
+
</div>
|
1227 |
+
</div>
|
1228 |
+
|
1229 |
+
</div>
|
1230 |
+
|
1231 |
+
|
1232 |
+
</td>
|
1233 |
+
</tr>
|
1234 |
+
</table>
|
1235 |
+
|
1236 |
+
<h2><?php _e('Copying Your Backup To Remote Storage','updraftplus');?></h2>
|
1237 |
+
|
1238 |
+
<table class="form-table" style="width:900px;">
|
1239 |
+
<tr>
|
1240 |
+
<th><?php _e('Choose your remote storage','updraftplus');?>:</th>
|
1241 |
+
<td><select name="updraft_service" id="updraft-service">
|
1242 |
+
<?php
|
1243 |
+
$debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
|
1244 |
+
|
1245 |
+
$set = 'selected="selected"';
|
1246 |
+
|
1247 |
+
// Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
|
1248 |
+
$active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
|
1249 |
+
|
1250 |
+
?>
|
1251 |
+
<option value="none" <?php
|
1252 |
+
if ($active_service == "none") echo $set; ?>><?php _e('None','updraftplus'); ?></option>
|
1253 |
+
<?php
|
1254 |
+
foreach ($updraftplus->backup_methods as $method => $description) {
|
1255 |
+
echo "<option value=\"$method\"";
|
1256 |
+
if ($active_service == $method) echo ' '.$set;
|
1257 |
+
echo '>'.$description;
|
1258 |
+
echo "</option>\n";
|
1259 |
+
}
|
1260 |
+
?>
|
1261 |
+
</select></td>
|
1262 |
+
</tr>
|
1263 |
+
<?php
|
1264 |
+
foreach ($updraftplus->backup_methods as $method => $description) {
|
1265 |
+
require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
1266 |
+
$call_method = "UpdraftPlus_BackupModule_$method";
|
1267 |
+
call_user_func(array($call_method, 'config_print'));
|
1268 |
+
}
|
1269 |
+
?>
|
1270 |
+
</table>
|
1271 |
+
<script type="text/javascript">
|
1272 |
+
/* <![CDATA[ */
|
1273 |
+
var lastlog_lastmessage = "";
|
1274 |
+
var lastlog_sdata = {
|
1275 |
+
action: 'updraft_ajax',
|
1276 |
+
subaction: 'lastlog',
|
1277 |
+
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
|
1278 |
+
};
|
1279 |
+
function updraft_showlastlog(){
|
1280 |
+
jQuery.get(ajaxurl, lastlog_sdata, function(response) {
|
1281 |
+
nexttimer = 1500;
|
1282 |
+
if (lastlog_lastmessage == response) { nexttimer = 4500; }
|
1283 |
+
setTimeout(function(){updraft_showlastlog()}, nexttimer);
|
1284 |
+
jQuery('#updraft_lastlogcontainer').html(response);
|
1285 |
+
lastlog_lastmessage = response;
|
1286 |
+
});
|
1287 |
+
}
|
1288 |
+
var lastbackup_sdata = {
|
1289 |
+
action: 'updraft_ajax',
|
1290 |
+
subaction: 'lastbackup',
|
1291 |
+
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
|
1292 |
+
};
|
1293 |
+
var lastbackup_laststatus = '<?php echo $last_backup_html?>'
|
1294 |
+
function updraft_showlastbackup(){
|
1295 |
+
jQuery.get(ajaxurl, lastbackup_sdata, function(response) {
|
1296 |
+
if (lastbackup_laststatus == response) {
|
1297 |
+
setTimeout(function(){updraft_showlastbackup()}, 7000);
|
1298 |
+
} else {
|
1299 |
+
jQuery('#updraft_last_backup').html(response);
|
1300 |
+
}
|
1301 |
+
lastbackup_laststatus = response;
|
1302 |
+
});
|
1303 |
+
}
|
1304 |
+
var updraft_historytimer = 0;
|
1305 |
+
var calculated_diskspace = 0;
|
1306 |
+
function updraft_historytimertoggle(forceon) {
|
1307 |
+
if (!updraft_historytimer || forceon == 1) {
|
1308 |
+
updraft_updatehistory(0);
|
1309 |
+
updraft_historytimer = setInterval(function(){updraft_updatehistory(0)}, 30000);
|
1310 |
+
if (!calculated_diskspace) {
|
1311 |
+
updraftplus_diskspace();
|
1312 |
+
calculated_diskspace=1;
|
1313 |
+
}
|
1314 |
+
} else {
|
1315 |
+
clearTimeout(updraft_historytimer);
|
1316 |
+
updraft_historytimer = 0;
|
1317 |
+
}
|
1318 |
+
}
|
1319 |
+
function updraft_updatehistory(rescan) {
|
1320 |
+
if (rescan == 1) {
|
1321 |
+
jQuery('#updraft_existing_backups').html('<p style="text-align:center;"><em>Rescanning (looking for backups that you have uploaded manually into the internal backup store)...</em></p>');
|
1322 |
+
}
|
1323 |
+
jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'historystatus', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>', rescan: rescan }, function(response) {
|
1324 |
+
jQuery('#updraft_existing_backups').html(response);
|
1325 |
+
});
|
1326 |
+
}
|
1327 |
+
|
1328 |
+
function updraft_check_same_times() {
|
1329 |
+
if (jQuery('#updraft_interval').val() == jQuery('#updraft_interval_database').val() && jQuery('#updraft_interval').val() != 'manual') {
|
1330 |
+
jQuery('#updraft_db_timings').css('opacity','0.25');
|
1331 |
+
} else {
|
1332 |
+
jQuery('#updraft_db_timings').css('opacity','1');
|
1333 |
+
}
|
1334 |
+
}
|
1335 |
+
|
1336 |
+
jQuery(document).ready(function() {
|
1337 |
+
|
1338 |
+
updraft_check_same_times();
|
1339 |
+
|
1340 |
+
jQuery( "#updraft-restore-modal" ).dialog({
|
1341 |
+
autoOpen: false, height: 385, width: 480, modal: true,
|
1342 |
+
buttons: {
|
1343 |
+
'<?php _e('Restore','updraftplus');?>': function() {
|
1344 |
+
var anyselected = 0;
|
1345 |
+
jQuery('input[name="updraft_restore[]"]').each(function(x,y){
|
1346 |
+
if (jQuery(y).is(':checked')) {
|
1347 |
+
anyselected = 1;
|
1348 |
+
//alert(jQuery(y).val());
|
1349 |
+
}
|
1350 |
+
});
|
1351 |
+
if (anyselected == 1) {
|
1352 |
+
jQuery('#updraft_restore_form').submit();
|
1353 |
+
} else {
|
1354 |
+
alert('You did not select any components to restore. Please select at least one, and then try again.');
|
1355 |
+
}
|
1356 |
+
},
|
1357 |
+
'<?php _e('Cancel','updraftplus');?>': function() { jQuery(this).dialog("close"); }
|
1358 |
+
}
|
1359 |
+
});
|
1360 |
+
|
1361 |
+
jQuery( "#updraft-backupnow-modal" ).dialog({
|
1362 |
+
autoOpen: false, height: 265, width: 375, modal: true,
|
1363 |
+
buttons: {
|
1364 |
+
'<?php _e('Backup Now','updraftplus');?>': function() {
|
1365 |
+
jQuery('#updraft-backupnow-form').submit();
|
1366 |
+
},
|
1367 |
+
'<?php _e('Cancel','updraftplus');?>': function() { jQuery(this).dialog("close"); }
|
1368 |
+
}
|
1369 |
+
});
|
1370 |
+
|
1371 |
+
jQuery('#enableexpertmode').click(function() {
|
1372 |
+
jQuery('.expertmode').fadeIn();
|
1373 |
+
return false;
|
1374 |
+
});
|
1375 |
+
<?php if (!@is_writable($updraft_dir)) echo "jQuery('.backupdirrow').show();\n"; ?>
|
1376 |
+
setTimeout(function(){updraft_showlastlog();}, 1200);
|
1377 |
+
jQuery('.updraftplusmethod').hide();
|
1378 |
+
<?php
|
1379 |
+
if ($active_service) echo "jQuery('.${active_service}').show();";
|
1380 |
+
foreach ($updraftplus->backup_methods as $method => $description) {
|
1381 |
+
// already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
1382 |
+
$call_method = "UpdraftPlus_BackupModule_$method";
|
1383 |
+
if (method_exists($call_method, 'config_print_javascript_onready')) call_user_func(array($call_method, 'config_print_javascript_onready'));
|
1384 |
+
}
|
1385 |
+
?>
|
1386 |
+
});
|
1387 |
+
/* ]]> */
|
1388 |
+
</script>
|
1389 |
+
<table class="form-table" style="width:900px;">
|
1390 |
+
<tr>
|
1391 |
+
<td colspan="2"><h2><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
|
1392 |
+
</tr>
|
1393 |
+
<tr>
|
1394 |
+
<th><?php _e('Debug mode','updraftplus');?>:</th>
|
1395 |
+
<td><input type="checkbox" id="updraft_debug_mode" name="updraft_debug_mode" value="1" <?php echo $debug_mode; ?> /> <br><label for="updraft_debug_mode"><?php _e('Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report.','updraftplus');?></label></td>
|
1396 |
+
</tr>
|
1397 |
+
<tr>
|
1398 |
+
<th><?php _e('Expert settings','updraftplus');?>:</th>
|
1399 |
+
<td><a id="enableexpertmode" href="#"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?> <?php do_action('updraftplus_expertsettingsdescription'); ?></td>
|
1400 |
+
</tr>
|
1401 |
+
<?php
|
1402 |
+
$delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
|
1403 |
+
?>
|
1404 |
+
|
1405 |
+
<tr class="deletelocal expertmode" style="display:none;">
|
1406 |
+
<th><?php _e('Delete local backup','updraftplus');?>:</th>
|
1407 |
+
<td><input type="checkbox" id="updraft_delete_local" name="updraft_delete_local" value="1" <?php if ($delete_local) echo 'checked="checked"'; ?>> <br><label for="updraft_delete_local"><?php _e('Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits).','updraftplus');?></label></td>
|
1408 |
+
</tr>
|
1409 |
+
|
1410 |
+
|
1411 |
+
<tr class="expertmode backupdirrow" style="display:none;">
|
1412 |
+
<th><?php _e('Backup directory','updraftplus');?>:</th>
|
1413 |
+
<td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
|
1414 |
+
</tr>
|
1415 |
+
<tr class="expertmode backupdirrow" style="display:none;">
|
1416 |
+
<td></td><td><?php
|
1417 |
+
|
1418 |
+
// Suppress warnings, since if the user is dumping warnings to screen, then invalid JavaScript results and the screen breaks.
|
1419 |
+
if(@is_writable($updraft_dir)) {
|
1420 |
+
$dir_info = '<span style="color:green">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
|
1421 |
+
} else {
|
1422 |
+
$dir_info = '<span style="color:red">'.__('Backup directory specified is <b>not</b> writable, or does not exist.','updraftplus').' <span style="font-size:110%;font-weight:bold"><a href="options-general.php?page=updraftplus&action=updraft_create_backup_dir">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" onclick="jQuery(\'#updraft_dir\').val(\''.WP_CONTENT_DIR.'/updraft\'); return false;">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
|
1423 |
+
}
|
1424 |
+
|
1425 |
+
echo $dir_info.' '.__("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...).",'updraftplus');?></td>
|
1426 |
+
</tr>
|
1427 |
+
|
1428 |
+
<tr class="expertmode" style="display:none;">
|
1429 |
+
<th><?php _e('Use the server\'s SSL certificates','updraftplus');?>:</th>
|
1430 |
+
<td><input type="checkbox" id="updraft_ssl_useservercerts" name="updraft_ssl_useservercerts" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_useservercerts"><?php _e('By default UpdraftPlus its own store of SSL certificates to verify the identity of remote sites (i.e. to make sure it is talking to the real Dropbox, Amazon S3, etc., and not an attacker). We keep these up to date. However, if you get an SSL error, then choosing this option (which causes UpdraftPlus to use your web server\'s collection instead) may help.','updraftplus');?></label></td>
|
1431 |
+
</tr>
|
1432 |
+
|
1433 |
+
<tr class="expertmode" style="display:none;">
|
1434 |
+
<th><?php _e('Do not verify SSL certificates','updraftplus');?>:</th>
|
1435 |
+
<td><input type="checkbox" id="updraft_ssl_disableverify" name="updraft_ssl_disableverify" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_disableverify"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from verifying the identity of encrypted sites that it connects to (e.g. Dropbox, Google Drive). It means that UpdraftPlus will be using SSL only for encryption of traffic, and not for authentication.','updraftplus');?> <?php _e('Note that not all cloud backup methods are necessarily using SSL authentication.', 'updraftplus');?></label></td>
|
1436 |
+
</tr>
|
1437 |
+
|
1438 |
+
<tr class="expertmode" style="display:none;">
|
1439 |
+
<th><?php _e('Disable SSL entirely where possible', 'updraftplus');?>:</th>
|
1440 |
+
<td><input type="checkbox" id="updraft_ssl_nossl" name="updraft_ssl_nossl" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_nossl"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from using SSL for authentication and encrypted transport at all, where possible. Note that some cloud storage providers do not allow this (e.g. Dropbox), so with those providers this setting will have no effect.','updraftplus');?> <a href="http://updraftplus.com/faqs/i-get-ssl-certificate-errors-when-backing-up-andor-restoring/">See this FAQ also.</a></label></td>
|
1441 |
+
</tr>
|
1442 |
+
|
1443 |
+
<?php do_action('updraftplus_configprint_expertoptions'); ?>
|
1444 |
+
|
1445 |
+
<tr>
|
1446 |
+
<td></td>
|
1447 |
+
<td>
|
1448 |
+
<?php
|
1449 |
+
$ws_ad = $updraftplus->wordshell_random_advert(1);
|
1450 |
+
if ($ws_ad) {
|
1451 |
+
?>
|
1452 |
+
<p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
|
1453 |
+
<?php echo $ws_ad; ?>
|
1454 |
+
</p>
|
1455 |
+
<?php
|
1456 |
+
}
|
1457 |
+
?>
|
1458 |
+
</td>
|
1459 |
+
</tr>
|
1460 |
+
<tr>
|
1461 |
+
<td></td>
|
1462 |
+
<td>
|
1463 |
+
<input type="hidden" name="action" value="update" />
|
1464 |
+
<input type="submit" class="button-primary" value="<?php _e('Save Changes','updraftplus');?>" />
|
1465 |
+
</td>
|
1466 |
+
</tr>
|
1467 |
+
</table>
|
1468 |
+
<?php
|
1469 |
+
}
|
1470 |
+
|
1471 |
+
function curl_check($service, $has_fallback = false) {
|
1472 |
+
// Check requirements
|
1473 |
+
if (!function_exists("curl_init")) {
|
1474 |
+
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php echo sprintf(__('Your web server\'s PHP installation does not included a required module (%s). Please contact your web hosting provider\'s support.', 'updraftplus'), 'Curl'); ?> <?php echo sprintf(__("UpdraftPlus's %s module <strong>requires</strong> Curl. Your only options to get this working are 1) Install/enable curl or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this.",'updraftplus'),$service);?></p><?php
|
1475 |
+
} else {
|
1476 |
+
$curl_version = curl_version();
|
1477 |
+
$curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
|
1478 |
+
if (!$curl_ssl_supported) {
|
1479 |
+
if ($has_fallback) {
|
1480 |
+
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php echo sprintf(__("Your web server's PHP/Curl installation does not support https access. Communications with %s will be unencrypted. ask your web host to install Curl/SSL in order to gain the ability for encryption (via an add-on).",'updraftplus'),$service);?></p><?php
|
1481 |
+
} else {
|
1482 |
+
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php echo sprintf(__("Your web server's PHP/Curl installation does not support https access. We cannot access %s without this support. Please contact your web hosting provider's support. %s <strong>requires</strong> Curl+https. Please do not file any support requests; there is no alternative.",'updraftplus'),$service);?></p><?php
|
1483 |
+
}
|
1484 |
+
} else {
|
1485 |
+
?><p><em><?php echo sprintf(__("Good news: Your site's communications with %s can be encrypted. If you see any errors to do with encryption, then look in the 'Expert Settings' for more help.", 'updraftplus'),$service);?></em></p><?php
|
1486 |
+
}
|
1487 |
+
}
|
1488 |
+
}
|
1489 |
+
|
1490 |
+
function recursive_directory_size($directory) {
|
1491 |
+
$size = 0;
|
1492 |
+
if(substr($directory,-1) == '/') $directory = substr($directory,0,-1);
|
1493 |
+
|
1494 |
+
if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
|
1495 |
+
|
1496 |
+
if($handle = opendir($directory)) {
|
1497 |
+
while(($file = readdir($handle)) !== false) {
|
1498 |
+
$path = $directory.'/'.$file;
|
1499 |
+
if($file != '.' && $file != '..') {
|
1500 |
+
if(is_file($path)) {
|
1501 |
+
$size += filesize($path);
|
1502 |
+
} elseif(is_dir($path)) {
|
1503 |
+
$handlesize = $this->recursive_directory_size($path);
|
1504 |
+
if($handlesize >= 0) { $size += $handlesize; } else { return -1; }
|
1505 |
+
}
|
1506 |
+
}
|
1507 |
+
}
|
1508 |
+
closedir($handle);
|
1509 |
+
}
|
1510 |
+
if ($size > 1073741824) {
|
1511 |
+
return round($size / 1073741824, 1).' Gb';
|
1512 |
+
} elseif ($size > 1048576) {
|
1513 |
+
return round($size / 1048576, 1).' Mb';
|
1514 |
+
} elseif ($size > 1024) {
|
1515 |
+
return round($size / 1024, 1).' Kb';
|
1516 |
+
} else {
|
1517 |
+
return round($size, 1).' b';
|
1518 |
+
}
|
1519 |
+
}
|
1520 |
+
|
1521 |
+
function existing_backup_table($backup_history = false) {
|
1522 |
+
|
1523 |
+
global $updraftplus;
|
1524 |
+
|
1525 |
+
// Fetch it if it was not passed
|
1526 |
+
if ($backup_history === false) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
1527 |
+
if (!is_array($backup_history)) $backup_history=array();
|
1528 |
+
|
1529 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
1530 |
+
|
1531 |
+
$backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
|
1532 |
+
|
1533 |
+
echo '<table>';
|
1534 |
+
|
1535 |
+
krsort($backup_history);
|
1536 |
+
|
1537 |
+
foreach($backup_history as $key=>$value) {
|
1538 |
+
$pretty_date = date('Y-m-d G:i',$key);
|
1539 |
+
$entities = '';
|
1540 |
+
?>
|
1541 |
+
<tr>
|
1542 |
+
<td><b><?php echo $pretty_date?></b></td>
|
1543 |
+
<td>
|
1544 |
+
<?php if (isset($value['db'])) {
|
1545 |
+
$entities .= '/db/';
|
1546 |
+
$sdescrip = preg_replace('/ \(.*\)$/', '', __('Database','updraftplus'));
|
1547 |
+
?>
|
1548 |
+
<form id="uddownloadform_db_<?php echo $key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', <?php echo $key;?>, 'db')" method="post">
|
1549 |
+
<?php wp_nonce_field('updraftplus_download'); ?>
|
1550 |
+
<input type="hidden" name="action" value="updraft_download_backup" />
|
1551 |
+
<input type="hidden" name="type" value="db" />
|
1552 |
+
<input type="hidden" name="timestamp" value="<?php echo $key?>" />
|
1553 |
+
<input type="submit" value="<?php _e('Database','updraftplus');?>" />
|
1554 |
+
</form>
|
1555 |
+
<?php } else { echo "(No database)"; } ?>
|
1556 |
+
</td>
|
1557 |
+
|
1558 |
+
<?php
|
1559 |
+
foreach ($backupable_entities as $type => $info) {
|
1560 |
+
echo '<td>';
|
1561 |
+
if (isset($value[$type])) {
|
1562 |
+
$entities .= '/'.$type.'/';
|
1563 |
+
$sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
|
1564 |
+
?>
|
1565 |
+
<form id="uddownloadform_<?php echo $type.'_'.$key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', '<?php echo $key."', '".$type;?>')" method="post">
|
1566 |
+
<?php wp_nonce_field('updraftplus_download'); ?>
|
1567 |
+
<input type="hidden" name="action" value="updraft_download_backup" />
|
1568 |
+
<input type="hidden" name="type" value="<?php echo $type; ?>" />
|
1569 |
+
<input type="hidden" name="timestamp" value="<?php echo $key?>" />
|
1570 |
+
<input type="submit" title="<?php echo __('Press here to download','updraftplus').' '.strtolower($info['description']); ?>" value="<?php echo $sdescrip;?>" />
|
1571 |
+
</form>
|
1572 |
+
<?php } else { printf(_x('(No %s)','Message shown when no such object is available','updraftplus'), preg_replace('/\s\(.{12,}\)/', '', strtolower($info['description']))); } ?>
|
1573 |
+
</td>
|
1574 |
+
<?php }; ?>
|
1575 |
+
|
1576 |
+
<td>
|
1577 |
+
<?php if (isset($value['nonce']) && preg_match("/^[0-9a-f]{12}$/",$value['nonce']) && is_readable($updraft_dir.'/log.'.$value['nonce'].'.txt')) { ?>
|
1578 |
+
<form action="options-general.php" method="get">
|
1579 |
+
<input type="hidden" name="action" value="downloadlog" />
|
1580 |
+
<input type="hidden" name="page" value="updraftplus" />
|
1581 |
+
<input type="hidden" name="updraftplus_backup_nonce" value="<?php echo $value['nonce']; ?>" />
|
1582 |
+
<input type="submit" value="<?php _e('Backup Log','updraftplus');?>" />
|
1583 |
+
</form>
|
1584 |
+
<?php } else { echo "(No backup log)"; } ?>
|
1585 |
+
</td>
|
1586 |
+
<td>
|
1587 |
+
<form method="post" action="">
|
1588 |
+
<input type="hidden" name="backup_timestamp" value="<?php echo $key;?>">
|
1589 |
+
<input type="hidden" name="action" value="updraft_restore" />
|
1590 |
+
<?php if ($entities) { ?><button title="<?php _e('After pressing this button, you will be given the option to choose which components you wish to restore','updraftplus');?>" type="button" <?php echo $restore_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:16px !important; min-height:26px;" onclick="updraft_restore_options('<?php echo $entities;?>'); jQuery('#updraft_restore_timestamp').val('<?php echo $key;?>'); jQuery('#updraft_restore_date').html('<?php echo $pretty_date;?>'); jQuery('#updraft-restore-modal').dialog('open');"><?php _e('Restore','updraftplus');?></button><?php } ?>
|
1591 |
+
</form>
|
1592 |
+
</td>
|
1593 |
+
</tr>
|
1594 |
+
<script>
|
1595 |
+
function updraft_restore_options(entities) {
|
1596 |
+
jQuery('input[name="updraft_restore[]"]').each(function(x,y){
|
1597 |
+
var entity = jQuery(y).val();
|
1598 |
+
if (entities.indexOf('/'+entity+'/') != -1) {
|
1599 |
+
jQuery(y).removeAttr('disabled').parent().show();
|
1600 |
+
} else {
|
1601 |
+
jQuery(y).attr('disabled','disabled').parent().hide();
|
1602 |
+
}
|
1603 |
+
});
|
1604 |
+
}
|
1605 |
+
</script>
|
1606 |
+
<?php }
|
1607 |
+
echo '</table>';
|
1608 |
+
}
|
1609 |
+
|
1610 |
+
// This function examines inside the updraft directory to see if any new archives have been uploaded. If so, it adds them to the backup set. (No removal of items from the backup set is done)
|
1611 |
+
function rebuild_backup_history() {
|
1612 |
+
|
1613 |
+
global $updraftplus;
|
1614 |
+
|
1615 |
+
$known_files = array();
|
1616 |
+
$known_nonces = array();
|
1617 |
+
$changes = false;
|
1618 |
+
|
1619 |
+
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
1620 |
+
if (!is_array($backup_history)) $backup_history = array();
|
1621 |
+
|
1622 |
+
// Accumulate a list of known files
|
1623 |
+
foreach ($backup_history as $btime => $bdata) {
|
1624 |
+
foreach ($bdata as $key => $value) {
|
1625 |
+
// Record which set this file is found in
|
1626 |
+
if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz|gz\.crypt)$/i', $value, $matches)) {
|
1627 |
+
$nonce = $matches[2];
|
1628 |
+
$known_files[$value] = $nonce;
|
1629 |
+
$known_nonces[$nonce] = $btime;
|
1630 |
+
}
|
1631 |
+
}
|
1632 |
+
}
|
1633 |
+
|
1634 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
1635 |
+
|
1636 |
+
if (!is_dir($updraft_dir)) return;
|
1637 |
+
|
1638 |
+
if (!$handle = opendir($updraft_dir)) return;
|
1639 |
+
|
1640 |
+
while (false !== ($entry = readdir($handle))) {
|
1641 |
+
if ($entry != "." && $entry != "..") {
|
1642 |
+
if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)\.(zip|gz|gz\.crypt)$/i', $entry, $matches)) {
|
1643 |
+
$btime = strtotime($matches[1]);
|
1644 |
+
if ($btime > 100) {
|
1645 |
+
if (!isset($known_files[$entry])) {
|
1646 |
+
$changes = true;
|
1647 |
+
$nonce = $matches[2];
|
1648 |
+
$type = $matches[3];
|
1649 |
+
// The time from the filename does not include seconds. Need to identify the seconds to get the right time
|
1650 |
+
if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
|
1651 |
+
if (!isset($backup_history[$btime])) $backup_history[$btime] = array();
|
1652 |
+
$backup_history[$btime][$type] = $entry;
|
1653 |
+
$backup_history[$btime][$type.'-size'] = filesize($updraft_dir.'/'.$entry);
|
1654 |
+
$backup_history[$btime]['nonce'] = $nonce;
|
1655 |
+
}
|
1656 |
+
}
|
1657 |
+
}
|
1658 |
+
}
|
1659 |
+
}
|
1660 |
+
|
1661 |
+
|
1662 |
+
if ($changes) UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backup_history);
|
1663 |
+
|
1664 |
+
}
|
1665 |
+
|
1666 |
+
function restore_backup($timestamp) {
|
1667 |
+
|
1668 |
+
@set_time_limit(900);
|
1669 |
+
|
1670 |
+
global $wp_filesystem, $updraftplus;
|
1671 |
+
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
1672 |
+
if(!is_array($backup_history[$timestamp])) {
|
1673 |
+
echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
|
1674 |
+
return false;
|
1675 |
+
}
|
1676 |
+
|
1677 |
+
$credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp");
|
1678 |
+
WP_Filesystem($credentials);
|
1679 |
+
if ( $wp_filesystem->errors->get_error_code() ) {
|
1680 |
+
foreach ( $wp_filesystem->errors->get_error_messages() as $message )
|
1681 |
+
show_message($message);
|
1682 |
+
exit;
|
1683 |
+
}
|
1684 |
+
|
1685 |
+
//if we make it this far then WP_Filesystem has been instantiated and is functional (tested with ftpext, what about suPHP and other situations where direct may work?)
|
1686 |
+
echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
|
1687 |
+
|
1688 |
+
$updraft_dir = $updraftplus->backups_dir_location().'/';
|
1689 |
+
|
1690 |
+
$service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
|
1691 |
+
|
1692 |
+
if (!isset($_POST['updraft_restore']) || !is_array($_POST['updraft_restore'])) {
|
1693 |
+
echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
|
1694 |
+
return false;
|
1695 |
+
}
|
1696 |
+
|
1697 |
+
$entities_to_restore = array_flip($_POST['updraft_restore']);
|
1698 |
+
|
1699 |
+
$backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
|
1700 |
+
|
1701 |
+
foreach($backup_history[$timestamp] as $type => $file) {
|
1702 |
+
// All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
|
1703 |
+
|
1704 |
+
if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
|
1705 |
+
|
1706 |
+
if ($type == 'db') {
|
1707 |
+
echo "<h2>".__('Database','updraftplus')."</h2>";
|
1708 |
+
} else {
|
1709 |
+
echo "<h2>".$backupable_entities[$type]['description']."</h2>";
|
1710 |
+
}
|
1711 |
+
|
1712 |
+
if (!isset($entities_to_restore[$type])) {
|
1713 |
+
echo "<p>$type: ".__('This component was not selected for restoration - skipping.', 'updraftplus')."</p>";
|
1714 |
+
continue;
|
1715 |
+
}
|
1716 |
+
|
1717 |
+
$fullpath = $updraft_dir.$file;
|
1718 |
+
|
1719 |
+
echo "Looking for $type archive: file name: ".htmlspecialchars($file)."<br>";
|
1720 |
+
if(!is_readable($fullpath)) {
|
1721 |
+
echo __("File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)",'updraftplus')."<br>";
|
1722 |
+
$this->download_file($file, $service);
|
1723 |
+
}
|
1724 |
+
// If a file size is stored in the backup data, then verify correctness of the local file
|
1725 |
+
if (isset($backup_history[$timestamp][$type.'-size'])) {
|
1726 |
+
$fs = $backup_history[$timestamp][$type.'-size'];
|
1727 |
+
echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024)." Kb: ";
|
1728 |
+
$as = @filesize($fullpath);
|
1729 |
+
if ($as == $fs) {
|
1730 |
+
echo "OK<br>";
|
1731 |
+
} else {
|
1732 |
+
echo "<strong>".__('ERROR','updraftplus').":</strong> is size: ".round($as/1024)." ($fs, $as)<br>";
|
1733 |
+
}
|
1734 |
+
} else {
|
1735 |
+
echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
|
1736 |
+
}
|
1737 |
+
# Types: uploads, themes, plugins, others, db
|
1738 |
+
if(is_readable($fullpath)) {
|
1739 |
+
|
1740 |
+
if(!class_exists('WP_Upgrader')) require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
|
1741 |
+
require_once(UPDRAFTPLUS_DIR.'/includes/updraft-restorer.php');
|
1742 |
+
$restorer = new Updraft_Restorer();
|
1743 |
+
$val = $restorer->restore_backup($fullpath, $type, $service, $backupable_entities[$type]);
|
1744 |
+
|
1745 |
+
if(is_wp_error($val)) {
|
1746 |
+
foreach ($val->get_error_messages() as $msg) {
|
1747 |
+
echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
|
1748 |
+
}
|
1749 |
+
echo '</div>'; //close the updraft_restore_progress div even if we error
|
1750 |
+
return false;
|
1751 |
+
}
|
1752 |
+
} else {
|
1753 |
+
$updraftplus->error("$file: ".__('Could not find one of the files for restoration', 'updraftplus'));
|
1754 |
+
echo __('Could not find one of the files for restoration', 'updraftplus').": ($file)";
|
1755 |
+
}
|
1756 |
+
}
|
1757 |
+
echo '</div>'; //close the updraft_restore_progress div
|
1758 |
+
return true;
|
1759 |
+
}
|
1760 |
+
|
1761 |
+
|
1762 |
+
|
1763 |
+
}
|
1764 |
+
|
1765 |
+
?>
|
backup.php
ADDED
@@ -0,0 +1,314 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (!defined ('ABSPATH')) die ('No direct access allowed');
|
4 |
+
|
5 |
+
// This file contains functions moved out of updraftplus.php that are only needed when a backup is running (reduce memory usage on other site pages)
|
6 |
+
|
7 |
+
global $updraftplus_backup;
|
8 |
+
$updraftplus_backup = new UpdraftPlus_Backup();
|
9 |
+
if (defined('UPDRAFTPLUS_PREFERPCLZIP') && UPDRAFTPLUS_PREFERPCLZIP == true) $updraftplus_backup->zip_preferpcl = true;
|
10 |
+
|
11 |
+
class UpdraftPlus_Backup {
|
12 |
+
|
13 |
+
var $zipfiles_added;
|
14 |
+
var $zipfiles_existingfiles;
|
15 |
+
var $zipfiles_dirbatched;
|
16 |
+
var $zipfiles_batched;
|
17 |
+
|
18 |
+
var $zipfiles_lastwritetime;
|
19 |
+
|
20 |
+
var $zip_preferpcl = false;
|
21 |
+
|
22 |
+
// This function recursively packs the zip, dereferencing symlinks but packing into a single-parent tree for universal unpacking
|
23 |
+
function makezip_recursive_add($zipfile, $fullpath, $use_path_when_storing, $original_fullpath) {
|
24 |
+
|
25 |
+
global $updraftplus;
|
26 |
+
|
27 |
+
// De-reference
|
28 |
+
$fullpath = realpath($fullpath);
|
29 |
+
|
30 |
+
// Is the place we've ended up above the original base? That leads to infinite recursion
|
31 |
+
if (($fullpath !== $original_fullpath && strpos($original_fullpath, $fullpath) === 0) || ($original_fullpath == $fullpath && strpos($use_path_when_storing, '/') !== false) ) {
|
32 |
+
$updraftplus->log("Infinite recursion: symlink lead us to $fullpath, which is within $original_fullpath");
|
33 |
+
$updraftplus->error(__("Infinite recursion: consult your log for more information",'updraftplus'));
|
34 |
+
return false;
|
35 |
+
}
|
36 |
+
|
37 |
+
if(is_file($fullpath)) {
|
38 |
+
if (is_readable($fullpath)) {
|
39 |
+
$key = ($fullpath == $original_fullpath) ? basename($fullpath) : $use_path_when_storing.'/'.basename($fullpath);
|
40 |
+
$this->zipfiles_batched[$fullpath] = $key;
|
41 |
+
@touch($zipfile);
|
42 |
+
} else {
|
43 |
+
$updraftplus->log("$fullpath: unreadable file");
|
44 |
+
$updraftplus->error("$fullpath: unreadable file");
|
45 |
+
}
|
46 |
+
} elseif (is_dir($fullpath)) {
|
47 |
+
if (!isset($this->existing_files[$use_path_when_storing])) $this->zipfiles_dirbatched[] = $use_path_when_storing;
|
48 |
+
if (!$dir_handle = @opendir($fullpath)) {
|
49 |
+
$updraftplus->log("Failed to open directory: $fullpath");
|
50 |
+
$updraftplus->error("Failed to open directory: $fullpath");
|
51 |
+
return;
|
52 |
+
}
|
53 |
+
while ($e = readdir($dir_handle)) {
|
54 |
+
if ($e != '.' && $e != '..') {
|
55 |
+
if (is_link($fullpath.'/'.$e)) {
|
56 |
+
$deref = realpath($fullpath.'/'.$e);
|
57 |
+
if (is_file($deref)) {
|
58 |
+
if (is_readable($deref)) {
|
59 |
+
$this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
|
60 |
+
@touch($zipfile);
|
61 |
+
} else {
|
62 |
+
$updraftplus->log("$deref: unreadable file");
|
63 |
+
$updraftplus->error("$deref: unreadable file");
|
64 |
+
}
|
65 |
+
} elseif (is_dir($deref)) {
|
66 |
+
$this->makezip_recursive_add($zipfile, $deref, $use_path_when_storing.'/'.$e, $original_fullpath);
|
67 |
+
}
|
68 |
+
} elseif (is_file($fullpath.'/'.$e)) {
|
69 |
+
if (is_readable($fullpath.'/'.$e)) {
|
70 |
+
$this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
|
71 |
+
@touch($zipfile);
|
72 |
+
} else {
|
73 |
+
$updraftplus->log("$fullpath/$e: unreadable file");
|
74 |
+
$updraftplus->error("$fullpath/$e: unreadable file");
|
75 |
+
}
|
76 |
+
} elseif (is_dir($fullpath.'/'.$e)) {
|
77 |
+
// no need to addEmptyDir here, as it gets done when we recurse
|
78 |
+
$this->makezip_recursive_add($zipfile, $fullpath.'/'.$e, $use_path_when_storing.'/'.$e, $original_fullpath);
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
closedir($dir_handle);
|
83 |
+
}
|
84 |
+
|
85 |
+
// We don't want to touch the zip file on every single file, so we batch them up
|
86 |
+
// We go every 25 files, because if you wait too much longer, the contents may have changed from under you
|
87 |
+
// And for some redundancy (redundant because of the touches going on anyway), we try to touch the file after 20 seconds, to help with the "recently modified" check on resumption (we saw a case where the file went for 155 seconds without being touched and so the other runner was not detected)
|
88 |
+
if (count($this->zipfiles_batched) > 25 || (file_exists($zipfile) && ((time()-filemtime($zipfile)) > 20) )) {
|
89 |
+
$ret = $this->makezip_addfiles($zipfile);
|
90 |
+
} else {
|
91 |
+
$ret = true;
|
92 |
+
}
|
93 |
+
|
94 |
+
return $ret;
|
95 |
+
|
96 |
+
}
|
97 |
+
|
98 |
+
// Caution: $source is allowed to be an array, not just a filename
|
99 |
+
function make_zipfile($source, $destination) {
|
100 |
+
|
101 |
+
global $updraftplus;
|
102 |
+
|
103 |
+
// When to prefer PCL:
|
104 |
+
// - We were asked to
|
105 |
+
// - No zip extension present and no relevant method present
|
106 |
+
// The zip extension check is not redundant, because method_exists segfaults some PHP installs, leading to support requests
|
107 |
+
|
108 |
+
// Fallback to PclZip - which my tests show is 25% slower (and we can't resume)
|
109 |
+
if ($this->zip_preferpcl || (!extension_loaded('zip') && !method_exists('ZipArchive', 'AddFile'))) {
|
110 |
+
if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
|
111 |
+
$zip_object = new PclZip($destination);
|
112 |
+
$zipcode = $zip_object->create($source, PCLZIP_OPT_REMOVE_PATH, WP_CONTENT_DIR);
|
113 |
+
if ($zipcode == 0 ) {
|
114 |
+
$updraftplus->log("PclZip Error: ".$zip_object->errorName());
|
115 |
+
return $zip_object->errorCode();
|
116 |
+
} else {
|
117 |
+
return true;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
$this->existing_files = array();
|
122 |
+
|
123 |
+
// If the file exists, then we should grab its index of files inside, and sizes
|
124 |
+
// Then, when we come to write a file, we should check if it's already there, and only add if it is not
|
125 |
+
if (file_exists($destination) && is_readable($destination)) {
|
126 |
+
$zip = new ZipArchive;
|
127 |
+
$zip->open($destination);
|
128 |
+
$updraftplus->log(basename($destination).": Zip file already exists, with ".$zip->numFiles." files");
|
129 |
+
for ($i=0; $i<$zip->numFiles; $i++) {
|
130 |
+
$si = $zip->statIndex($i);
|
131 |
+
$name = $si['name'];
|
132 |
+
$this->existing_files[$name] = $si['size'];
|
133 |
+
}
|
134 |
+
} elseif (file_exists($destination)) {
|
135 |
+
$updraftplus->log("Zip file already exists, but is not readable; will remove: $destination");
|
136 |
+
@unlink($destination);
|
137 |
+
}
|
138 |
+
|
139 |
+
$this->zipfiles_added = 0;
|
140 |
+
$this->zipfiles_dirbatched = array();
|
141 |
+
$this->zipfiles_batched = array();
|
142 |
+
$this->zipfiles_lastwritetime = time();
|
143 |
+
|
144 |
+
// Magic value, used later to detect no error occurring
|
145 |
+
$last_error = 2349864;
|
146 |
+
if (is_array($source)) {
|
147 |
+
foreach ($source as $element) {
|
148 |
+
$howmany = $this->makezip_recursive_add($destination, $element, basename($element), $element);
|
149 |
+
if ($howmany < 0) {
|
150 |
+
$last_error = $howmany;
|
151 |
+
}
|
152 |
+
}
|
153 |
+
} else {
|
154 |
+
$howmany = $this->makezip_recursive_add($destination, $source, basename($source), $source);
|
155 |
+
if ($howmany < 0) {
|
156 |
+
$last_error = $howmany;
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
// Any not yet dispatched?
|
161 |
+
if (count($this->zipfiles_dirbatched)>0 || count($this->zipfiles_batched)>0) {
|
162 |
+
$howmany = $this->makezip_addfiles($destination);
|
163 |
+
if ($howmany < 0) {
|
164 |
+
$last_error = $howmany;
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
if ($this->zipfiles_added > 0 || $last_error == 2349864) {
|
169 |
+
// ZipArchive::addFile sometimes fails
|
170 |
+
if (filesize($destination) < 100) {
|
171 |
+
// Retry with PclZip
|
172 |
+
$updraftplus->log("Zip::addFile apparently failed - retrying with PclZip");
|
173 |
+
$this->zip_preferpcl = true;
|
174 |
+
return $this->make_zipfile($source, $destination);
|
175 |
+
}
|
176 |
+
return true;
|
177 |
+
} else {
|
178 |
+
return $last_error;
|
179 |
+
}
|
180 |
+
|
181 |
+
}
|
182 |
+
|
183 |
+
// Q. Why don't we only open and close the zip file just once?
|
184 |
+
// A. Because apparently PHP doesn't write out until the final close, and it will return an error if anything file has vanished in the meantime. So going directory-by-directory reduces our chances of hitting an error if the filesystem is changing underneath us (which is very possible if dealing with e.g. 1Gb of files)
|
185 |
+
|
186 |
+
// We batch up the files, rather than do them one at a time. So we are more efficient than open,one-write,close.
|
187 |
+
function makezip_addfiles($zipfile) {
|
188 |
+
|
189 |
+
global $updraftplus;
|
190 |
+
|
191 |
+
// Short-circuit the null case, because we want to detect later if something useful happenned
|
192 |
+
if (count($this->zipfiles_dirbatched) == 0 && count($this->zipfiles_batched) == 0) return true;
|
193 |
+
|
194 |
+
// 05-Mar-2013 - added a new check on the total data added; it appears that things fall over if too much data is contained in the cumulative total of files that were addFile'd without a close-open cycle; presumably data is being stored in memory. In the case in question, it was a batch of MP3 files of around 100Mb each - 25 of those equals 2.5Gb!
|
195 |
+
|
196 |
+
$data_added_since_reopen = 0;
|
197 |
+
|
198 |
+
$zip = new ZipArchive();
|
199 |
+
if (file_exists($zipfile)) {
|
200 |
+
$opencode = $zip->open($zipfile);
|
201 |
+
$original_size = filesize($zipfile);
|
202 |
+
clearstatcache();
|
203 |
+
} else {
|
204 |
+
$opencode = $zip->open($zipfile, ZIPARCHIVE::CREATE);
|
205 |
+
$original_size = 0;
|
206 |
+
}
|
207 |
+
|
208 |
+
if ($opencode !== true) return array($opencode, 0);
|
209 |
+
// Make sure all directories are created before we start creating files
|
210 |
+
while ($dir = array_pop($this->zipfiles_dirbatched)) {
|
211 |
+
$zip->addEmptyDir($dir);
|
212 |
+
}
|
213 |
+
foreach ($this->zipfiles_batched as $file => $add_as) {
|
214 |
+
$fsize = filesize($file);
|
215 |
+
if (!isset($this->existing_files[$add_as]) || $this->existing_files[$add_as] != $fsize) {
|
216 |
+
|
217 |
+
@touch($zipfile);
|
218 |
+
$zip->addFile($file, $add_as);
|
219 |
+
|
220 |
+
$data_added_since_reopen += $fsize;
|
221 |
+
# 25Mb - force a write-out and re-open
|
222 |
+
if ($data_added_since_reopen > 26214400 || (time() - $this->zipfiles_lastwritetime) > 2) {
|
223 |
+
|
224 |
+
$before_size = filesize($zipfile);
|
225 |
+
clearstatcache();
|
226 |
+
|
227 |
+
if ($data_added_since_reopen > 26214400) {
|
228 |
+
$updraftplus->log("Adding batch to zip file: over 25Mb added on this batch (".round($data_added_since_reopen/1048576,1)." Mb); re-opening (prior size: ".round($before_size/1024,1).' Kb)');
|
229 |
+
} else {
|
230 |
+
$updraftplus->log("Adding batch to zip file: over 2 seconds have passed since the last write (".round($data_added_since_reopen/1048576,1)." Mb); re-opening (prior size: ".round($before_size/1024,1).' Kb)');
|
231 |
+
}
|
232 |
+
if (!$zip->close()) {
|
233 |
+
$updraftplus->log("zip::Close returned an error");
|
234 |
+
}
|
235 |
+
unset($zip);
|
236 |
+
$zip = new ZipArchive();
|
237 |
+
$opencode = $zip->open($zipfile);
|
238 |
+
if ($opencode !== true) return array($opencode, 0);
|
239 |
+
$data_added_since_reopen = 0;
|
240 |
+
$this->zipfiles_lastwritetime = time();
|
241 |
+
// Call here, in case we've got so many big files that we don't complete the whole routine
|
242 |
+
if (filesize($zipfile) > $before_size) $updraftplus->something_useful_happened();
|
243 |
+
clearstatcache();
|
244 |
+
}
|
245 |
+
}
|
246 |
+
$this->zipfiles_added++;
|
247 |
+
// Don't call something_useful_happened() here - nothing necessarily happens until close() is called
|
248 |
+
if ($this->zipfiles_added % 100 == 0) $updraftplus->log("Zip: ".basename($zipfile).": ".$this->zipfiles_added." files added (on-disk size: ".round(filesize($zipfile)/1024,1)." Kb, lwt=".round(time() - $this->zipfiles_lastwritetime,1)."s)");
|
249 |
+
}
|
250 |
+
// Reset the array
|
251 |
+
$this->zipfiles_batched = array();
|
252 |
+
$ret = $zip->close();
|
253 |
+
$this->zipfiles_lastwritetime = time();
|
254 |
+
if (filesize($zipfile) > $original_size) $updraftplus->something_useful_happened();
|
255 |
+
clearstatcache();
|
256 |
+
return $ret;
|
257 |
+
}
|
258 |
+
|
259 |
+
function create_zip($create_from_dir, $whichone, $create_in_dir, $backup_file_basename) {
|
260 |
+
// Note: $create_from_dir can be an array or a string
|
261 |
+
@set_time_limit(900);
|
262 |
+
|
263 |
+
global $updraftplus;
|
264 |
+
|
265 |
+
if ($whichone != "others") $updraftplus->log("Beginning creation of dump of $whichone");
|
266 |
+
|
267 |
+
$full_path = $create_in_dir.'/'.$backup_file_basename.'-'.$whichone.'.zip';
|
268 |
+
$time_now = time();
|
269 |
+
|
270 |
+
if (file_exists($full_path)) {
|
271 |
+
$updraftplus->log("$backup_file_basename-$whichone.zip: this file has already been created");
|
272 |
+
$time_mod = (int)@filemtime($full_path);
|
273 |
+
if ($time_mod>100 && ($time_now-$time_mod)<30) {
|
274 |
+
$updraftplus->log("Terminate: the zip $full_path already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=".filesize($full_path)."). This likely means that another UpdraftPlus run is still at work; so we will exit.");
|
275 |
+
$updraftplus->increase_resume_and_reschedule(120);
|
276 |
+
die;
|
277 |
+
}
|
278 |
+
return basename($full_path);
|
279 |
+
}
|
280 |
+
|
281 |
+
// Temporary file, to be able to detect actual completion (upon which, it is renamed)
|
282 |
+
|
283 |
+
// Firstly, make sure that the temporary file is not already being written to - which can happen if a resumption takes place whilst an old run is still active
|
284 |
+
$zip_name = $full_path.'.tmp';
|
285 |
+
$time_mod = (int)@filemtime($zip_name);
|
286 |
+
if (file_exists($zip_name) && $time_mod>100 && ($time_now-$time_mod)<30) {
|
287 |
+
$file_size = filesize($zip_name);
|
288 |
+
$updraftplus->log("Terminate: the temporary file $zip_name already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=$file_size). This likely means that another UpdraftPlus run is still at work; so we will exit.");
|
289 |
+
$updraftplus->increase_resume_and_reschedule(120);
|
290 |
+
die;
|
291 |
+
} elseif (file_exists($zip_name)) {
|
292 |
+
$updraftplus->log("File exists ($zip_name), but was apparently not modified within the last 30 seconds, so we assume that any previous run has now terminated (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).")");
|
293 |
+
}
|
294 |
+
|
295 |
+
$microtime_start = microtime(true);
|
296 |
+
# The paths in the zip should then begin with '$whichone', having removed WP_CONTENT_DIR from the front
|
297 |
+
$zipcode = $this->make_zipfile($create_from_dir, $zip_name);
|
298 |
+
if ($zipcode !== true) {
|
299 |
+
$updraftplus->log("ERROR: Zip failure: Could not create $whichone zip: code=$zipcode");
|
300 |
+
$updraftplus->error(sprintf(__("Could not create %s zip. Consult the log file for more information.",'updraftplus'),$whichone));
|
301 |
+
return false;
|
302 |
+
} else {
|
303 |
+
rename($full_path.'.tmp', $full_path);
|
304 |
+
$timetaken = max(microtime(true)-$microtime_start, 0.000001);
|
305 |
+
$kbsize = filesize($full_path)/1024;
|
306 |
+
$rate = round($kbsize/$timetaken, 1);
|
307 |
+
$updraftplus->log("Created $whichone zip - file size is ".round($kbsize,1)." Kb in ".round($timetaken,1)." s ($rate Kb/s)");
|
308 |
+
}
|
309 |
+
|
310 |
+
return basename($full_path);
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
}
|
example-decrypt.php
CHANGED
@@ -27,13 +27,11 @@ function rijndael_decrypt_file($file, $key) {
|
|
27 |
require_once(dirname(__FILE__).'/includes/phpseclib/Crypt/Rijndael.php');
|
28 |
|
29 |
$rijndael = new Crypt_Rijndael();
|
|
|
30 |
$rijndael->setKey($key);
|
31 |
-
|
32 |
-
$ciphertext =
|
33 |
-
|
34 |
-
$ciphertext .= fread($in_handle, 16384);
|
35 |
-
}
|
36 |
-
fclose ($in_handle);
|
37 |
print $rijndael->decrypt($ciphertext);
|
38 |
|
39 |
}
|
27 |
require_once(dirname(__FILE__).'/includes/phpseclib/Crypt/Rijndael.php');
|
28 |
|
29 |
$rijndael = new Crypt_Rijndael();
|
30 |
+
|
31 |
$rijndael->setKey($key);
|
32 |
+
|
33 |
+
$ciphertext = file_get_contents($file);
|
34 |
+
|
|
|
|
|
|
|
35 |
print $rijndael->decrypt($ciphertext);
|
36 |
|
37 |
}
|
images/rackspacecloud-logo.png
ADDED
Binary file
|
includes/Dropbox/OAuth/Consumer/Curl.php
CHANGED
@@ -15,7 +15,6 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
15 |
* @var array
|
16 |
*/
|
17 |
private $defaultOptions = array(
|
18 |
-
CURLOPT_SSL_VERIFYPEER => true,
|
19 |
CURLOPT_VERBOSE => true,
|
20 |
CURLOPT_HEADER => true,
|
21 |
CURLINFO_HEADER_OUT => false,
|
@@ -63,7 +62,14 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
63 |
|
64 |
// Get the default options array
|
65 |
$options = $this->defaultOptions;
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
if ($method == 'GET' && $this->outFile) { // GET
|
69 |
$options[CURLOPT_RETURNTRANSFER] = false;
|
15 |
* @var array
|
16 |
*/
|
17 |
private $defaultOptions = array(
|
|
|
18 |
CURLOPT_VERBOSE => true,
|
19 |
CURLOPT_HEADER => true,
|
20 |
CURLINFO_HEADER_OUT => false,
|
62 |
|
63 |
// Get the default options array
|
64 |
$options = $this->defaultOptions;
|
65 |
+
if (!UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) {
|
66 |
+
$options[CURLOPT_CAINFO] = UPDRAFTPLUS_DIR.'/includes/ca-bundle.pem';
|
67 |
+
}
|
68 |
+
if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) {
|
69 |
+
$options[CURLOPT_SSL_VERIFYPEER] = false;
|
70 |
+
} else {
|
71 |
+
$options[CURLOPT_SSL_VERIFYPEER] = true;
|
72 |
+
}
|
73 |
|
74 |
if ($method == 'GET' && $this->outFile) { // GET
|
75 |
$options[CURLOPT_RETURNTRANSFER] = false;
|
includes/S3.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* $Id$
|
4 |
*
|
5 |
* Copyright (c) 2011, Donovan Schönknecht. All rights reserved.
|
6 |
-
* Portions copyright (c) 2012, David Anderson (http://www.simbahosting.co.uk). All rights reserved.
|
7 |
*
|
8 |
* Redistribution and use in source and binary forms, with or without
|
9 |
* modification, are permitted provided that the following conditions are met:
|
3 |
* $Id$
|
4 |
*
|
5 |
* Copyright (c) 2011, Donovan Schönknecht. All rights reserved.
|
6 |
+
* Portions copyright (c) 2012-3, David Anderson (http://www.simbahosting.co.uk). All rights reserved.
|
7 |
*
|
8 |
* Redistribution and use in source and binary forms, with or without
|
9 |
* modification, are permitted provided that the following conditions are met:
|
includes/ajax.js
DELETED
File without changes
|
includes/{Dropbox/OAuth/Consumer/ca-bundle.pem → cacert.pem}
RENAMED
@@ -1,7 +1,7 @@
|
|
1 |
##
|
2 |
## ca-bundle.crt -- Bundle of CA Root Certificates
|
3 |
##
|
4 |
-
## Certificate data from Mozilla as of:
|
5 |
##
|
6 |
## This is a bundle of X.509 certificates of public Certificate Authorities
|
7 |
## (CA). These were automatically extracted from Mozilla's root certificates
|
@@ -14,7 +14,7 @@
|
|
14 |
## Just configure this file as the SSLCACertificateFile.
|
15 |
##
|
16 |
|
17 |
-
# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.
|
18 |
|
19 |
GTE CyberTrust Global Root
|
20 |
==========================
|
@@ -3848,31 +3848,6 @@ eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
|
|
3848 |
Cp/HuZc=
|
3849 |
-----END CERTIFICATE-----
|
3850 |
|
3851 |
-
TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
|
3852 |
-
======================================================
|
3853 |
-
-----BEGIN CERTIFICATE-----
|
3854 |
-
MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
|
3855 |
-
bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
|
3856 |
-
MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
|
3857 |
-
QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
|
3858 |
-
DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
|
3859 |
-
a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
|
3860 |
-
BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
|
3861 |
-
bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
|
3862 |
-
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
|
3863 |
-
YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
|
3864 |
-
KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
|
3865 |
-
KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
|
3866 |
-
rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
|
3867 |
-
AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
|
3868 |
-
BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
|
3869 |
-
Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
|
3870 |
-
aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
|
3871 |
-
Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
|
3872 |
-
BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
|
3873 |
-
poRq0Tl9
|
3874 |
-
-----END CERTIFICATE-----
|
3875 |
-
|
3876 |
T-TeleSec GlobalRoot Class 3
|
3877 |
============================
|
3878 |
-----BEGIN CERTIFICATE-----
|
1 |
##
|
2 |
## ca-bundle.crt -- Bundle of CA Root Certificates
|
3 |
##
|
4 |
+
## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
|
5 |
##
|
6 |
## This is a bundle of X.509 certificates of public Certificate Authorities
|
7 |
## (CA). These were automatically extracted from Mozilla's root certificates
|
14 |
## Just configure this file as the SSLCACertificateFile.
|
15 |
##
|
16 |
|
17 |
+
# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $
|
18 |
|
19 |
GTE CyberTrust Global Root
|
20 |
==========================
|
3848 |
Cp/HuZc=
|
3849 |
-----END CERTIFICATE-----
|
3850 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3851 |
T-TeleSec GlobalRoot Class 3
|
3852 |
============================
|
3853 |
-----BEGIN CERTIFICATE-----
|
includes/cloudfiles/cloudfiles.php
ADDED
@@ -0,0 +1,2629 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This is the PHP Cloud Files API.
|
4 |
+
*
|
5 |
+
* <code>
|
6 |
+
* # Authenticate to Cloud Files. The default is to automatically try
|
7 |
+
* # to re-authenticate if an authentication token expires.
|
8 |
+
* #
|
9 |
+
* # NOTE: Some versions of cURL include an outdated certificate authority (CA)
|
10 |
+
* # file. This API ships with a newer version obtained directly from
|
11 |
+
* # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
|
12 |
+
* # call the CF_Authentication instance's 'ssl_use_cabundle()' method.
|
13 |
+
* #
|
14 |
+
* $auth = new CF_Authentication($username, $api_key);
|
15 |
+
* # $auth->ssl_use_cabundle(); # bypass cURL's old CA bundle
|
16 |
+
* $auth->authenticate();
|
17 |
+
*
|
18 |
+
* # Establish a connection to the storage system
|
19 |
+
* #
|
20 |
+
* # NOTE: Some versions of cURL include an outdated certificate authority (CA)
|
21 |
+
* # file. This API ships with a newer version obtained directly from
|
22 |
+
* # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
|
23 |
+
* # call the CF_Connection instance's 'ssl_use_cabundle()' method.
|
24 |
+
* #
|
25 |
+
* $conn = new CF_Connection($auth);
|
26 |
+
* # $conn->ssl_use_cabundle(); # bypass cURL's old CA bundle
|
27 |
+
*
|
28 |
+
* # Create a remote Container and storage Object
|
29 |
+
* #
|
30 |
+
* $images = $conn->create_container("photos");
|
31 |
+
* $bday = $images->create_object("first_birthday.jpg");
|
32 |
+
*
|
33 |
+
* # Upload content from a local file by streaming it. Note that we use
|
34 |
+
* # a "float" for the file size to overcome PHP's 32-bit integer limit for
|
35 |
+
* # very large files.
|
36 |
+
* #
|
37 |
+
* $fname = "/home/user/photos/birthdays/birthday1.jpg"; # filename to upload
|
38 |
+
* $size = (float) sprintf("%u", filesize($fname));
|
39 |
+
* $fp = open($fname, "r");
|
40 |
+
* $bday->write($fp, $size);
|
41 |
+
*
|
42 |
+
* # Or... use a convenience function instead
|
43 |
+
* #
|
44 |
+
* $bday->load_from_filename("/home/user/photos/birthdays/birthday1.jpg");
|
45 |
+
*
|
46 |
+
* # Now, publish the "photos" container to serve the images by CDN.
|
47 |
+
* # Use the "$uri" value to put in your web pages or send the link in an
|
48 |
+
* # email message, etc.
|
49 |
+
* #
|
50 |
+
* $uri = $images->make_public();
|
51 |
+
*
|
52 |
+
* # Or... print out the Object's public URI
|
53 |
+
* #
|
54 |
+
* print $bday->public_uri();
|
55 |
+
* </code>
|
56 |
+
*
|
57 |
+
* See the included tests directory for additional sample code.
|
58 |
+
*
|
59 |
+
* Requres PHP 5.x (for Exceptions and OO syntax) and PHP's cURL module.
|
60 |
+
*
|
61 |
+
* It uses the supporting "cloudfiles_http.php" module for HTTP(s) support and
|
62 |
+
* allows for connection re-use and streaming of content into/out of Cloud Files
|
63 |
+
* via PHP's cURL module.
|
64 |
+
*
|
65 |
+
* See COPYING for license information.
|
66 |
+
*
|
67 |
+
* @author Eric "EJ" Johnson <ej@racklabs.com>
|
68 |
+
* @copyright Copyright (c) 2008, Rackspace US, Inc.
|
69 |
+
* @package php-cloudfiles
|
70 |
+
*/
|
71 |
+
|
72 |
+
/**
|
73 |
+
*/
|
74 |
+
require_once("cloudfiles_exceptions.php");
|
75 |
+
require("cloudfiles_http.php");
|
76 |
+
@define("DEFAULT_CF_API_VERSION", 1);
|
77 |
+
@define("MAX_CONTAINER_NAME_LEN", 256);
|
78 |
+
@define("MAX_OBJECT_NAME_LEN", 1024);
|
79 |
+
@define("MAX_OBJECT_SIZE", 5*1024*1024*1024+1);
|
80 |
+
@define("US_AUTHURL", "https://auth.api.rackspacecloud.com");
|
81 |
+
@define("UK_AUTHURL", "https://lon.auth.api.rackspacecloud.com");
|
82 |
+
/**
|
83 |
+
* Class for handling Cloud Files Authentication, call it's {@link authenticate()}
|
84 |
+
* method to obtain authorized service urls and an authentication token.
|
85 |
+
*
|
86 |
+
* Example:
|
87 |
+
* <code>
|
88 |
+
* # Create the authentication instance
|
89 |
+
* #
|
90 |
+
* $auth = new CF_Authentication("username", "api_key");
|
91 |
+
*
|
92 |
+
* # NOTE: For UK Customers please specify your AuthURL Manually
|
93 |
+
* # There is a Predfined constant to use EX:
|
94 |
+
* #
|
95 |
+
* # $auth = new CF_Authentication("username, "api_key", NULL, UK_AUTHURL);
|
96 |
+
* # Using the UK_AUTHURL keyword will force the api to use the UK AuthUrl.
|
97 |
+
* # rather then the US one. The NULL Is passed for legacy purposes and must
|
98 |
+
* # be passed to function correctly.
|
99 |
+
*
|
100 |
+
* # NOTE: Some versions of cURL include an outdated certificate authority (CA)
|
101 |
+
* # file. This API ships with a newer version obtained directly from
|
102 |
+
* # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
|
103 |
+
* # call the CF_Authentication instance's 'ssl_use_cabundle()' method.
|
104 |
+
* #
|
105 |
+
* # $auth->ssl_use_cabundle(); # bypass cURL's old CA bundle
|
106 |
+
*
|
107 |
+
* # Perform authentication request
|
108 |
+
* #
|
109 |
+
* $auth->authenticate();
|
110 |
+
* </code>
|
111 |
+
*
|
112 |
+
* @package php-cloudfiles
|
113 |
+
*/
|
114 |
+
class CF_Authentication
|
115 |
+
{
|
116 |
+
public $dbug;
|
117 |
+
public $username;
|
118 |
+
public $api_key;
|
119 |
+
public $auth_host;
|
120 |
+
public $account;
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Instance variables that are set after successful authentication
|
124 |
+
*/
|
125 |
+
public $storage_url;
|
126 |
+
public $cdnm_url;
|
127 |
+
public $auth_token;
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Class constructor (PHP 5 syntax)
|
131 |
+
*
|
132 |
+
* @param string $username Mosso username
|
133 |
+
* @param string $api_key Mosso API Access Key
|
134 |
+
* @param string $account <i>Account name</i>
|
135 |
+
* @param string $auth_host <i>Authentication service URI</i>
|
136 |
+
*/
|
137 |
+
function __construct($username=NULL, $api_key=NULL, $account=NULL, $auth_host=US_AUTHURL)
|
138 |
+
{
|
139 |
+
|
140 |
+
$this->dbug = False;
|
141 |
+
$this->username = $username;
|
142 |
+
$this->api_key = $api_key;
|
143 |
+
$this->account_name = $account;
|
144 |
+
$this->auth_host = $auth_host;
|
145 |
+
|
146 |
+
$this->storage_url = NULL;
|
147 |
+
$this->cdnm_url = NULL;
|
148 |
+
$this->auth_token = NULL;
|
149 |
+
|
150 |
+
$this->cfs_http = new UpdraftPlus_CF_Http(DEFAULT_CF_API_VERSION);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Use the Certificate Authority bundle included with this API
|
155 |
+
*
|
156 |
+
* Most versions of PHP with cURL support include an outdated Certificate
|
157 |
+
* Authority (CA) bundle (the file that lists all valid certificate
|
158 |
+
* signing authorities). The SSL certificates used by the Cloud Files
|
159 |
+
* storage system are perfectly valid but have been created/signed by
|
160 |
+
* a CA not listed in these outdated cURL distributions.
|
161 |
+
*
|
162 |
+
* As a work-around, we've included an updated CA bundle obtained
|
163 |
+
* directly from cURL's web site (http://curl.haxx.se). You can direct
|
164 |
+
* the API to use this CA bundle by calling this method prior to making
|
165 |
+
* any remote calls. The best place to use this method is right after
|
166 |
+
* the CF_Authentication instance has been instantiated.
|
167 |
+
*
|
168 |
+
* You can specify your own CA bundle by passing in the full pathname
|
169 |
+
* to the bundle. You can use the included CA bundle by leaving the
|
170 |
+
* argument blank.
|
171 |
+
*
|
172 |
+
* @param string $path Specify path to CA bundle (default to included)
|
173 |
+
*/
|
174 |
+
function ssl_use_cabundle($path=NULL)
|
175 |
+
{
|
176 |
+
$this->cfs_http->ssl_use_cabundle($path);
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Attempt to validate Username/API Access Key
|
181 |
+
*
|
182 |
+
* Attempts to validate credentials with the authentication service. It
|
183 |
+
* either returns <kbd>True</kbd> or throws an Exception. Accepts a single
|
184 |
+
* (optional) argument for the storage system API version.
|
185 |
+
*
|
186 |
+
* Example:
|
187 |
+
* <code>
|
188 |
+
* # Create the authentication instance
|
189 |
+
* #
|
190 |
+
* $auth = new CF_Authentication("username", "api_key");
|
191 |
+
*
|
192 |
+
* # Perform authentication request
|
193 |
+
* #
|
194 |
+
* $auth->authenticate();
|
195 |
+
* </code>
|
196 |
+
*
|
197 |
+
* @param string $version API version for Auth service (optional)
|
198 |
+
* @return boolean <kbd>True</kbd> if successfully authenticated
|
199 |
+
* @throws AuthenticationException invalid credentials
|
200 |
+
* @throws InvalidResponseException invalid response
|
201 |
+
*/
|
202 |
+
function authenticate($version=DEFAULT_CF_API_VERSION)
|
203 |
+
{
|
204 |
+
list($status,$reason,$surl,$curl,$atoken) =
|
205 |
+
$this->cfs_http->authenticate($this->username, $this->api_key,
|
206 |
+
$this->account_name, $this->auth_host);
|
207 |
+
|
208 |
+
if ($status == 401) {
|
209 |
+
throw new AuthenticationException("Invalid username or access key.");
|
210 |
+
}
|
211 |
+
if ($status < 200 || $status > 299) {
|
212 |
+
throw new InvalidResponseException(
|
213 |
+
"Unexpected response (".$status."): ".$reason);
|
214 |
+
}
|
215 |
+
|
216 |
+
if (!($surl || $curl) || !$atoken) {
|
217 |
+
throw new InvalidResponseException(
|
218 |
+
"Expected headers missing from auth service.");
|
219 |
+
}
|
220 |
+
$this->storage_url = $surl;
|
221 |
+
$this->cdnm_url = $curl;
|
222 |
+
$this->auth_token = $atoken;
|
223 |
+
return True;
|
224 |
+
}
|
225 |
+
/**
|
226 |
+
* Use Cached Token and Storage URL's rather then grabbing from the Auth System
|
227 |
+
*
|
228 |
+
* Example:
|
229 |
+
* <code>
|
230 |
+
* #Create an Auth instance
|
231 |
+
* $auth = new CF_Authentication();
|
232 |
+
* #Pass Cached URL's and Token as Args
|
233 |
+
* $auth->load_cached_credentials("auth_token", "storage_url", "cdn_management_url");
|
234 |
+
* </code>
|
235 |
+
*
|
236 |
+
* @param string $auth_token A Cloud Files Auth Token (Required)
|
237 |
+
* @param string $storage_url The Cloud Files Storage URL (Required)
|
238 |
+
* @param string $cdnm_url CDN Management URL (Required)
|
239 |
+
* @return boolean <kbd>True</kbd> if successful
|
240 |
+
* @throws SyntaxException If any of the Required Arguments are missing
|
241 |
+
*/
|
242 |
+
function load_cached_credentials($auth_token, $storage_url, $cdnm_url)
|
243 |
+
{
|
244 |
+
if(!$storage_url || !$cdnm_url)
|
245 |
+
{
|
246 |
+
throw new SyntaxException("Missing Required Interface URL's!");
|
247 |
+
return False;
|
248 |
+
}
|
249 |
+
if(!$auth_token)
|
250 |
+
{
|
251 |
+
throw new SyntaxException("Missing Auth Token!");
|
252 |
+
return False;
|
253 |
+
}
|
254 |
+
|
255 |
+
$this->storage_url = $storage_url;
|
256 |
+
$this->cdnm_url = $cdnm_url;
|
257 |
+
$this->auth_token = $auth_token;
|
258 |
+
return True;
|
259 |
+
}
|
260 |
+
/**
|
261 |
+
* Grab Cloud Files info to be Cached for later use with the load_cached_credentials method.
|
262 |
+
*
|
263 |
+
* Example:
|
264 |
+
* <code>
|
265 |
+
* #Create an Auth instance
|
266 |
+
* $auth = new CF_Authentication("UserName","API_Key");
|
267 |
+
* $auth->authenticate();
|
268 |
+
* $array = $auth->export_credentials();
|
269 |
+
* </code>
|
270 |
+
*
|
271 |
+
* @return array of url's and an auth token.
|
272 |
+
*/
|
273 |
+
function export_credentials()
|
274 |
+
{
|
275 |
+
$arr = array();
|
276 |
+
$arr['storage_url'] = $this->storage_url;
|
277 |
+
$arr['cdnm_url'] = $this->cdnm_url;
|
278 |
+
$arr['auth_token'] = $this->auth_token;
|
279 |
+
|
280 |
+
return $arr;
|
281 |
+
}
|
282 |
+
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Make sure the CF_Authentication instance has authenticated.
|
286 |
+
*
|
287 |
+
* Ensures that the instance variables necessary to communicate with
|
288 |
+
* Cloud Files have been set from a previous authenticate() call.
|
289 |
+
*
|
290 |
+
* @return boolean <kbd>True</kbd> if successfully authenticated
|
291 |
+
*/
|
292 |
+
function authenticated()
|
293 |
+
{
|
294 |
+
if (!($this->storage_url || $this->cdnm_url) || !$this->auth_token) {
|
295 |
+
return False;
|
296 |
+
}
|
297 |
+
return True;
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Toggle debugging - set cURL verbose flag
|
302 |
+
*/
|
303 |
+
function setDebug($bool)
|
304 |
+
{
|
305 |
+
$this->dbug = $bool;
|
306 |
+
$this->cfs_http->setDebug($bool);
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Class for establishing connections to the Cloud Files storage system.
|
312 |
+
* Connection instances are used to communicate with the storage system at
|
313 |
+
* the account level; listing and deleting Containers and returning Container
|
314 |
+
* instances.
|
315 |
+
*
|
316 |
+
* Example:
|
317 |
+
* <code>
|
318 |
+
* # Create the authentication instance
|
319 |
+
* #
|
320 |
+
* $auth = new CF_Authentication("username", "api_key");
|
321 |
+
*
|
322 |
+
* # Perform authentication request
|
323 |
+
* #
|
324 |
+
* $auth->authenticate();
|
325 |
+
*
|
326 |
+
* # Create a connection to the storage/cdn system(s) and pass in the
|
327 |
+
* # validated CF_Authentication instance.
|
328 |
+
* #
|
329 |
+
* $conn = new CF_Connection($auth);
|
330 |
+
*
|
331 |
+
* # NOTE: Some versions of cURL include an outdated certificate authority (CA)
|
332 |
+
* # file. This API ships with a newer version obtained directly from
|
333 |
+
* # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
|
334 |
+
* # call the CF_Authentication instance's 'ssl_use_cabundle()' method.
|
335 |
+
* #
|
336 |
+
* # $conn->ssl_use_cabundle(); # bypass cURL's old CA bundle
|
337 |
+
* </code>
|
338 |
+
*
|
339 |
+
* @package php-cloudfiles
|
340 |
+
*/
|
341 |
+
class CF_Connection
|
342 |
+
{
|
343 |
+
public $dbug;
|
344 |
+
public $cfs_http;
|
345 |
+
public $cfs_auth;
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Pass in a previously authenticated CF_Authentication instance.
|
349 |
+
*
|
350 |
+
* Example:
|
351 |
+
* <code>
|
352 |
+
* # Create the authentication instance
|
353 |
+
* #
|
354 |
+
* $auth = new CF_Authentication("username", "api_key");
|
355 |
+
*
|
356 |
+
* # Perform authentication request
|
357 |
+
* #
|
358 |
+
* $auth->authenticate();
|
359 |
+
*
|
360 |
+
* # Create a connection to the storage/cdn system(s) and pass in the
|
361 |
+
* # validated CF_Authentication instance.
|
362 |
+
* #
|
363 |
+
* $conn = new CF_Connection($auth);
|
364 |
+
*
|
365 |
+
* # If you are connecting via Rackspace servers and have access
|
366 |
+
* # to the servicenet network you can set the $servicenet to True
|
367 |
+
* # like this.
|
368 |
+
*
|
369 |
+
* $conn = new CF_Connection($auth, $servicenet=True);
|
370 |
+
*
|
371 |
+
* </code>
|
372 |
+
*
|
373 |
+
* If the environement variable RACKSPACE_SERVICENET is defined it will
|
374 |
+
* force to connect via the servicenet.
|
375 |
+
*
|
376 |
+
* @param obj $cfs_auth previously authenticated CF_Authentication instance
|
377 |
+
* @param boolean $servicenet enable/disable access via Rackspace servicenet.
|
378 |
+
* @throws AuthenticationException not authenticated
|
379 |
+
*/
|
380 |
+
function __construct($cfs_auth, $servicenet=False)
|
381 |
+
{
|
382 |
+
if (isset($_ENV['RACKSPACE_SERVICENET']))
|
383 |
+
$servicenet=True;
|
384 |
+
$this->cfs_http = new UpdraftPlus_CF_Http(DEFAULT_CF_API_VERSION);
|
385 |
+
$this->cfs_auth = $cfs_auth;
|
386 |
+
if (!$this->cfs_auth->authenticated()) {
|
387 |
+
$e = "Need to pass in a previously authenticated ";
|
388 |
+
$e .= "CF_Authentication instance.";
|
389 |
+
throw new AuthenticationException($e);
|
390 |
+
}
|
391 |
+
$this->cfs_http->setCFAuth($this->cfs_auth, $servicenet=$servicenet);
|
392 |
+
$this->dbug = False;
|
393 |
+
}
|
394 |
+
|
395 |
+
/**
|
396 |
+
* Toggle debugging of instance and back-end HTTP module
|
397 |
+
*
|
398 |
+
* @param boolean $bool enable/disable cURL debugging
|
399 |
+
*/
|
400 |
+
function setDebug($bool)
|
401 |
+
{
|
402 |
+
$this->dbug = (boolean) $bool;
|
403 |
+
$this->cfs_http->setDebug($this->dbug);
|
404 |
+
}
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Close a connection
|
408 |
+
*
|
409 |
+
* Example:
|
410 |
+
* <code>
|
411 |
+
*
|
412 |
+
* $conn->close();
|
413 |
+
*
|
414 |
+
* </code>
|
415 |
+
*
|
416 |
+
* Will close all current cUrl active connections.
|
417 |
+
*
|
418 |
+
*/
|
419 |
+
public function close()
|
420 |
+
{
|
421 |
+
$this->cfs_http->close();
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Cloud Files account information
|
426 |
+
*
|
427 |
+
* Return an array of two floats (since PHP only supports 32-bit integers);
|
428 |
+
* number of containers on the account and total bytes used for the account.
|
429 |
+
*
|
430 |
+
* Example:
|
431 |
+
* <code>
|
432 |
+
* # ... authentication code excluded (see previous examples) ...
|
433 |
+
* #
|
434 |
+
* $conn = new CF_Connection($auth);
|
435 |
+
*
|
436 |
+
* list($quantity, $bytes) = $conn->get_info();
|
437 |
+
* print "Number of containers: " . $quantity . "\n";
|
438 |
+
* print "Bytes stored in container: " . $bytes . "\n";
|
439 |
+
* </code>
|
440 |
+
*
|
441 |
+
* @return array (number of containers, total bytes stored)
|
442 |
+
* @throws InvalidResponseException unexpected response
|
443 |
+
*/
|
444 |
+
function get_info()
|
445 |
+
{
|
446 |
+
list($status, $reason, $container_count, $total_bytes) =
|
447 |
+
$this->cfs_http->head_account();
|
448 |
+
#if ($status == 401 && $this->_re_auth()) {
|
449 |
+
# return $this->get_info();
|
450 |
+
#}
|
451 |
+
if ($status < 200 || $status > 299) {
|
452 |
+
throw new InvalidResponseException(
|
453 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
454 |
+
}
|
455 |
+
return array($container_count, $total_bytes);
|
456 |
+
}
|
457 |
+
|
458 |
+
/**
|
459 |
+
* Create a Container
|
460 |
+
*
|
461 |
+
* Given a Container name, return a Container instance, creating a new
|
462 |
+
* remote Container if it does not exit.
|
463 |
+
*
|
464 |
+
* Example:
|
465 |
+
* <code>
|
466 |
+
* # ... authentication code excluded (see previous examples) ...
|
467 |
+
* #
|
468 |
+
* $conn = new CF_Connection($auth);
|
469 |
+
*
|
470 |
+
* $images = $conn->create_container("my photos");
|
471 |
+
* </code>
|
472 |
+
*
|
473 |
+
* @param string $container_name container name
|
474 |
+
* @return CF_Container
|
475 |
+
* @throws SyntaxException invalid name
|
476 |
+
* @throws InvalidResponseException unexpected response
|
477 |
+
*/
|
478 |
+
function create_container($container_name=NULL)
|
479 |
+
{
|
480 |
+
if ($container_name != "0" and !isset($container_name))
|
481 |
+
throw new SyntaxException("Container name not set.");
|
482 |
+
|
483 |
+
if (!isset($container_name) or $container_name == "")
|
484 |
+
throw new SyntaxException("Container name not set.");
|
485 |
+
|
486 |
+
if (strpos($container_name, "/") !== False) {
|
487 |
+
$r = "Container name '".$container_name;
|
488 |
+
$r .= "' cannot contain a '/' character.";
|
489 |
+
throw new SyntaxException($r);
|
490 |
+
}
|
491 |
+
if (strlen($container_name) > MAX_CONTAINER_NAME_LEN) {
|
492 |
+
throw new SyntaxException(sprintf(
|
493 |
+
"Container name exeeds %d bytes.",
|
494 |
+
MAX_CONTAINER_NAME_LEN));
|
495 |
+
}
|
496 |
+
|
497 |
+
$return_code = $this->cfs_http->create_container($container_name);
|
498 |
+
if (!$return_code) {
|
499 |
+
throw new InvalidResponseException("Invalid response ("
|
500 |
+
. $return_code. "): " . $this->cfs_http->get_error());
|
501 |
+
}
|
502 |
+
#if ($status == 401 && $this->_re_auth()) {
|
503 |
+
# return $this->create_container($container_name);
|
504 |
+
#}
|
505 |
+
if ($return_code != 201 && $return_code != 202) {
|
506 |
+
throw new InvalidResponseException(
|
507 |
+
"Invalid response (".$return_code."): "
|
508 |
+
. $this->cfs_http->get_error());
|
509 |
+
}
|
510 |
+
return new CF_Container($this->cfs_auth, $this->cfs_http, $container_name);
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Delete a Container
|
515 |
+
*
|
516 |
+
* Given either a Container instance or name, remove the remote Container.
|
517 |
+
* The Container must be empty prior to removing it.
|
518 |
+
*
|
519 |
+
* Example:
|
520 |
+
* <code>
|
521 |
+
* # ... authentication code excluded (see previous examples) ...
|
522 |
+
* #
|
523 |
+
* $conn = new CF_Connection($auth);
|
524 |
+
*
|
525 |
+
* $conn->delete_container("my photos");
|
526 |
+
* </code>
|
527 |
+
*
|
528 |
+
* @param string|obj $container container name or instance
|
529 |
+
* @return boolean <kbd>True</kbd> if successfully deleted
|
530 |
+
* @throws SyntaxException missing proper argument
|
531 |
+
* @throws InvalidResponseException invalid response
|
532 |
+
* @throws NonEmptyContainerException container not empty
|
533 |
+
* @throws NoSuchContainerException remote container does not exist
|
534 |
+
*/
|
535 |
+
function delete_container($container=NULL)
|
536 |
+
{
|
537 |
+
$container_name = NULL;
|
538 |
+
|
539 |
+
if (is_object($container)) {
|
540 |
+
if (get_class($container) == "CF_Container") {
|
541 |
+
$container_name = $container->name;
|
542 |
+
}
|
543 |
+
}
|
544 |
+
if (is_string($container)) {
|
545 |
+
$container_name = $container;
|
546 |
+
}
|
547 |
+
|
548 |
+
if ($container_name != "0" and !isset($container_name))
|
549 |
+
throw new SyntaxException("Must specify container object or name.");
|
550 |
+
|
551 |
+
$return_code = $this->cfs_http->delete_container($container_name);
|
552 |
+
|
553 |
+
if (!$return_code) {
|
554 |
+
throw new InvalidResponseException("Failed to obtain http response");
|
555 |
+
}
|
556 |
+
#if ($status == 401 && $this->_re_auth()) {
|
557 |
+
# return $this->delete_container($container);
|
558 |
+
#}
|
559 |
+
if ($return_code == 409) {
|
560 |
+
throw new NonEmptyContainerException(
|
561 |
+
"Container must be empty prior to removing it.");
|
562 |
+
}
|
563 |
+
if ($return_code == 404) {
|
564 |
+
throw new NoSuchContainerException(
|
565 |
+
"Specified container did not exist to delete.");
|
566 |
+
}
|
567 |
+
if ($return_code != 204) {
|
568 |
+
throw new InvalidResponseException(
|
569 |
+
"Invalid response (".$return_code."): "
|
570 |
+
. $this->cfs_http->get_error());
|
571 |
+
}
|
572 |
+
return True;
|
573 |
+
}
|
574 |
+
|
575 |
+
/**
|
576 |
+
* Return a Container instance
|
577 |
+
*
|
578 |
+
* For the given name, return a Container instance if the remote Container
|
579 |
+
* exists, otherwise throw a Not Found exception.
|
580 |
+
*
|
581 |
+
* Example:
|
582 |
+
* <code>
|
583 |
+
* # ... authentication code excluded (see previous examples) ...
|
584 |
+
* #
|
585 |
+
* $conn = new CF_Connection($auth);
|
586 |
+
*
|
587 |
+
* $images = $conn->get_container("my photos");
|
588 |
+
* print "Number of Objects: " . $images->count . "\n";
|
589 |
+
* print "Bytes stored in container: " . $images->bytes . "\n";
|
590 |
+
* </code>
|
591 |
+
*
|
592 |
+
* @param string $container_name name of the remote Container
|
593 |
+
* @return container CF_Container instance
|
594 |
+
* @throws NoSuchContainerException thrown if no remote Container
|
595 |
+
* @throws InvalidResponseException unexpected response
|
596 |
+
*/
|
597 |
+
function get_container($container_name=NULL)
|
598 |
+
{
|
599 |
+
list($status, $reason, $count, $bytes) =
|
600 |
+
$this->cfs_http->head_container($container_name);
|
601 |
+
#if ($status == 401 && $this->_re_auth()) {
|
602 |
+
# return $this->get_container($container_name);
|
603 |
+
#}
|
604 |
+
if ($status == 404) {
|
605 |
+
throw new NoSuchContainerException("Container not found.");
|
606 |
+
}
|
607 |
+
if ($status < 200 || $status > 299) {
|
608 |
+
throw new InvalidResponseException(
|
609 |
+
"Invalid response: ".$this->cfs_http->get_error());
|
610 |
+
}
|
611 |
+
return new CF_Container($this->cfs_auth, $this->cfs_http,
|
612 |
+
$container_name, $count, $bytes);
|
613 |
+
}
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Return array of Container instances
|
617 |
+
*
|
618 |
+
* Return an array of CF_Container instances on the account. The instances
|
619 |
+
* will be fully populated with Container attributes (bytes stored and
|
620 |
+
* Object count)
|
621 |
+
*
|
622 |
+
* Example:
|
623 |
+
* <code>
|
624 |
+
* # ... authentication code excluded (see previous examples) ...
|
625 |
+
* #
|
626 |
+
* $conn = new CF_Connection($auth);
|
627 |
+
*
|
628 |
+
* $clist = $conn->get_containers();
|
629 |
+
* foreach ($clist as $cont) {
|
630 |
+
* print "Container name: " . $cont->name . "\n";
|
631 |
+
* print "Number of Objects: " . $cont->count . "\n";
|
632 |
+
* print "Bytes stored in container: " . $cont->bytes . "\n";
|
633 |
+
* }
|
634 |
+
* </code>
|
635 |
+
*
|
636 |
+
* @return array An array of CF_Container instances
|
637 |
+
* @throws InvalidResponseException unexpected response
|
638 |
+
*/
|
639 |
+
function get_containers($limit=0, $marker=NULL)
|
640 |
+
{
|
641 |
+
list($status, $reason, $container_info) =
|
642 |
+
$this->cfs_http->list_containers_info($limit, $marker);
|
643 |
+
#if ($status == 401 && $this->_re_auth()) {
|
644 |
+
# return $this->get_containers();
|
645 |
+
#}
|
646 |
+
if ($status < 200 || $status > 299) {
|
647 |
+
throw new InvalidResponseException(
|
648 |
+
"Invalid response: ".$this->cfs_http->get_error());
|
649 |
+
}
|
650 |
+
$containers = array();
|
651 |
+
foreach ($container_info as $name => $info) {
|
652 |
+
$containers[] = new CF_Container($this->cfs_auth, $this->cfs_http,
|
653 |
+
$info['name'], $info["count"], $info["bytes"], False);
|
654 |
+
}
|
655 |
+
return $containers;
|
656 |
+
}
|
657 |
+
|
658 |
+
/**
|
659 |
+
* Return list of remote Containers
|
660 |
+
*
|
661 |
+
* Return an array of strings containing the names of all remote Containers.
|
662 |
+
*
|
663 |
+
* Example:
|
664 |
+
* <code>
|
665 |
+
* # ... authentication code excluded (see previous examples) ...
|
666 |
+
* #
|
667 |
+
* $conn = new CF_Connection($auth);
|
668 |
+
*
|
669 |
+
* $container_list = $conn->list_containers();
|
670 |
+
* print_r($container_list);
|
671 |
+
* Array
|
672 |
+
* (
|
673 |
+
* [0] => "my photos",
|
674 |
+
* [1] => "my docs"
|
675 |
+
* )
|
676 |
+
* </code>
|
677 |
+
*
|
678 |
+
* @param integer $limit restrict results to $limit Containers
|
679 |
+
* @param string $marker return results greater than $marker
|
680 |
+
* @return array list of remote Containers
|
681 |
+
* @throws InvalidResponseException unexpected response
|
682 |
+
*/
|
683 |
+
function list_containers($limit=0, $marker=NULL)
|
684 |
+
{
|
685 |
+
list($status, $reason, $containers) =
|
686 |
+
$this->cfs_http->list_containers($limit, $marker);
|
687 |
+
#if ($status == 401 && $this->_re_auth()) {
|
688 |
+
# return $this->list_containers($limit, $marker);
|
689 |
+
#}
|
690 |
+
if ($status < 200 || $status > 299) {
|
691 |
+
throw new InvalidResponseException(
|
692 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
693 |
+
}
|
694 |
+
return $containers;
|
695 |
+
}
|
696 |
+
|
697 |
+
/**
|
698 |
+
* Return array of information about remote Containers
|
699 |
+
*
|
700 |
+
* Return a nested array structure of Container info.
|
701 |
+
*
|
702 |
+
* Example:
|
703 |
+
* <code>
|
704 |
+
* # ... authentication code excluded (see previous examples) ...
|
705 |
+
* #
|
706 |
+
*
|
707 |
+
* $container_info = $conn->list_containers_info();
|
708 |
+
* print_r($container_info);
|
709 |
+
* Array
|
710 |
+
* (
|
711 |
+
* ["my photos"] =>
|
712 |
+
* Array
|
713 |
+
* (
|
714 |
+
* ["bytes"] => 78,
|
715 |
+
* ["count"] => 2
|
716 |
+
* )
|
717 |
+
* ["docs"] =>
|
718 |
+
* Array
|
719 |
+
* (
|
720 |
+
* ["bytes"] => 37323,
|
721 |
+
* ["count"] => 12
|
722 |
+
* )
|
723 |
+
* )
|
724 |
+
* </code>
|
725 |
+
*
|
726 |
+
* @param integer $limit restrict results to $limit Containers
|
727 |
+
* @param string $marker return results greater than $marker
|
728 |
+
* @return array nested array structure of Container info
|
729 |
+
* @throws InvalidResponseException unexpected response
|
730 |
+
*/
|
731 |
+
function list_containers_info($limit=0, $marker=NULL)
|
732 |
+
{
|
733 |
+
list($status, $reason, $container_info) =
|
734 |
+
$this->cfs_http->list_containers_info($limit, $marker);
|
735 |
+
#if ($status == 401 && $this->_re_auth()) {
|
736 |
+
# return $this->list_containers_info($limit, $marker);
|
737 |
+
#}
|
738 |
+
if ($status < 200 || $status > 299) {
|
739 |
+
throw new InvalidResponseException(
|
740 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
741 |
+
}
|
742 |
+
return $container_info;
|
743 |
+
}
|
744 |
+
|
745 |
+
/**
|
746 |
+
* Return list of Containers that have been published to the CDN.
|
747 |
+
*
|
748 |
+
* Return an array of strings containing the names of published Containers.
|
749 |
+
* Note that this function returns the list of any Container that has
|
750 |
+
* ever been CDN-enabled regardless of it's existence in the storage
|
751 |
+
* system.
|
752 |
+
*
|
753 |
+
* Example:
|
754 |
+
* <code>
|
755 |
+
* # ... authentication code excluded (see previous examples) ...
|
756 |
+
* #
|
757 |
+
* $conn = new CF_Connection($auth);
|
758 |
+
*
|
759 |
+
* $public_containers = $conn->list_public_containers();
|
760 |
+
* print_r($public_containers);
|
761 |
+
* Array
|
762 |
+
* (
|
763 |
+
* [0] => "images",
|
764 |
+
* [1] => "css",
|
765 |
+
* [2] => "javascript"
|
766 |
+
* )
|
767 |
+
* </code>
|
768 |
+
*
|
769 |
+
* @param bool $enabled_only Will list all containers ever CDN enabled if * set to false or only currently enabled CDN containers if set to true. * Defaults to false.
|
770 |
+
* @return array list of published Container names
|
771 |
+
* @throws InvalidResponseException unexpected response
|
772 |
+
*/
|
773 |
+
function list_public_containers($enabled_only=False)
|
774 |
+
{
|
775 |
+
list($status, $reason, $containers) =
|
776 |
+
$this->cfs_http->list_cdn_containers($enabled_only);
|
777 |
+
#if ($status == 401 && $this->_re_auth()) {
|
778 |
+
# return $this->list_public_containers();
|
779 |
+
#}
|
780 |
+
if ($status < 200 || $status > 299) {
|
781 |
+
throw new InvalidResponseException(
|
782 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
783 |
+
}
|
784 |
+
return $containers;
|
785 |
+
}
|
786 |
+
|
787 |
+
/**
|
788 |
+
* Set a user-supplied callback function to report download progress
|
789 |
+
*
|
790 |
+
* The callback function is used to report incremental progress of a data
|
791 |
+
* download functions (e.g. $container->list_objects(), $obj->read(), etc).
|
792 |
+
* The specified function will be periodically called with the number of
|
793 |
+
* bytes transferred until the entire download is complete. This callback
|
794 |
+
* function can be useful for implementing "progress bars" for large
|
795 |
+
* downloads.
|
796 |
+
*
|
797 |
+
* The specified callback function should take a single integer parameter.
|
798 |
+
*
|
799 |
+
* <code>
|
800 |
+
* function read_callback($bytes_transferred) {
|
801 |
+
* print ">> downloaded " . $bytes_transferred . " bytes.\n";
|
802 |
+
* # ... do other things ...
|
803 |
+
* return;
|
804 |
+
* }
|
805 |
+
*
|
806 |
+
* $conn = new CF_Connection($auth_obj);
|
807 |
+
* $conn->set_read_progress_function("read_callback");
|
808 |
+
* print_r($conn->list_containers());
|
809 |
+
*
|
810 |
+
* # output would look like this:
|
811 |
+
* #
|
812 |
+
* >> downloaded 10 bytes.
|
813 |
+
* >> downloaded 11 bytes.
|
814 |
+
* Array
|
815 |
+
* (
|
816 |
+
* [0] => fuzzy.txt
|
817 |
+
* [1] => space name
|
818 |
+
* )
|
819 |
+
* </code>
|
820 |
+
*
|
821 |
+
* @param string $func_name the name of the user callback function
|
822 |
+
*/
|
823 |
+
function set_read_progress_function($func_name)
|
824 |
+
{
|
825 |
+
$this->cfs_http->setReadProgressFunc($func_name);
|
826 |
+
}
|
827 |
+
|
828 |
+
/**
|
829 |
+
* Set a user-supplied callback function to report upload progress
|
830 |
+
*
|
831 |
+
* The callback function is used to report incremental progress of a data
|
832 |
+
* upload functions (e.g. $obj->write() call). The specified function will
|
833 |
+
* be periodically called with the number of bytes transferred until the
|
834 |
+
* entire upload is complete. This callback function can be useful
|
835 |
+
* for implementing "progress bars" for large uploads/downloads.
|
836 |
+
*
|
837 |
+
* The specified callback function should take a single integer parameter.
|
838 |
+
*
|
839 |
+
* <code>
|
840 |
+
* function write_callback($bytes_transferred) {
|
841 |
+
* print ">> uploaded " . $bytes_transferred . " bytes.\n";
|
842 |
+
* # ... do other things ...
|
843 |
+
* return;
|
844 |
+
* }
|
845 |
+
*
|
846 |
+
* $conn = new CF_Connection($auth_obj);
|
847 |
+
* $conn->set_write_progress_function("write_callback");
|
848 |
+
* $container = $conn->create_container("stuff");
|
849 |
+
* $obj = $container->create_object("foo");
|
850 |
+
* $obj->write("The callback function will be called during upload.");
|
851 |
+
*
|
852 |
+
* # output would look like this:
|
853 |
+
* # >> uploaded 51 bytes.
|
854 |
+
* #
|
855 |
+
* </code>
|
856 |
+
*
|
857 |
+
* @param string $func_name the name of the user callback function
|
858 |
+
*/
|
859 |
+
function set_write_progress_function($func_name)
|
860 |
+
{
|
861 |
+
$this->cfs_http->setWriteProgressFunc($func_name);
|
862 |
+
}
|
863 |
+
|
864 |
+
/**
|
865 |
+
* Use the Certificate Authority bundle included with this API
|
866 |
+
*
|
867 |
+
* Most versions of PHP with cURL support include an outdated Certificate
|
868 |
+
* Authority (CA) bundle (the file that lists all valid certificate
|
869 |
+
* signing authorities). The SSL certificates used by the Cloud Files
|
870 |
+
* storage system are perfectly valid but have been created/signed by
|
871 |
+
* a CA not listed in these outdated cURL distributions.
|
872 |
+
*
|
873 |
+
* As a work-around, we've included an updated CA bundle obtained
|
874 |
+
* directly from cURL's web site (http://curl.haxx.se). You can direct
|
875 |
+
* the API to use this CA bundle by calling this method prior to making
|
876 |
+
* any remote calls. The best place to use this method is right after
|
877 |
+
* the CF_Authentication instance has been instantiated.
|
878 |
+
*
|
879 |
+
* You can specify your own CA bundle by passing in the full pathname
|
880 |
+
* to the bundle. You can use the included CA bundle by leaving the
|
881 |
+
* argument blank.
|
882 |
+
*
|
883 |
+
* @param string $path Specify path to CA bundle (default to included)
|
884 |
+
*/
|
885 |
+
function ssl_use_cabundle($path=NULL)
|
886 |
+
{
|
887 |
+
$this->cfs_http->ssl_use_cabundle($path);
|
888 |
+
}
|
889 |
+
|
890 |
+
#private function _re_auth()
|
891 |
+
#{
|
892 |
+
# $new_auth = new CF_Authentication(
|
893 |
+
# $this->cfs_auth->username,
|
894 |
+
# $this->cfs_auth->api_key,
|
895 |
+
# $this->cfs_auth->auth_host,
|
896 |
+
# $this->cfs_auth->account);
|
897 |
+
# $new_auth->authenticate();
|
898 |
+
# $this->cfs_auth = $new_auth;
|
899 |
+
# $this->cfs_http->setCFAuth($this->cfs_auth);
|
900 |
+
# return True;
|
901 |
+
#}
|
902 |
+
}
|
903 |
+
|
904 |
+
/**
|
905 |
+
* Container operations
|
906 |
+
*
|
907 |
+
* Containers are storage compartments where you put your data (objects).
|
908 |
+
* A container is similar to a directory or folder on a conventional filesystem
|
909 |
+
* with the exception that they exist in a flat namespace, you can not create
|
910 |
+
* containers inside of containers.
|
911 |
+
*
|
912 |
+
* You also have the option of marking a Container as "public" so that the
|
913 |
+
* Objects stored in the Container are publicly available via the CDN.
|
914 |
+
*
|
915 |
+
* @package php-cloudfiles
|
916 |
+
*/
|
917 |
+
class CF_Container
|
918 |
+
{
|
919 |
+
public $cfs_auth;
|
920 |
+
public $cfs_http;
|
921 |
+
public $name;
|
922 |
+
public $object_count;
|
923 |
+
public $bytes_used;
|
924 |
+
public $metadata;
|
925 |
+
public $cdn_enabled;
|
926 |
+
public $cdn_streaming_uri;
|
927 |
+
public $cdn_ssl_uri;
|
928 |
+
public $cdn_uri;
|
929 |
+
public $cdn_ttl;
|
930 |
+
public $cdn_log_retention;
|
931 |
+
public $cdn_acl_user_agent;
|
932 |
+
public $cdn_acl_referrer;
|
933 |
+
|
934 |
+
/**
|
935 |
+
* Class constructor
|
936 |
+
*
|
937 |
+
* Constructor for Container
|
938 |
+
*
|
939 |
+
* @param obj $cfs_auth CF_Authentication instance
|
940 |
+
* @param obj $cfs_http HTTP connection manager
|
941 |
+
* @param string $name name of Container
|
942 |
+
* @param int $count number of Objects stored in this Container
|
943 |
+
* @param int $bytes number of bytes stored in this Container
|
944 |
+
* @throws SyntaxException invalid Container name
|
945 |
+
*/
|
946 |
+
function __construct(&$cfs_auth, &$cfs_http, $name, $count=0,
|
947 |
+
$bytes=0, $docdn=True)
|
948 |
+
{
|
949 |
+
if (strlen($name) > MAX_CONTAINER_NAME_LEN) {
|
950 |
+
throw new SyntaxException("Container name exceeds "
|
951 |
+
. "maximum allowed length.");
|
952 |
+
}
|
953 |
+
if (strpos($name, "/") !== False) {
|
954 |
+
throw new SyntaxException(
|
955 |
+
"Container names cannot contain a '/' character.");
|
956 |
+
}
|
957 |
+
$this->cfs_auth = $cfs_auth;
|
958 |
+
$this->cfs_http = $cfs_http;
|
959 |
+
$this->name = $name;
|
960 |
+
$this->object_count = $count;
|
961 |
+
$this->bytes_used = $bytes;
|
962 |
+
$this->metadata = array();
|
963 |
+
$this->cdn_enabled = NULL;
|
964 |
+
$this->cdn_uri = NULL;
|
965 |
+
$this->cdn_ssl_uri = NULL;
|
966 |
+
$this->cdn_streaming_uri = NULL;
|
967 |
+
$this->cdn_ttl = NULL;
|
968 |
+
$this->cdn_log_retention = NULL;
|
969 |
+
$this->cdn_acl_user_agent = NULL;
|
970 |
+
$this->cdn_acl_referrer = NULL;
|
971 |
+
if ($this->cfs_http->getCDNMUrl() != NULL && $docdn) {
|
972 |
+
$this->_cdn_initialize();
|
973 |
+
}
|
974 |
+
}
|
975 |
+
|
976 |
+
/**
|
977 |
+
* String representation of Container
|
978 |
+
*
|
979 |
+
* Pretty print the Container instance.
|
980 |
+
*
|
981 |
+
* @return string Container details
|
982 |
+
*/
|
983 |
+
function __toString()
|
984 |
+
{
|
985 |
+
$me = sprintf("name: %s, count: %.0f, bytes: %.0f",
|
986 |
+
$this->name, $this->object_count, $this->bytes_used);
|
987 |
+
if ($this->cfs_http->getCDNMUrl() != NULL) {
|
988 |
+
$me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f, logs retention: %s",
|
989 |
+
$this->is_public() ? "Yes" : "No",
|
990 |
+
$this->cdn_uri, $this->cdn_ttl,
|
991 |
+
$this->cdn_log_retention ? "Yes" : "No"
|
992 |
+
);
|
993 |
+
|
994 |
+
if ($this->cdn_acl_user_agent != NULL) {
|
995 |
+
$me .= ", cdn acl user agent: " . $this->cdn_acl_user_agent;
|
996 |
+
}
|
997 |
+
|
998 |
+
if ($this->cdn_acl_referrer != NULL) {
|
999 |
+
$me .= ", cdn acl referrer: " . $this->cdn_acl_referrer;
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
|
1003 |
+
}
|
1004 |
+
return $me;
|
1005 |
+
}
|
1006 |
+
|
1007 |
+
/**
|
1008 |
+
* Enable Container content to be served via CDN or modify CDN attributes
|
1009 |
+
*
|
1010 |
+
* Either enable this Container's content to be served via CDN or
|
1011 |
+
* adjust its CDN attributes. This Container will always return the
|
1012 |
+
* same CDN-enabled URI each time it is toggled public/private/public.
|
1013 |
+
*
|
1014 |
+
* Example:
|
1015 |
+
* <code>
|
1016 |
+
* # ... authentication code excluded (see previous examples) ...
|
1017 |
+
* #
|
1018 |
+
* $conn = new CF_Connection($auth);
|
1019 |
+
*
|
1020 |
+
* $public_container = $conn->create_container("public");
|
1021 |
+
*
|
1022 |
+
* # CDN-enable the container and set it's TTL for a month
|
1023 |
+
* #
|
1024 |
+
* $public_container->make_public(86400/2); # 12 hours (86400 seconds/day)
|
1025 |
+
* </code>
|
1026 |
+
*
|
1027 |
+
* @param int $ttl the time in seconds content will be cached in the CDN
|
1028 |
+
* @returns string the CDN enabled Container's URI
|
1029 |
+
* @throws CDNNotEnabledException CDN functionality not returned during auth
|
1030 |
+
* @throws AuthenticationException if auth token is not valid/expired
|
1031 |
+
* @throws InvalidResponseException unexpected response
|
1032 |
+
*/
|
1033 |
+
function make_public($ttl=86400)
|
1034 |
+
{
|
1035 |
+
if ($this->cfs_http->getCDNMUrl() == NULL) {
|
1036 |
+
throw new CDNNotEnabledException(
|
1037 |
+
"Authentication response did not indicate CDN availability");
|
1038 |
+
}
|
1039 |
+
if ($this->cdn_uri != NULL) {
|
1040 |
+
# previously published, assume we're setting new attributes
|
1041 |
+
list($status, $reason, $cdn_uri, $cdn_ssl_uri) =
|
1042 |
+
$this->cfs_http->update_cdn_container($this->name,$ttl,
|
1043 |
+
$this->cdn_log_retention,
|
1044 |
+
$this->cdn_acl_user_agent,
|
1045 |
+
$this->cdn_acl_referrer);
|
1046 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1047 |
+
# return $this->make_public($ttl);
|
1048 |
+
#}
|
1049 |
+
if ($status == 404) {
|
1050 |
+
# this instance _thinks_ the container was published, but the
|
1051 |
+
# cdn management system thinks otherwise - try again with a PUT
|
1052 |
+
list($status, $reason, $cdn_uri, $cdn_ssl_uri) =
|
1053 |
+
$this->cfs_http->add_cdn_container($this->name,$ttl);
|
1054 |
+
|
1055 |
+
}
|
1056 |
+
} else {
|
1057 |
+
# publish it for first time
|
1058 |
+
list($status, $reason, $cdn_uri, $cdn_ssl_uri) =
|
1059 |
+
$this->cfs_http->add_cdn_container($this->name,$ttl);
|
1060 |
+
}
|
1061 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1062 |
+
# return $this->make_public($ttl);
|
1063 |
+
#}
|
1064 |
+
if (!in_array($status, array(201,202))) {
|
1065 |
+
throw new InvalidResponseException(
|
1066 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1067 |
+
}
|
1068 |
+
$this->cdn_enabled = True;
|
1069 |
+
$this->cdn_ttl = $ttl;
|
1070 |
+
$this->cdn_ssl_uri = $cdn_ssl_uri;
|
1071 |
+
$this->cdn_uri = $cdn_uri;
|
1072 |
+
$this->cdn_log_retention = False;
|
1073 |
+
$this->cdn_acl_user_agent = "";
|
1074 |
+
$this->cdn_acl_referrer = "";
|
1075 |
+
return $this->cdn_uri;
|
1076 |
+
}
|
1077 |
+
/**
|
1078 |
+
* Purge Containers objects from CDN Cache.
|
1079 |
+
* Example:
|
1080 |
+
* <code>
|
1081 |
+
* # ... authentication code excluded (see previous examples) ...
|
1082 |
+
* #
|
1083 |
+
* $conn = new CF_Connection($auth);
|
1084 |
+
* $container = $conn->get_container("cdn_enabled");
|
1085 |
+
* $container->purge_from_cdn("user@domain.com");
|
1086 |
+
* # or
|
1087 |
+
* $container->purge_from_cdn();
|
1088 |
+
* # or
|
1089 |
+
* $container->purge_from_cdn("user1@domain.com,user2@domain.com");
|
1090 |
+
* @returns boolean True if successful
|
1091 |
+
* @throws CDNNotEnabledException if CDN Is not enabled on this connection
|
1092 |
+
* @throws InvalidResponseException if the response expected is not returned
|
1093 |
+
*/
|
1094 |
+
function purge_from_cdn($email=null)
|
1095 |
+
{
|
1096 |
+
if (!$this->cfs_http->getCDNMUrl())
|
1097 |
+
{
|
1098 |
+
throw new CDNNotEnabledException(
|
1099 |
+
"Authentication response did not indicate CDN availability");
|
1100 |
+
}
|
1101 |
+
$status = $this->cfs_http->purge_from_cdn($this->name, $email);
|
1102 |
+
if ($status < 199 or $status > 299) {
|
1103 |
+
throw new InvalidResponseException(
|
1104 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1105 |
+
}
|
1106 |
+
return True;
|
1107 |
+
}
|
1108 |
+
/**
|
1109 |
+
* Enable ACL restriction by User Agent for this container.
|
1110 |
+
*
|
1111 |
+
* Example:
|
1112 |
+
* <code>
|
1113 |
+
* # ... authentication code excluded (see previous examples) ...
|
1114 |
+
* #
|
1115 |
+
* $conn = new CF_Connection($auth);
|
1116 |
+
*
|
1117 |
+
* $public_container = $conn->get_container("public");
|
1118 |
+
*
|
1119 |
+
* # Enable ACL by Referrer
|
1120 |
+
* $public_container->acl_referrer("Mozilla");
|
1121 |
+
* </code>
|
1122 |
+
*
|
1123 |
+
* @returns boolean True if successful
|
1124 |
+
* @throws CDNNotEnabledException CDN functionality not returned during auth
|
1125 |
+
* @throws AuthenticationException if auth token is not valid/expired
|
1126 |
+
* @throws InvalidResponseException unexpected response
|
1127 |
+
*/
|
1128 |
+
function acl_user_agent($cdn_acl_user_agent="") {
|
1129 |
+
if ($this->cfs_http->getCDNMUrl() == NULL) {
|
1130 |
+
throw new CDNNotEnabledException(
|
1131 |
+
"Authentication response did not indicate CDN availability");
|
1132 |
+
}
|
1133 |
+
list($status,$reason) =
|
1134 |
+
$this->cfs_http->update_cdn_container($this->name,
|
1135 |
+
$this->cdn_ttl,
|
1136 |
+
$this->cdn_log_retention,
|
1137 |
+
$cdn_acl_user_agent,
|
1138 |
+
$this->cdn_acl_referrer
|
1139 |
+
);
|
1140 |
+
if (!in_array($status, array(202,404))) {
|
1141 |
+
throw new InvalidResponseException(
|
1142 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1143 |
+
}
|
1144 |
+
$this->cdn_acl_user_agent = $cdn_acl_user_agent;
|
1145 |
+
return True;
|
1146 |
+
}
|
1147 |
+
|
1148 |
+
/**
|
1149 |
+
* Enable ACL restriction by referer for this container.
|
1150 |
+
*
|
1151 |
+
* Example:
|
1152 |
+
* <code>
|
1153 |
+
* # ... authentication code excluded (see previous examples) ...
|
1154 |
+
* #
|
1155 |
+
* $conn = new CF_Connection($auth);
|
1156 |
+
*
|
1157 |
+
* $public_container = $conn->get_container("public");
|
1158 |
+
*
|
1159 |
+
* # Enable Referrer
|
1160 |
+
* $public_container->acl_referrer("http://www.example.com/gallery.php");
|
1161 |
+
* </code>
|
1162 |
+
*
|
1163 |
+
* @returns boolean True if successful
|
1164 |
+
* @throws CDNNotEnabledException CDN functionality not returned during auth
|
1165 |
+
* @throws AuthenticationException if auth token is not valid/expired
|
1166 |
+
* @throws InvalidResponseException unexpected response
|
1167 |
+
*/
|
1168 |
+
function acl_referrer($cdn_acl_referrer="") {
|
1169 |
+
if ($this->cfs_http->getCDNMUrl() == NULL) {
|
1170 |
+
throw new CDNNotEnabledException(
|
1171 |
+
"Authentication response did not indicate CDN availability");
|
1172 |
+
}
|
1173 |
+
list($status,$reason) =
|
1174 |
+
$this->cfs_http->update_cdn_container($this->name,
|
1175 |
+
$this->cdn_ttl,
|
1176 |
+
$this->cdn_log_retention,
|
1177 |
+
$this->cdn_acl_user_agent,
|
1178 |
+
$cdn_acl_referrer
|
1179 |
+
);
|
1180 |
+
if (!in_array($status, array(202,404))) {
|
1181 |
+
throw new InvalidResponseException(
|
1182 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1183 |
+
}
|
1184 |
+
$this->cdn_acl_referrer = $cdn_acl_referrer;
|
1185 |
+
return True;
|
1186 |
+
}
|
1187 |
+
|
1188 |
+
/**
|
1189 |
+
* Enable log retention for this CDN container.
|
1190 |
+
*
|
1191 |
+
* Enable CDN log retention on the container. If enabled logs will
|
1192 |
+
* be periodically (at unpredictable intervals) compressed and
|
1193 |
+
* uploaded to a ".CDN_ACCESS_LOGS" container in the form of
|
1194 |
+
* "container_name.YYYYMMDDHH-XXXX.gz". Requires CDN be enabled on
|
1195 |
+
* the account.
|
1196 |
+
*
|
1197 |
+
* Example:
|
1198 |
+
* <code>
|
1199 |
+
* # ... authentication code excluded (see previous examples) ...
|
1200 |
+
* #
|
1201 |
+
* $conn = new CF_Connection($auth);
|
1202 |
+
*
|
1203 |
+
* $public_container = $conn->get_container("public");
|
1204 |
+
*
|
1205 |
+
* # Enable logs retention.
|
1206 |
+
* $public_container->log_retention(True);
|
1207 |
+
* </code>
|
1208 |
+
*
|
1209 |
+
* @returns boolean True if successful
|
1210 |
+
* @throws CDNNotEnabledException CDN functionality not returned during auth
|
1211 |
+
* @throws AuthenticationException if auth token is not valid/expired
|
1212 |
+
* @throws InvalidResponseException unexpected response
|
1213 |
+
*/
|
1214 |
+
function log_retention($cdn_log_retention=False) {
|
1215 |
+
if ($this->cfs_http->getCDNMUrl() == NULL) {
|
1216 |
+
throw new CDNNotEnabledException(
|
1217 |
+
"Authentication response did not indicate CDN availability");
|
1218 |
+
}
|
1219 |
+
list($status,$reason) =
|
1220 |
+
$this->cfs_http->update_cdn_container($this->name,
|
1221 |
+
$this->cdn_ttl,
|
1222 |
+
$cdn_log_retention,
|
1223 |
+
$this->cdn_acl_user_agent,
|
1224 |
+
$this->cdn_acl_referrer
|
1225 |
+
);
|
1226 |
+
if (!in_array($status, array(202,404))) {
|
1227 |
+
throw new InvalidResponseException(
|
1228 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1229 |
+
}
|
1230 |
+
$this->cdn_log_retention = $cdn_log_retention;
|
1231 |
+
return True;
|
1232 |
+
}
|
1233 |
+
|
1234 |
+
/**
|
1235 |
+
* Disable the CDN sharing for this container
|
1236 |
+
*
|
1237 |
+
* Use this method to disallow distribution into the CDN of this Container's
|
1238 |
+
* content.
|
1239 |
+
*
|
1240 |
+
* NOTE: Any content already cached in the CDN will continue to be served
|
1241 |
+
* from its cache until the TTL expiration transpires. The default
|
1242 |
+
* TTL is typically one day, so "privatizing" the Container will take
|
1243 |
+
* up to 24 hours before the content is purged from the CDN cache.
|
1244 |
+
*
|
1245 |
+
* Example:
|
1246 |
+
* <code>
|
1247 |
+
* # ... authentication code excluded (see previous examples) ...
|
1248 |
+
* #
|
1249 |
+
* $conn = new CF_Connection($auth);
|
1250 |
+
*
|
1251 |
+
* $public_container = $conn->get_container("public");
|
1252 |
+
*
|
1253 |
+
* # Disable CDN accessability
|
1254 |
+
* # ... still cached up to a month based on previous example
|
1255 |
+
* #
|
1256 |
+
* $public_container->make_private();
|
1257 |
+
* </code>
|
1258 |
+
*
|
1259 |
+
* @returns boolean True if successful
|
1260 |
+
* @throws CDNNotEnabledException CDN functionality not returned during auth
|
1261 |
+
* @throws AuthenticationException if auth token is not valid/expired
|
1262 |
+
* @throws InvalidResponseException unexpected response
|
1263 |
+
*/
|
1264 |
+
function make_private()
|
1265 |
+
{
|
1266 |
+
if ($this->cfs_http->getCDNMUrl() == NULL) {
|
1267 |
+
throw new CDNNotEnabledException(
|
1268 |
+
"Authentication response did not indicate CDN availability");
|
1269 |
+
}
|
1270 |
+
list($status,$reason) = $this->cfs_http->remove_cdn_container($this->name);
|
1271 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1272 |
+
# return $this->make_private();
|
1273 |
+
#}
|
1274 |
+
if (!in_array($status, array(202,404))) {
|
1275 |
+
throw new InvalidResponseException(
|
1276 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1277 |
+
}
|
1278 |
+
$this->cdn_enabled = False;
|
1279 |
+
$this->cdn_ttl = NULL;
|
1280 |
+
$this->cdn_uri = NULL;
|
1281 |
+
$this->cdn_ssl_uri = NULL;
|
1282 |
+
$this->cdn_streaming_uri - NULL;
|
1283 |
+
$this->cdn_log_retention = NULL;
|
1284 |
+
$this->cdn_acl_user_agent = NULL;
|
1285 |
+
$this->cdn_acl_referrer = NULL;
|
1286 |
+
return True;
|
1287 |
+
}
|
1288 |
+
|
1289 |
+
/**
|
1290 |
+
* Check if this Container is being publicly served via CDN
|
1291 |
+
*
|
1292 |
+
* Use this method to determine if the Container's content is currently
|
1293 |
+
* available through the CDN.
|
1294 |
+
*
|
1295 |
+
* Example:
|
1296 |
+
* <code>
|
1297 |
+
* # ... authentication code excluded (see previous examples) ...
|
1298 |
+
* #
|
1299 |
+
* $conn = new CF_Connection($auth);
|
1300 |
+
*
|
1301 |
+
* $public_container = $conn->get_container("public");
|
1302 |
+
*
|
1303 |
+
* # Display CDN accessability
|
1304 |
+
* #
|
1305 |
+
* $public_container->is_public() ? print "Yes" : print "No";
|
1306 |
+
* </code>
|
1307 |
+
*
|
1308 |
+
* @returns boolean True if enabled, False otherwise
|
1309 |
+
*/
|
1310 |
+
function is_public()
|
1311 |
+
{
|
1312 |
+
return $this->cdn_enabled == True ? True : False;
|
1313 |
+
}
|
1314 |
+
|
1315 |
+
/**
|
1316 |
+
* Create a new remote storage Object
|
1317 |
+
*
|
1318 |
+
* Return a new Object instance. If the remote storage Object exists,
|
1319 |
+
* the instance's attributes are populated.
|
1320 |
+
*
|
1321 |
+
* Example:
|
1322 |
+
* <code>
|
1323 |
+
* # ... authentication code excluded (see previous examples) ...
|
1324 |
+
* #
|
1325 |
+
* $conn = new CF_Connection($auth);
|
1326 |
+
*
|
1327 |
+
* $public_container = $conn->get_container("public");
|
1328 |
+
*
|
1329 |
+
* # This creates a local instance of a storage object but only creates
|
1330 |
+
* # it in the storage system when the object's write() method is called.
|
1331 |
+
* #
|
1332 |
+
* $pic = $public_container->create_object("baby.jpg");
|
1333 |
+
* </code>
|
1334 |
+
*
|
1335 |
+
* @param string $obj_name name of storage Object
|
1336 |
+
* @return obj CF_Object instance
|
1337 |
+
*/
|
1338 |
+
function create_object($obj_name=NULL)
|
1339 |
+
{
|
1340 |
+
return new CF_Object($this, $obj_name);
|
1341 |
+
}
|
1342 |
+
|
1343 |
+
/**
|
1344 |
+
* Return an Object instance for the remote storage Object
|
1345 |
+
*
|
1346 |
+
* Given a name, return a Object instance representing the
|
1347 |
+
* remote storage object.
|
1348 |
+
*
|
1349 |
+
* Example:
|
1350 |
+
* <code>
|
1351 |
+
* # ... authentication code excluded (see previous examples) ...
|
1352 |
+
* #
|
1353 |
+
* $conn = new CF_Connection($auth);
|
1354 |
+
*
|
1355 |
+
* $public_container = $conn->get_container("public");
|
1356 |
+
*
|
1357 |
+
* # This call only fetches header information and not the content of
|
1358 |
+
* # the storage object. Use the Object's read() or stream() methods
|
1359 |
+
* # to obtain the object's data.
|
1360 |
+
* #
|
1361 |
+
* $pic = $public_container->get_object("baby.jpg");
|
1362 |
+
* </code>
|
1363 |
+
*
|
1364 |
+
* @param string $obj_name name of storage Object
|
1365 |
+
* @return obj CF_Object instance
|
1366 |
+
*/
|
1367 |
+
function get_object($obj_name=NULL)
|
1368 |
+
{
|
1369 |
+
return new CF_Object($this, $obj_name, True);
|
1370 |
+
}
|
1371 |
+
|
1372 |
+
/**
|
1373 |
+
* Return a list of Objects
|
1374 |
+
*
|
1375 |
+
* Return an array of strings listing the Object names in this Container.
|
1376 |
+
*
|
1377 |
+
* Example:
|
1378 |
+
* <code>
|
1379 |
+
* # ... authentication code excluded (see previous examples) ...
|
1380 |
+
* #
|
1381 |
+
* $images = $conn->get_container("my photos");
|
1382 |
+
*
|
1383 |
+
* # Grab the list of all storage objects
|
1384 |
+
* #
|
1385 |
+
* $all_objects = $images->list_objects();
|
1386 |
+
*
|
1387 |
+
* # Grab subsets of all storage objects
|
1388 |
+
* #
|
1389 |
+
* $first_ten = $images->list_objects(10);
|
1390 |
+
*
|
1391 |
+
* # Note the use of the previous result's last object name being
|
1392 |
+
* # used as the 'marker' parameter to fetch the next 10 objects
|
1393 |
+
* #
|
1394 |
+
* $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
|
1395 |
+
*
|
1396 |
+
* # Grab images starting with "birthday_party" and default limit/marker
|
1397 |
+
* # to match all photos with that prefix
|
1398 |
+
* #
|
1399 |
+
* $prefixed = $images->list_objects(0, NULL, "birthday");
|
1400 |
+
*
|
1401 |
+
* # Assuming you have created the appropriate directory marker Objects,
|
1402 |
+
* # you can traverse your pseudo-hierarchical containers
|
1403 |
+
* # with the "path" argument.
|
1404 |
+
* #
|
1405 |
+
* $animals = $images->list_objects(0,NULL,NULL,"pictures/animals");
|
1406 |
+
* $dogs = $images->list_objects(0,NULL,NULL,"pictures/animals/dogs");
|
1407 |
+
* </code>
|
1408 |
+
*
|
1409 |
+
* @param int $limit <i>optional</i> only return $limit names
|
1410 |
+
* @param int $marker <i>optional</i> subset of names starting at $marker
|
1411 |
+
* @param string $prefix <i>optional</i> Objects whose names begin with $prefix
|
1412 |
+
* @param string $path <i>optional</i> only return results under "pathname"
|
1413 |
+
* @return array array of strings
|
1414 |
+
* @throws InvalidResponseException unexpected response
|
1415 |
+
*/
|
1416 |
+
function list_objects($limit=0, $marker=NULL, $prefix=NULL, $path=NULL)
|
1417 |
+
{
|
1418 |
+
list($status, $reason, $obj_list) =
|
1419 |
+
$this->cfs_http->list_objects($this->name, $limit,
|
1420 |
+
$marker, $prefix, $path);
|
1421 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1422 |
+
# return $this->list_objects($limit, $marker, $prefix, $path);
|
1423 |
+
#}
|
1424 |
+
if ($status < 200 || $status > 299) {
|
1425 |
+
throw new InvalidResponseException(
|
1426 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1427 |
+
}
|
1428 |
+
return $obj_list;
|
1429 |
+
}
|
1430 |
+
|
1431 |
+
/**
|
1432 |
+
* Return an array of Objects
|
1433 |
+
*
|
1434 |
+
* Return an array of Object instances in this Container.
|
1435 |
+
*
|
1436 |
+
* Example:
|
1437 |
+
* <code>
|
1438 |
+
* # ... authentication code excluded (see previous examples) ...
|
1439 |
+
* #
|
1440 |
+
* $images = $conn->get_container("my photos");
|
1441 |
+
*
|
1442 |
+
* # Grab the list of all storage objects
|
1443 |
+
* #
|
1444 |
+
* $all_objects = $images->get_objects();
|
1445 |
+
*
|
1446 |
+
* # Grab subsets of all storage objects
|
1447 |
+
* #
|
1448 |
+
* $first_ten = $images->get_objects(10);
|
1449 |
+
*
|
1450 |
+
* # Note the use of the previous result's last object name being
|
1451 |
+
* # used as the 'marker' parameter to fetch the next 10 objects
|
1452 |
+
* #
|
1453 |
+
* $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
|
1454 |
+
*
|
1455 |
+
* # Grab images starting with "birthday_party" and default limit/marker
|
1456 |
+
* # to match all photos with that prefix
|
1457 |
+
* #
|
1458 |
+
* $prefixed = $images->get_objects(0, NULL, "birthday");
|
1459 |
+
*
|
1460 |
+
* # Assuming you have created the appropriate directory marker Objects,
|
1461 |
+
* # you can traverse your pseudo-hierarchical containers
|
1462 |
+
* # with the "path" argument.
|
1463 |
+
* #
|
1464 |
+
* $animals = $images->get_objects(0,NULL,NULL,"pictures/animals");
|
1465 |
+
* $dogs = $images->get_objects(0,NULL,NULL,"pictures/animals/dogs");
|
1466 |
+
* </code>
|
1467 |
+
*
|
1468 |
+
* @param int $limit <i>optional</i> only return $limit names
|
1469 |
+
* @param int $marker <i>optional</i> subset of names starting at $marker
|
1470 |
+
* @param string $prefix <i>optional</i> Objects whose names begin with $prefix
|
1471 |
+
* @param string $path <i>optional</i> only return results under "pathname"
|
1472 |
+
* @return array array of strings
|
1473 |
+
* @throws InvalidResponseException unexpected response
|
1474 |
+
*/
|
1475 |
+
function get_objects($limit=0, $marker=NULL, $prefix=NULL, $path=NULL, $delimiter=NULL)
|
1476 |
+
{
|
1477 |
+
list($status, $reason, $obj_array) =
|
1478 |
+
$this->cfs_http->get_objects($this->name, $limit,
|
1479 |
+
$marker, $prefix, $path, $delimiter);
|
1480 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1481 |
+
# return $this->get_objects($limit, $marker, $prefix, $path);
|
1482 |
+
#}
|
1483 |
+
if ($status < 200 || $status > 299) {
|
1484 |
+
throw new InvalidResponseException(
|
1485 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1486 |
+
}
|
1487 |
+
$objects = array();
|
1488 |
+
foreach ($obj_array as $obj) {
|
1489 |
+
if(!isset($obj['subdir'])) {
|
1490 |
+
$tmp = new CF_Object($this, $obj["name"], False, False);
|
1491 |
+
$tmp->content_type = $obj["content_type"];
|
1492 |
+
$tmp->content_length = (float) $obj["bytes"];
|
1493 |
+
$tmp->set_etag($obj["hash"]);
|
1494 |
+
$tmp->last_modified = $obj["last_modified"];
|
1495 |
+
$objects[] = $tmp;
|
1496 |
+
}
|
1497 |
+
}
|
1498 |
+
return $objects;
|
1499 |
+
}
|
1500 |
+
|
1501 |
+
/**
|
1502 |
+
* Copy a remote storage Object to a target Container
|
1503 |
+
*
|
1504 |
+
* Given an Object instance or name and a target Container instance or name, copy copies the remote Object
|
1505 |
+
* and all associated metadata.
|
1506 |
+
*
|
1507 |
+
* Example:
|
1508 |
+
* <code>
|
1509 |
+
* # ... authentication code excluded (see previous examples) ...
|
1510 |
+
* #
|
1511 |
+
* $conn = new CF_Connection($auth);
|
1512 |
+
*
|
1513 |
+
* $images = $conn->get_container("my photos");
|
1514 |
+
*
|
1515 |
+
* # Copy specific object
|
1516 |
+
* #
|
1517 |
+
* $images->copy_object_to("disco_dancing.jpg","container_target");
|
1518 |
+
* </code>
|
1519 |
+
*
|
1520 |
+
* @param obj $obj name or instance of Object to copy
|
1521 |
+
* @param obj $container_target name or instance of target Container
|
1522 |
+
* @param string $dest_obj_name name of target object (optional - uses source name if omitted)
|
1523 |
+
* @param array $metadata metadata array for new object (optional)
|
1524 |
+
* @param array $headers header fields array for the new object (optional)
|
1525 |
+
* @return boolean <kbd>true</kbd> if successfully copied
|
1526 |
+
* @throws SyntaxException invalid Object/Container name
|
1527 |
+
* @throws NoSuchObjectException remote Object does not exist
|
1528 |
+
* @throws InvalidResponseException unexpected response
|
1529 |
+
*/
|
1530 |
+
function copy_object_to($obj,$container_target,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
|
1531 |
+
{
|
1532 |
+
$obj_name = NULL;
|
1533 |
+
if (is_object($obj)) {
|
1534 |
+
if (get_class($obj) == "CF_Object") {
|
1535 |
+
$obj_name = $obj->name;
|
1536 |
+
}
|
1537 |
+
}
|
1538 |
+
if (is_string($obj)) {
|
1539 |
+
$obj_name = $obj;
|
1540 |
+
}
|
1541 |
+
if (!$obj_name) {
|
1542 |
+
throw new SyntaxException("Object name not set.");
|
1543 |
+
}
|
1544 |
+
|
1545 |
+
if ($dest_obj_name === NULL) {
|
1546 |
+
$dest_obj_name = $obj_name;
|
1547 |
+
}
|
1548 |
+
|
1549 |
+
$container_name_target = NULL;
|
1550 |
+
if (is_object($container_target)) {
|
1551 |
+
if (get_class($container_target) == "CF_Container") {
|
1552 |
+
$container_name_target = $container_target->name;
|
1553 |
+
}
|
1554 |
+
}
|
1555 |
+
if (is_string($container_target)) {
|
1556 |
+
$container_name_target = $container_target;
|
1557 |
+
}
|
1558 |
+
if (!$container_name_target) {
|
1559 |
+
throw new SyntaxException("Container name target not set.");
|
1560 |
+
}
|
1561 |
+
|
1562 |
+
$status = $this->cfs_http->copy_object($obj_name,$dest_obj_name,$this->name,$container_name_target,$metadata,$headers);
|
1563 |
+
if ($status == 404) {
|
1564 |
+
$m = "Specified object '".$this->name."/".$obj_name;
|
1565 |
+
$m.= "' did not exist as source to copy from or '".$container_name_target."' did not exist as target to copy to.";
|
1566 |
+
throw new NoSuchObjectException($m);
|
1567 |
+
}
|
1568 |
+
if ($status < 200 || $status > 299) {
|
1569 |
+
throw new InvalidResponseException(
|
1570 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1571 |
+
}
|
1572 |
+
return true;
|
1573 |
+
}
|
1574 |
+
|
1575 |
+
/**
|
1576 |
+
* Copy a remote storage Object from a source Container
|
1577 |
+
*
|
1578 |
+
* Given an Object instance or name and a source Container instance or name, copy copies the remote Object
|
1579 |
+
* and all associated metadata.
|
1580 |
+
*
|
1581 |
+
* Example:
|
1582 |
+
* <code>
|
1583 |
+
* # ... authentication code excluded (see previous examples) ...
|
1584 |
+
* #
|
1585 |
+
* $conn = new CF_Connection($auth);
|
1586 |
+
*
|
1587 |
+
* $images = $conn->get_container("my photos");
|
1588 |
+
*
|
1589 |
+
* # Copy specific object
|
1590 |
+
* #
|
1591 |
+
* $images->copy_object_from("disco_dancing.jpg","container_source");
|
1592 |
+
* </code>
|
1593 |
+
*
|
1594 |
+
* @param obj $obj name or instance of Object to copy
|
1595 |
+
* @param obj $container_source name or instance of source Container
|
1596 |
+
* @param string $dest_obj_name name of target object (optional - uses source name if omitted)
|
1597 |
+
* @param array $metadata metadata array for new object (optional)
|
1598 |
+
* @param array $headers header fields array for the new object (optional)
|
1599 |
+
* @return boolean <kbd>true</kbd> if successfully copied
|
1600 |
+
* @throws SyntaxException invalid Object/Container name
|
1601 |
+
* @throws NoSuchObjectException remote Object does not exist
|
1602 |
+
* @throws InvalidResponseException unexpected response
|
1603 |
+
*/
|
1604 |
+
function copy_object_from($obj,$container_source,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
|
1605 |
+
{
|
1606 |
+
$obj_name = NULL;
|
1607 |
+
if (is_object($obj)) {
|
1608 |
+
if (get_class($obj) == "CF_Object") {
|
1609 |
+
$obj_name = $obj->name;
|
1610 |
+
}
|
1611 |
+
}
|
1612 |
+
if (is_string($obj)) {
|
1613 |
+
$obj_name = $obj;
|
1614 |
+
}
|
1615 |
+
if (!$obj_name) {
|
1616 |
+
throw new SyntaxException("Object name not set.");
|
1617 |
+
}
|
1618 |
+
|
1619 |
+
if ($dest_obj_name === NULL) {
|
1620 |
+
$dest_obj_name = $obj_name;
|
1621 |
+
}
|
1622 |
+
|
1623 |
+
$container_name_source = NULL;
|
1624 |
+
if (is_object($container_source)) {
|
1625 |
+
if (get_class($container_source) == "CF_Container") {
|
1626 |
+
$container_name_source = $container_source->name;
|
1627 |
+
}
|
1628 |
+
}
|
1629 |
+
if (is_string($container_source)) {
|
1630 |
+
$container_name_source = $container_source;
|
1631 |
+
}
|
1632 |
+
if (!$container_name_source) {
|
1633 |
+
throw new SyntaxException("Container name source not set.");
|
1634 |
+
}
|
1635 |
+
|
1636 |
+
$status = $this->cfs_http->copy_object($obj_name,$dest_obj_name,$container_name_source,$this->name,$metadata,$headers);
|
1637 |
+
if ($status == 404) {
|
1638 |
+
$m = "Specified object '".$container_name_source."/".$obj_name;
|
1639 |
+
$m.= "' did not exist as source to copy from or '".$this->name."/".$obj_name."' did not exist as target to copy to.";
|
1640 |
+
throw new NoSuchObjectException($m);
|
1641 |
+
}
|
1642 |
+
if ($status < 200 || $status > 299) {
|
1643 |
+
throw new InvalidResponseException(
|
1644 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1645 |
+
}
|
1646 |
+
|
1647 |
+
return true;
|
1648 |
+
}
|
1649 |
+
|
1650 |
+
/**
|
1651 |
+
* Move a remote storage Object to a target Container
|
1652 |
+
*
|
1653 |
+
* Given an Object instance or name and a target Container instance or name, move copies the remote Object
|
1654 |
+
* and all associated metadata and deletes the source Object afterwards
|
1655 |
+
*
|
1656 |
+
* Example:
|
1657 |
+
* <code>
|
1658 |
+
* # ... authentication code excluded (see previous examples) ...
|
1659 |
+
* #
|
1660 |
+
* $conn = new CF_Connection($auth);
|
1661 |
+
*
|
1662 |
+
* $images = $conn->get_container("my photos");
|
1663 |
+
*
|
1664 |
+
* # Move specific object
|
1665 |
+
* #
|
1666 |
+
* $images->move_object_to("disco_dancing.jpg","container_target");
|
1667 |
+
* </code>
|
1668 |
+
*
|
1669 |
+
* @param obj $obj name or instance of Object to move
|
1670 |
+
* @param obj $container_target name or instance of target Container
|
1671 |
+
* @param string $dest_obj_name name of target object (optional - uses source name if omitted)
|
1672 |
+
* @param array $metadata metadata array for new object (optional)
|
1673 |
+
* @param array $headers header fields array for the new object (optional)
|
1674 |
+
* @return boolean <kbd>true</kbd> if successfully moved
|
1675 |
+
* @throws SyntaxException invalid Object/Container name
|
1676 |
+
* @throws NoSuchObjectException remote Object does not exist
|
1677 |
+
* @throws InvalidResponseException unexpected response
|
1678 |
+
*/
|
1679 |
+
function move_object_to($obj,$container_target,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
|
1680 |
+
{
|
1681 |
+
$retVal = false;
|
1682 |
+
|
1683 |
+
if(self::copy_object_to($obj,$container_target,$dest_obj_name,$metadata,$headers)) {
|
1684 |
+
$retVal = self::delete_object($obj,$this->name);
|
1685 |
+
}
|
1686 |
+
|
1687 |
+
return $retVal;
|
1688 |
+
}
|
1689 |
+
|
1690 |
+
/**
|
1691 |
+
* Move a remote storage Object from a source Container
|
1692 |
+
*
|
1693 |
+
* Given an Object instance or name and a source Container instance or name, move copies the remote Object
|
1694 |
+
* and all associated metadata and deletes the source Object afterwards
|
1695 |
+
*
|
1696 |
+
* Example:
|
1697 |
+
* <code>
|
1698 |
+
* # ... authentication code excluded (see previous examples) ...
|
1699 |
+
* #
|
1700 |
+
* $conn = new CF_Connection($auth);
|
1701 |
+
*
|
1702 |
+
* $images = $conn->get_container("my photos");
|
1703 |
+
*
|
1704 |
+
* # Move specific object
|
1705 |
+
* #
|
1706 |
+
* $images->move_object_from("disco_dancing.jpg","container_target");
|
1707 |
+
* </code>
|
1708 |
+
*
|
1709 |
+
* @param obj $obj name or instance of Object to move
|
1710 |
+
* @param obj $container_source name or instance of target Container
|
1711 |
+
* @param string $dest_obj_name name of target object (optional - uses source name if omitted)
|
1712 |
+
* @param array $metadata metadata array for new object (optional)
|
1713 |
+
* @param array $headers header fields array for the new object (optional)
|
1714 |
+
* @return boolean <kbd>true</kbd> if successfully moved
|
1715 |
+
* @throws SyntaxException invalid Object/Container name
|
1716 |
+
* @throws NoSuchObjectException remote Object does not exist
|
1717 |
+
* @throws InvalidResponseException unexpected response
|
1718 |
+
*/
|
1719 |
+
function move_object_from($obj,$container_source,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
|
1720 |
+
{
|
1721 |
+
$retVal = false;
|
1722 |
+
|
1723 |
+
if(self::copy_object_from($obj,$container_source,$dest_obj_name,$metadata,$headers)) {
|
1724 |
+
$retVal = self::delete_object($obj,$container_source);
|
1725 |
+
}
|
1726 |
+
|
1727 |
+
return $retVal;
|
1728 |
+
}
|
1729 |
+
|
1730 |
+
/**
|
1731 |
+
* Delete a remote storage Object
|
1732 |
+
*
|
1733 |
+
* Given an Object instance or name, permanently remove the remote Object
|
1734 |
+
* and all associated metadata.
|
1735 |
+
*
|
1736 |
+
* Example:
|
1737 |
+
* <code>
|
1738 |
+
* # ... authentication code excluded (see previous examples) ...
|
1739 |
+
* #
|
1740 |
+
* $conn = new CF_Connection($auth);
|
1741 |
+
*
|
1742 |
+
* $images = $conn->get_container("my photos");
|
1743 |
+
*
|
1744 |
+
* # Delete specific object
|
1745 |
+
* #
|
1746 |
+
* $images->delete_object("disco_dancing.jpg");
|
1747 |
+
* </code>
|
1748 |
+
*
|
1749 |
+
* @param obj $obj name or instance of Object to delete
|
1750 |
+
* @param obj $container name or instance of Container in which the object resides (optional)
|
1751 |
+
* @return boolean <kbd>True</kbd> if successfully removed
|
1752 |
+
* @throws SyntaxException invalid Object name
|
1753 |
+
* @throws NoSuchObjectException remote Object does not exist
|
1754 |
+
* @throws InvalidResponseException unexpected response
|
1755 |
+
*/
|
1756 |
+
function delete_object($obj,$container=NULL)
|
1757 |
+
{
|
1758 |
+
$obj_name = NULL;
|
1759 |
+
if (is_object($obj)) {
|
1760 |
+
if (get_class($obj) == "CF_Object") {
|
1761 |
+
$obj_name = $obj->name;
|
1762 |
+
}
|
1763 |
+
}
|
1764 |
+
if (is_string($obj)) {
|
1765 |
+
$obj_name = $obj;
|
1766 |
+
}
|
1767 |
+
if (!$obj_name) {
|
1768 |
+
throw new SyntaxException("Object name not set.");
|
1769 |
+
}
|
1770 |
+
|
1771 |
+
$container_name = NULL;
|
1772 |
+
|
1773 |
+
if($container === NULL) {
|
1774 |
+
$container_name = $this->name;
|
1775 |
+
}
|
1776 |
+
else {
|
1777 |
+
if (is_object($container)) {
|
1778 |
+
if (get_class($container) == "CF_Container") {
|
1779 |
+
$container_name = $container->name;
|
1780 |
+
}
|
1781 |
+
}
|
1782 |
+
if (is_string($container)) {
|
1783 |
+
$container_name = $container;
|
1784 |
+
}
|
1785 |
+
if (!$container_name) {
|
1786 |
+
throw new SyntaxException("Container name source not set.");
|
1787 |
+
}
|
1788 |
+
}
|
1789 |
+
|
1790 |
+
$status = $this->cfs_http->delete_object($container_name, $obj_name);
|
1791 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1792 |
+
# return $this->delete_object($obj);
|
1793 |
+
#}
|
1794 |
+
if ($status == 404) {
|
1795 |
+
$m = "Specified object '".$container_name."/".$obj_name;
|
1796 |
+
$m.= "' did not exist to delete.";
|
1797 |
+
throw new NoSuchObjectException($m);
|
1798 |
+
}
|
1799 |
+
if ($status != 204) {
|
1800 |
+
throw new InvalidResponseException(
|
1801 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1802 |
+
}
|
1803 |
+
return True;
|
1804 |
+
}
|
1805 |
+
|
1806 |
+
/**
|
1807 |
+
* Helper function to create "path" elements for a given Object name
|
1808 |
+
*
|
1809 |
+
* Given an Object whos name contains '/' path separators, this function
|
1810 |
+
* will create the "directory marker" Objects of one byte with the
|
1811 |
+
* Content-Type of "application/directory".
|
1812 |
+
*
|
1813 |
+
* It assumes the last element of the full path is the "real" Object
|
1814 |
+
* and does NOT create a remote storage Object for that last element.
|
1815 |
+
*/
|
1816 |
+
function create_paths($path_name)
|
1817 |
+
{
|
1818 |
+
if ($path_name[0] == '/') {
|
1819 |
+
$path_name = mb_substr($path_name, 0, 1);
|
1820 |
+
}
|
1821 |
+
$elements = explode('/', $path_name, -1);
|
1822 |
+
$build_path = "";
|
1823 |
+
foreach ($elements as $idx => $val) {
|
1824 |
+
if (!$build_path) {
|
1825 |
+
$build_path = $val;
|
1826 |
+
} else {
|
1827 |
+
$build_path .= "/" . $val;
|
1828 |
+
}
|
1829 |
+
$obj = new CF_Object($this, $build_path);
|
1830 |
+
$obj->content_type = "application/directory";
|
1831 |
+
$obj->write(".", 1);
|
1832 |
+
}
|
1833 |
+
}
|
1834 |
+
|
1835 |
+
/**
|
1836 |
+
* Internal method to grab CDN/Container info if appropriate to do so
|
1837 |
+
*
|
1838 |
+
* @throws InvalidResponseException unexpected response
|
1839 |
+
*/
|
1840 |
+
private function _cdn_initialize()
|
1841 |
+
{
|
1842 |
+
list($status, $reason, $cdn_enabled, $cdn_ssl_uri, $cdn_streaming_uri, $cdn_uri, $cdn_ttl,
|
1843 |
+
$cdn_log_retention, $cdn_acl_user_agent, $cdn_acl_referrer) =
|
1844 |
+
$this->cfs_http->head_cdn_container($this->name);
|
1845 |
+
#if ($status == 401 && $this->_re_auth()) {
|
1846 |
+
# return $this->_cdn_initialize();
|
1847 |
+
#}
|
1848 |
+
if (!in_array($status, array(204,404))) {
|
1849 |
+
throw new InvalidResponseException(
|
1850 |
+
"Invalid response (".$status."): ".$this->cfs_http->get_error());
|
1851 |
+
}
|
1852 |
+
$this->cdn_enabled = $cdn_enabled;
|
1853 |
+
$this->cdn_streaming_uri = $cdn_streaming_uri;
|
1854 |
+
$this->cdn_ssl_uri = $cdn_ssl_uri;
|
1855 |
+
$this->cdn_uri = $cdn_uri;
|
1856 |
+
$this->cdn_ttl = $cdn_ttl;
|
1857 |
+
$this->cdn_log_retention = $cdn_log_retention;
|
1858 |
+
$this->cdn_acl_user_agent = $cdn_acl_user_agent;
|
1859 |
+
$this->cdn_acl_referrer = $cdn_acl_referrer;
|
1860 |
+
}
|
1861 |
+
|
1862 |
+
#private function _re_auth()
|
1863 |
+
#{
|
1864 |
+
# $new_auth = new CF_Authentication(
|
1865 |
+
# $this->cfs_auth->username,
|
1866 |
+
# $this->cfs_auth->api_key,
|
1867 |
+
# $this->cfs_auth->auth_host,
|
1868 |
+
# $this->cfs_auth->account);
|
1869 |
+
# $new_auth->authenticate();
|
1870 |
+
# $this->cfs_auth = $new_auth;
|
1871 |
+
# $this->cfs_http->setCFAuth($this->cfs_auth);
|
1872 |
+
# return True;
|
1873 |
+
#}
|
1874 |
+
}
|
1875 |
+
|
1876 |
+
|
1877 |
+
/**
|
1878 |
+
* Object operations
|
1879 |
+
*
|
1880 |
+
* An Object is analogous to a file on a conventional filesystem. You can
|
1881 |
+
* read data from, or write data to your Objects. You can also associate
|
1882 |
+
* arbitrary metadata with them.
|
1883 |
+
*
|
1884 |
+
* @package php-cloudfiles
|
1885 |
+
*/
|
1886 |
+
class CF_Object
|
1887 |
+
{
|
1888 |
+
public $container;
|
1889 |
+
public $name;
|
1890 |
+
public $last_modified;
|
1891 |
+
public $content_type;
|
1892 |
+
public $content_length;
|
1893 |
+
public $metadata;
|
1894 |
+
public $headers;
|
1895 |
+
public $manifest;
|
1896 |
+
private $etag;
|
1897 |
+
|
1898 |
+
/**
|
1899 |
+
* Class constructor
|
1900 |
+
*
|
1901 |
+
* @param obj $container CF_Container instance
|
1902 |
+
* @param string $name name of Object
|
1903 |
+
* @param boolean $force_exists if set, throw an error if Object doesn't exist
|
1904 |
+
*/
|
1905 |
+
function __construct(&$container, $name, $force_exists=False, $dohead=True)
|
1906 |
+
{
|
1907 |
+
if ($name[0] == "/") {
|
1908 |
+
$r = "Object name '".$name;
|
1909 |
+
$r .= "' cannot contain begin with a '/' character.";
|
1910 |
+
throw new SyntaxException($r);
|
1911 |
+
}
|
1912 |
+
if (strlen($name) > MAX_OBJECT_NAME_LEN) {
|
1913 |
+
throw new SyntaxException("Object name exceeds "
|
1914 |
+
. "maximum allowed length.");
|
1915 |
+
}
|
1916 |
+
$this->container = $container;
|
1917 |
+
$this->name = $name;
|
1918 |
+
$this->etag = NULL;
|
1919 |
+
$this->_etag_override = False;
|
1920 |
+
$this->last_modified = NULL;
|
1921 |
+
$this->content_type = NULL;
|
1922 |
+
$this->content_length = 0;
|
1923 |
+
$this->metadata = array();
|
1924 |
+
$this->headers = array();
|
1925 |
+
$this->manifest = NULL;
|
1926 |
+
if ($dohead) {
|
1927 |
+
if (!$this->_initialize() && $force_exists) {
|
1928 |
+
throw new NoSuchObjectException("No such object '".$name."'");
|
1929 |
+
}
|
1930 |
+
}
|
1931 |
+
}
|
1932 |
+
|
1933 |
+
/**
|
1934 |
+
* String representation of Object
|
1935 |
+
*
|
1936 |
+
* Pretty print the Object's location and name
|
1937 |
+
*
|
1938 |
+
* @return string Object information
|
1939 |
+
*/
|
1940 |
+
function __toString()
|
1941 |
+
{
|
1942 |
+
return $this->container->name . "/" . $this->name;
|
1943 |
+
}
|
1944 |
+
|
1945 |
+
/**
|
1946 |
+
* Internal check to get the proper mimetype.
|
1947 |
+
*
|
1948 |
+
* This function would go over the available PHP methods to get
|
1949 |
+
* the MIME type.
|
1950 |
+
*
|
1951 |
+
* By default it will try to use the PHP fileinfo library which is
|
1952 |
+
* available from PHP 5.3 or as an PECL extension
|
1953 |
+
* (http://pecl.php.net/package/Fileinfo).
|
1954 |
+
*
|
1955 |
+
* It will get the magic file by default from the system wide file
|
1956 |
+
* which is usually available in /usr/share/magic on Unix or try
|
1957 |
+
* to use the file specified in the source directory of the API
|
1958 |
+
* (share directory).
|
1959 |
+
*
|
1960 |
+
* if fileinfo is not available it will try to use the internal
|
1961 |
+
* mime_content_type function.
|
1962 |
+
*
|
1963 |
+
* @param string $handle name of file or buffer to guess the type from
|
1964 |
+
* @return boolean <kbd>True</kbd> if successful
|
1965 |
+
* @throws BadContentTypeException
|
1966 |
+
*/
|
1967 |
+
function _guess_content_type($handle) {
|
1968 |
+
if ($this->content_type)
|
1969 |
+
return;
|
1970 |
+
|
1971 |
+
if (function_exists("finfo_open")) {
|
1972 |
+
$local_magic = dirname(__FILE__) . "/share/magic";
|
1973 |
+
$finfo = @finfo_open(FILEINFO_MIME, $local_magic);
|
1974 |
+
|
1975 |
+
if (!$finfo)
|
1976 |
+
$finfo = @finfo_open(FILEINFO_MIME);
|
1977 |
+
|
1978 |
+
if ($finfo) {
|
1979 |
+
|
1980 |
+
if (is_file((string)$handle))
|
1981 |
+
$ct = @finfo_file($finfo, $handle);
|
1982 |
+
else
|
1983 |
+
$ct = @finfo_buffer($finfo, $handle);
|
1984 |
+
|
1985 |
+
/* PHP 5.3 fileinfo display extra information like
|
1986 |
+
charset so we remove everything after the ; since
|
1987 |
+
we are not into that stuff */
|
1988 |
+
if ($ct) {
|
1989 |
+
$extra_content_type_info = strpos($ct, "; ");
|
1990 |
+
if ($extra_content_type_info)
|
1991 |
+
$ct = substr($ct, 0, $extra_content_type_info);
|
1992 |
+
}
|
1993 |
+
|
1994 |
+
if ($ct && $ct != 'application/octet-stream')
|
1995 |
+
$this->content_type = $ct;
|
1996 |
+
|
1997 |
+
@finfo_close($finfo);
|
1998 |
+
}
|
1999 |
+
}
|
2000 |
+
|
2001 |
+
if (!$this->content_type && (string)is_file($handle) && function_exists("mime_content_type")) {
|
2002 |
+
$this->content_type = @mime_content_type($handle);
|
2003 |
+
}
|
2004 |
+
|
2005 |
+
if (!$this->content_type) {
|
2006 |
+
throw new BadContentTypeException("Required Content-Type not set");
|
2007 |
+
}
|
2008 |
+
return True;
|
2009 |
+
}
|
2010 |
+
|
2011 |
+
/**
|
2012 |
+
* String representation of the Object's public URI
|
2013 |
+
*
|
2014 |
+
* A string representing the Object's public URI assuming that it's
|
2015 |
+
* parent Container is CDN-enabled.
|
2016 |
+
*
|
2017 |
+
* Example:
|
2018 |
+
* <code>
|
2019 |
+
* # ... authentication/connection/container code excluded
|
2020 |
+
* # ... see previous examples
|
2021 |
+
*
|
2022 |
+
* # Print out the Object's CDN URI (if it has one) in an HTML img-tag
|
2023 |
+
* #
|
2024 |
+
* print "<img src='$pic->public_uri()' />\n";
|
2025 |
+
* </code>
|
2026 |
+
*
|
2027 |
+
* @return string Object's public URI or NULL
|
2028 |
+
*/
|
2029 |
+
function public_uri()
|
2030 |
+
{
|
2031 |
+
if ($this->container->cdn_enabled) {
|
2032 |
+
return $this->container->cdn_uri . "/" . $this->name;
|
2033 |
+
}
|
2034 |
+
return NULL;
|
2035 |
+
}
|
2036 |
+
|
2037 |
+
/**
|
2038 |
+
* String representation of the Object's public SSL URI
|
2039 |
+
*
|
2040 |
+
* A string representing the Object's public SSL URI assuming that it's
|
2041 |
+
* parent Container is CDN-enabled.
|
2042 |
+
*
|
2043 |
+
* Example:
|
2044 |
+
* <code>
|
2045 |
+
* # ... authentication/connection/container code excluded
|
2046 |
+
* # ... see previous examples
|
2047 |
+
*
|
2048 |
+
* # Print out the Object's CDN SSL URI (if it has one) in an HTML img-tag
|
2049 |
+
* #
|
2050 |
+
* print "<img src='$pic->public_ssl_uri()' />\n";
|
2051 |
+
* </code>
|
2052 |
+
*
|
2053 |
+
* @return string Object's public SSL URI or NULL
|
2054 |
+
*/
|
2055 |
+
function public_ssl_uri()
|
2056 |
+
{
|
2057 |
+
if ($this->container->cdn_enabled) {
|
2058 |
+
return $this->container->cdn_ssl_uri . "/" . $this->name;
|
2059 |
+
}
|
2060 |
+
return NULL;
|
2061 |
+
}
|
2062 |
+
/**
|
2063 |
+
* String representation of the Object's public Streaming URI
|
2064 |
+
*
|
2065 |
+
* A string representing the Object's public Streaming URI assuming that it's
|
2066 |
+
* parent Container is CDN-enabled.
|
2067 |
+
*
|
2068 |
+
* Example:
|
2069 |
+
* <code>
|
2070 |
+
* # ... authentication/connection/container code excluded
|
2071 |
+
* # ... see previous examples
|
2072 |
+
*
|
2073 |
+
* # Print out the Object's CDN Streaming URI (if it has one) in an HTML img-tag
|
2074 |
+
* #
|
2075 |
+
* print "<img src='$pic->public_streaming_uri()' />\n";
|
2076 |
+
* </code>
|
2077 |
+
*
|
2078 |
+
* @return string Object's public Streaming URI or NULL
|
2079 |
+
*/
|
2080 |
+
function public_streaming_uri()
|
2081 |
+
{
|
2082 |
+
if ($this->container->cdn_enabled) {
|
2083 |
+
return $this->container->cdn_streaming_uri . "/" . $this->name;
|
2084 |
+
}
|
2085 |
+
return NULL;
|
2086 |
+
}
|
2087 |
+
|
2088 |
+
/**
|
2089 |
+
* Read the remote Object's data
|
2090 |
+
*
|
2091 |
+
* Returns the Object's data. This is useful for smaller Objects such
|
2092 |
+
* as images or office documents. Object's with larger content should use
|
2093 |
+
* the stream() method below.
|
2094 |
+
*
|
2095 |
+
* Pass in $hdrs array to set specific custom HTTP headers such as
|
2096 |
+
* If-Match, If-None-Match, If-Modified-Since, Range, etc.
|
2097 |
+
*
|
2098 |
+
* Example:
|
2099 |
+
* <code>
|
2100 |
+
* # ... authentication/connection/container code excluded
|
2101 |
+
* # ... see previous examples
|
2102 |
+
*
|
2103 |
+
* $my_docs = $conn->get_container("documents");
|
2104 |
+
* $doc = $my_docs->get_object("README");
|
2105 |
+
* $data = $doc->read(); # read image content into a string variable
|
2106 |
+
* print $data;
|
2107 |
+
*
|
2108 |
+
* # Or see stream() below for a different example.
|
2109 |
+
* #
|
2110 |
+
* </code>
|
2111 |
+
*
|
2112 |
+
* @param array $hdrs user-defined headers (Range, If-Match, etc.)
|
2113 |
+
* @return string Object's data
|
2114 |
+
* @throws InvalidResponseException unexpected response
|
2115 |
+
*/
|
2116 |
+
function read($hdrs=array())
|
2117 |
+
{
|
2118 |
+
list($status, $reason, $data) =
|
2119 |
+
$this->container->cfs_http->get_object_to_string($this, $hdrs);
|
2120 |
+
#if ($status == 401 && $this->_re_auth()) {
|
2121 |
+
# return $this->read($hdrs);
|
2122 |
+
#}
|
2123 |
+
if (($status < 200) || ($status > 299
|
2124 |
+
&& $status != 412 && $status != 304)) {
|
2125 |
+
throw new InvalidResponseException("Invalid response (".$status."): "
|
2126 |
+
. $this->container->cfs_http->get_error());
|
2127 |
+
}
|
2128 |
+
return $data;
|
2129 |
+
}
|
2130 |
+
|
2131 |
+
/**
|
2132 |
+
* Streaming read of Object's data
|
2133 |
+
*
|
2134 |
+
* Given an open PHP resource (see PHP's fopen() method), fetch the Object's
|
2135 |
+
* data and write it to the open resource handle. This is useful for
|
2136 |
+
* streaming an Object's content to the browser (videos, images) or for
|
2137 |
+
* fetching content to a local file.
|
2138 |
+
*
|
2139 |
+
* Pass in $hdrs array to set specific custom HTTP headers such as
|
2140 |
+
* If-Match, If-None-Match, If-Modified-Since, Range, etc.
|
2141 |
+
*
|
2142 |
+
* Example:
|
2143 |
+
* <code>
|
2144 |
+
* # ... authentication/connection/container code excluded
|
2145 |
+
* # ... see previous examples
|
2146 |
+
*
|
2147 |
+
* # Assuming this is a web script to display the README to the
|
2148 |
+
* # user's browser:
|
2149 |
+
* #
|
2150 |
+
* <?php
|
2151 |
+
* // grab README from storage system
|
2152 |
+
* //
|
2153 |
+
* $my_docs = $conn->get_container("documents");
|
2154 |
+
* $doc = $my_docs->get_object("README");
|
2155 |
+
*
|
2156 |
+
* // Hand it back to user's browser with appropriate content-type
|
2157 |
+
* //
|
2158 |
+
* header("Content-Type: " . $doc->content_type);
|
2159 |
+
* $output = fopen("php://output", "w");
|
2160 |
+
* $doc->stream($output); # stream object content to PHP's output buffer
|
2161 |
+
* fclose($output);
|
2162 |
+
* ?>
|
2163 |
+
*
|
2164 |
+
* # See read() above for a more simple example.
|
2165 |
+
* #
|
2166 |
+
* </code>
|
2167 |
+
*
|
2168 |
+
* @param resource $fp open resource for writing data to
|
2169 |
+
* @param array $hdrs user-defined headers (Range, If-Match, etc.)
|
2170 |
+
* @return string Object's data
|
2171 |
+
* @throws InvalidResponseException unexpected response
|
2172 |
+
*/
|
2173 |
+
function stream(&$fp, $hdrs=array())
|
2174 |
+
{
|
2175 |
+
list($status, $reason) =
|
2176 |
+
$this->container->cfs_http->get_object_to_stream($this,$fp,$hdrs);
|
2177 |
+
#if ($status == 401 && $this->_re_auth()) {
|
2178 |
+
# return $this->stream($fp, $hdrs);
|
2179 |
+
#}
|
2180 |
+
if (($status < 200) || ($status > 299
|
2181 |
+
&& $status != 412 && $status != 304)) {
|
2182 |
+
throw new InvalidResponseException("Invalid response (".$status."): "
|
2183 |
+
.$reason);
|
2184 |
+
}
|
2185 |
+
return True;
|
2186 |
+
}
|
2187 |
+
|
2188 |
+
/**
|
2189 |
+
* Store new Object metadata
|
2190 |
+
*
|
2191 |
+
* Write's an Object's metadata to the remote Object. This will overwrite
|
2192 |
+
* an prior Object metadata.
|
2193 |
+
*
|
2194 |
+
* Example:
|
2195 |
+
* <code>
|
2196 |
+
* # ... authentication/connection/container code excluded
|
2197 |
+
* # ... see previous examples
|
2198 |
+
*
|
2199 |
+
* $my_docs = $conn->get_container("documents");
|
2200 |
+
* $doc = $my_docs->get_object("README");
|
2201 |
+
*
|
2202 |
+
* # Define new metadata for the object
|
2203 |
+
* #
|
2204 |
+
* $doc->metadata = array(
|
2205 |
+
* "Author" => "EJ",
|
2206 |
+
* "Subject" => "How to use the PHP tests",
|
2207 |
+
* "Version" => "1.2.2"
|
2208 |
+
* );
|
2209 |
+
*
|
2210 |
+
* # Define additional headers for the object
|
2211 |
+
* #
|
2212 |
+
* $doc->headers = array(
|
2213 |
+
* "Content-Disposition" => "attachment",
|
2214 |
+
* );
|
2215 |
+
*
|
2216 |
+
* # Push the new metadata up to the storage system
|
2217 |
+
* #
|
2218 |
+
* $doc->sync_metadata();
|
2219 |
+
* </code>
|
2220 |
+
*
|
2221 |
+
* @return boolean <kbd>True</kbd> if successful, <kbd>False</kbd> otherwise
|
2222 |
+
* @throws InvalidResponseException unexpected response
|
2223 |
+
*/
|
2224 |
+
function sync_metadata()
|
2225 |
+
{
|
2226 |
+
if (!empty($this->metadata) || !empty($this->headers) || $this->manifest) {
|
2227 |
+
$status = $this->container->cfs_http->update_object($this);
|
2228 |
+
#if ($status == 401 && $this->_re_auth()) {
|
2229 |
+
# return $this->sync_metadata();
|
2230 |
+
#}
|
2231 |
+
if ($status != 202) {
|
2232 |
+
throw new InvalidResponseException("Invalid response ("
|
2233 |
+
.$status."): ".$this->container->cfs_http->get_error());
|
2234 |
+
}
|
2235 |
+
return True;
|
2236 |
+
}
|
2237 |
+
return False;
|
2238 |
+
}
|
2239 |
+
/**
|
2240 |
+
* Store new Object manifest
|
2241 |
+
*
|
2242 |
+
* Write's an Object's manifest to the remote Object. This will overwrite
|
2243 |
+
* an prior Object manifest.
|
2244 |
+
*
|
2245 |
+
* Example:
|
2246 |
+
* <code>
|
2247 |
+
* # ... authentication/connection/container code excluded
|
2248 |
+
* # ... see previous examples
|
2249 |
+
*
|
2250 |
+
* $my_docs = $conn->get_container("documents");
|
2251 |
+
* $doc = $my_docs->get_object("README");
|
2252 |
+
*
|
2253 |
+
* # Define new manifest for the object
|
2254 |
+
* #
|
2255 |
+
* $doc->manifest = "container/prefix";
|
2256 |
+
*
|
2257 |
+
* # Push the new manifest up to the storage system
|
2258 |
+
* #
|
2259 |
+
* $doc->sync_manifest();
|
2260 |
+
* </code>
|
2261 |
+
*
|
2262 |
+
* @return boolean <kbd>True</kbd> if successful, <kbd>False</kbd> otherwise
|
2263 |
+
* @throws InvalidResponseException unexpected response
|
2264 |
+
*/
|
2265 |
+
|
2266 |
+
function sync_manifest()
|
2267 |
+
{
|
2268 |
+
return $this->sync_metadata();
|
2269 |
+
}
|
2270 |
+
/**
|
2271 |
+
* Upload Object's data to Cloud Files
|
2272 |
+
*
|
2273 |
+
* Write data to the remote Object. The $data argument can either be a
|
2274 |
+
* PHP resource open for reading (see PHP's fopen() method) or an in-memory
|
2275 |
+
* variable. If passing in a PHP resource, you must also include the $bytes
|
2276 |
+
* parameter.
|
2277 |
+
*
|
2278 |
+
* Example:
|
2279 |
+
* <code>
|
2280 |
+
* # ... authentication/connection/container code excluded
|
2281 |
+
* # ... see previous examples
|
2282 |
+
*
|
2283 |
+
* $my_docs = $conn->get_container("documents");
|
2284 |
+
* $doc = $my_docs->get_object("README");
|
2285 |
+
*
|
2286 |
+
* # Upload placeholder text in my README
|
2287 |
+
* #
|
2288 |
+
* $doc->write("This is just placeholder text for now...");
|
2289 |
+
* </code>
|
2290 |
+
*
|
2291 |
+
* @param string|resource $data string or open resource
|
2292 |
+
* @param float $bytes amount of data to upload (required for resources)
|
2293 |
+
* @param boolean $verify generate, send, and compare MD5 checksums
|
2294 |
+
* @return boolean <kbd>True</kbd> when data uploaded successfully
|
2295 |
+
* @throws SyntaxException missing required parameters
|
2296 |
+
* @throws BadContentTypeException if no Content-Type was/could be set
|
2297 |
+
* @throws MisMatchedChecksumException $verify is set and checksums unequal
|
2298 |
+
* @throws InvalidResponseException unexpected response
|
2299 |
+
*/
|
2300 |
+
function write($data=NULL, $bytes=0, $verify=True)
|
2301 |
+
{
|
2302 |
+
if (!$data && !is_string($data)) {
|
2303 |
+
throw new SyntaxException("Missing data source.");
|
2304 |
+
}
|
2305 |
+
if ($bytes > MAX_OBJECT_SIZE) {
|
2306 |
+
throw new SyntaxException("Bytes exceeds maximum object size.");
|
2307 |
+
}
|
2308 |
+
if ($verify) {
|
2309 |
+
if (!$this->_etag_override) {
|
2310 |
+
$this->etag = $this->compute_md5sum($data);
|
2311 |
+
}
|
2312 |
+
} else {
|
2313 |
+
$this->etag = NULL;
|
2314 |
+
}
|
2315 |
+
|
2316 |
+
$close_fh = False;
|
2317 |
+
if (!is_resource($data)) {
|
2318 |
+
# A hack to treat string data as a file handle. php://memory feels
|
2319 |
+
# like a better option, but it seems to break on Windows so use
|
2320 |
+
# a temporary file instead.
|
2321 |
+
#
|
2322 |
+
$fp = fopen("php://temp", "wb+");
|
2323 |
+
#$fp = fopen("php://memory", "wb+");
|
2324 |
+
fwrite($fp, $data, strlen($data));
|
2325 |
+
rewind($fp);
|
2326 |
+
$close_fh = True;
|
2327 |
+
$this->content_length = (float) strlen($data);
|
2328 |
+
if ($this->content_length > MAX_OBJECT_SIZE) {
|
2329 |
+
throw new SyntaxException("Data exceeds maximum object size");
|
2330 |
+
}
|
2331 |
+
$ct_data = substr($data, 0, 64);
|
2332 |
+
} else {
|
2333 |
+
$this->content_length = $bytes;
|
2334 |
+
$fp = $data;
|
2335 |
+
$ct_data = fread($data, 64);
|
2336 |
+
rewind($data);
|
2337 |
+
}
|
2338 |
+
|
2339 |
+
$this->_guess_content_type($ct_data);
|
2340 |
+
|
2341 |
+
list($status, $reason, $etag) =
|
2342 |
+
$this->container->cfs_http->put_object($this, $fp);
|
2343 |
+
#if ($status == 401 && $this->_re_auth()) {
|
2344 |
+
# return $this->write($data, $bytes, $verify);
|
2345 |
+
#}
|
2346 |
+
if ($status == 412) {
|
2347 |
+
if ($close_fh) { fclose($fp); }
|
2348 |
+
throw new SyntaxException("Missing Content-Type header");
|
2349 |
+
}
|
2350 |
+
if ($status == 422) {
|
2351 |
+
if ($close_fh) { fclose($fp); }
|
2352 |
+
throw new MisMatchedChecksumException(
|
2353 |
+
"Supplied and computed checksums do not match.");
|
2354 |
+
}
|
2355 |
+
if ($status != 201) {
|
2356 |
+
if ($close_fh) { fclose($fp); }
|
2357 |
+
throw new InvalidResponseException("Invalid response (".$status."): "
|
2358 |
+
. $this->container->cfs_http->get_error());
|
2359 |
+
}
|
2360 |
+
if (!$verify) {
|
2361 |
+
$this->etag = $etag;
|
2362 |
+
}
|
2363 |
+
if ($close_fh) { fclose($fp); }
|
2364 |
+
return True;
|
2365 |
+
}
|
2366 |
+
|
2367 |
+
/**
|
2368 |
+
* Upload Object data from local filename
|
2369 |
+
*
|
2370 |
+
* This is a convenience function to upload the data from a local file. A
|
2371 |
+
* True value for $verify will cause the method to compute the Object's MD5
|
2372 |
+
* checksum prior to uploading.
|
2373 |
+
*
|
2374 |
+
* Example:
|
2375 |
+
* <code>
|
2376 |
+
* # ... authentication/connection/container code excluded
|
2377 |
+
* # ... see previous examples
|
2378 |
+
*
|
2379 |
+
* $my_docs = $conn->get_container("documents");
|
2380 |
+
* $doc = $my_docs->get_object("README");
|
2381 |
+
*
|
2382 |
+
* # Upload my local README's content
|
2383 |
+
* #
|
2384 |
+
* $doc->load_from_filename("/home/ej/cloudfiles/readme");
|
2385 |
+
* </code>
|
2386 |
+
*
|
2387 |
+
* @param string $filename full path to local file
|
2388 |
+
* @param boolean $verify enable local/remote MD5 checksum validation
|
2389 |
+
* @return boolean <kbd>True</kbd> if data uploaded successfully
|
2390 |
+
* @throws SyntaxException missing required parameters
|
2391 |
+
* @throws BadContentTypeException if no Content-Type was/could be set
|
2392 |
+
* @throws MisMatchedChecksumException $verify is set and checksums unequal
|
2393 |
+
* @throws InvalidResponseException unexpected response
|
2394 |
+
* @throws IOException error opening file
|
2395 |
+
*/
|
2396 |
+
function load_from_filename($filename, $verify=True)
|
2397 |
+
{
|
2398 |
+
$fp = @fopen($filename, "r");
|
2399 |
+
if (!$fp) {
|
2400 |
+
throw new IOException("Could not open file for reading: ".$filename);
|
2401 |
+
}
|
2402 |
+
|
2403 |
+
clearstatcache();
|
2404 |
+
|
2405 |
+
$size = (float) sprintf("%u", filesize($filename));
|
2406 |
+
if ($size > MAX_OBJECT_SIZE) {
|
2407 |
+
throw new SyntaxException("File size exceeds maximum object size.");
|
2408 |
+
}
|
2409 |
+
|
2410 |
+
$this->_guess_content_type($filename);
|
2411 |
+
|
2412 |
+
$this->write($fp, $size, $verify);
|
2413 |
+
fclose($fp);
|
2414 |
+
return True;
|
2415 |
+
}
|
2416 |
+
|
2417 |
+
/**
|
2418 |
+
* Save Object's data to local filename
|
2419 |
+
*
|
2420 |
+
* Given a local filename, the Object's data will be written to the newly
|
2421 |
+
* created file.
|
2422 |
+
*
|
2423 |
+
* Example:
|
2424 |
+
* <code>
|
2425 |
+
* # ... authentication/connection/container code excluded
|
2426 |
+
* # ... see previous examples
|
2427 |
+
*
|
2428 |
+
* # Whoops! I deleted my local README, let me download/save it
|
2429 |
+
* #
|
2430 |
+
* $my_docs = $conn->get_container("documents");
|
2431 |
+
* $doc = $my_docs->get_object("README");
|
2432 |
+
*
|
2433 |
+
* $doc->save_to_filename("/home/ej/cloudfiles/readme.restored");
|
2434 |
+
* </code>
|
2435 |
+
*
|
2436 |
+
* @param string $filename name of local file to write data to
|
2437 |
+
* @return boolean <kbd>True</kbd> if successful
|
2438 |
+
* @throws IOException error opening file
|
2439 |
+
* @throws InvalidResponseException unexpected response
|
2440 |
+
*/
|
2441 |
+
function save_to_filename($filename)
|
2442 |
+
{
|
2443 |
+
$fp = @fopen($filename, "wb");
|
2444 |
+
if (!$fp) {
|
2445 |
+
throw new IOException("Could not open file for writing: ".$filename);
|
2446 |
+
}
|
2447 |
+
$result = $this->stream($fp);
|
2448 |
+
fclose($fp);
|
2449 |
+
return $result;
|
2450 |
+
}
|
2451 |
+
/**
|
2452 |
+
* Purge this Object from CDN Cache.
|
2453 |
+
* Example:
|
2454 |
+
* <code>
|
2455 |
+
* # ... authentication code excluded (see previous examples) ...
|
2456 |
+
* #
|
2457 |
+
* $conn = new CF_Connection($auth);
|
2458 |
+
* $container = $conn->get_container("cdn_enabled");
|
2459 |
+
* $obj = $container->get_object("object");
|
2460 |
+
* $obj->purge_from_cdn("user@domain.com");
|
2461 |
+
* # or
|
2462 |
+
* $obj->purge_from_cdn();
|
2463 |
+
* # or
|
2464 |
+
* $obj->purge_from_cdn("user1@domain.com,user2@domain.com");
|
2465 |
+
* </code>
|
2466 |
+
* @returns boolean True if successful
|
2467 |
+
* @throws CDNNotEnabledException if CDN Is not enabled on this connection
|
2468 |
+
* @throws InvalidResponseException if the response expected is not returned
|
2469 |
+
*/
|
2470 |
+
function purge_from_cdn($email=null)
|
2471 |
+
{
|
2472 |
+
if (!$this->container->cfs_http->getCDNMUrl())
|
2473 |
+
{
|
2474 |
+
throw new CDNNotEnabledException(
|
2475 |
+
"Authentication response did not indicate CDN availability");
|
2476 |
+
}
|
2477 |
+
$status = $this->container->cfs_http->purge_from_cdn($this->container->name . "/" . $this->name, $email);
|
2478 |
+
if ($status < 199 or $status > 299) {
|
2479 |
+
throw new InvalidResponseException(
|
2480 |
+
"Invalid response (".$status."): ".$this->container->cfs_http->get_error());
|
2481 |
+
}
|
2482 |
+
return True;
|
2483 |
+
}
|
2484 |
+
|
2485 |
+
/**
|
2486 |
+
* Set Object's MD5 checksum
|
2487 |
+
*
|
2488 |
+
* Manually set the Object's ETag. Including the ETag is mandatory for
|
2489 |
+
* Cloud Files to perform end-to-end verification. Omitting the ETag forces
|
2490 |
+
* the user to handle any data integrity checks.
|
2491 |
+
*
|
2492 |
+
* @param string $etag MD5 checksum hexidecimal string
|
2493 |
+
*/
|
2494 |
+
function set_etag($etag)
|
2495 |
+
{
|
2496 |
+
$this->etag = $etag;
|
2497 |
+
$this->_etag_override = True;
|
2498 |
+
}
|
2499 |
+
|
2500 |
+
/**
|
2501 |
+
* Object's MD5 checksum
|
2502 |
+
*
|
2503 |
+
* Accessor method for reading Object's private ETag attribute.
|
2504 |
+
*
|
2505 |
+
* @return string MD5 checksum hexidecimal string
|
2506 |
+
*/
|
2507 |
+
function getETag()
|
2508 |
+
{
|
2509 |
+
return $this->etag;
|
2510 |
+
}
|
2511 |
+
|
2512 |
+
/**
|
2513 |
+
* Compute the MD5 checksum
|
2514 |
+
*
|
2515 |
+
* Calculate the MD5 checksum on either a PHP resource or data. The argument
|
2516 |
+
* may either be a local filename, open resource for reading, or a string.
|
2517 |
+
*
|
2518 |
+
* <b>WARNING:</b> if you are uploading a big file over a stream
|
2519 |
+
* it could get very slow to compute the md5 you probably want to
|
2520 |
+
* set the $verify parameter to False in the write() method and
|
2521 |
+
* compute yourself the md5 before if you have it.
|
2522 |
+
*
|
2523 |
+
* @param filename|obj|string $data filename, open resource, or string
|
2524 |
+
* @return string MD5 checksum hexidecimal string
|
2525 |
+
*/
|
2526 |
+
function compute_md5sum(&$data)
|
2527 |
+
{
|
2528 |
+
|
2529 |
+
if (function_exists("hash_init") && is_resource($data)) {
|
2530 |
+
$ctx = hash_init('md5');
|
2531 |
+
while (!feof($data)) {
|
2532 |
+
$buffer = fgets($data, 65536);
|
2533 |
+
hash_update($ctx, $buffer);
|
2534 |
+
}
|
2535 |
+
$md5 = hash_final($ctx, false);
|
2536 |
+
rewind($data);
|
2537 |
+
} elseif ((string)is_file($data)) {
|
2538 |
+
$md5 = md5_file($data);
|
2539 |
+
} else {
|
2540 |
+
$md5 = md5($data);
|
2541 |
+
}
|
2542 |
+
return $md5;
|
2543 |
+
}
|
2544 |
+
|
2545 |
+
/**
|
2546 |
+
* PRIVATE: fetch information about the remote Object if it exists
|
2547 |
+
*/
|
2548 |
+
private function _initialize()
|
2549 |
+
{
|
2550 |
+
list($status, $reason, $etag, $last_modified, $content_type,
|
2551 |
+
$content_length, $metadata, $manifest, $headers) =
|
2552 |
+
$this->container->cfs_http->head_object($this);
|
2553 |
+
#if ($status == 401 && $this->_re_auth()) {
|
2554 |
+
# return $this->_initialize();
|
2555 |
+
#}
|
2556 |
+
if ($status == 404) {
|
2557 |
+
return False;
|
2558 |
+
}
|
2559 |
+
if ($status < 200 || $status > 299) {
|
2560 |
+
throw new InvalidResponseException("Invalid response (".$status."): "
|
2561 |
+
. $this->container->cfs_http->get_error());
|
2562 |
+
}
|
2563 |
+
$this->etag = $etag;
|
2564 |
+
$this->last_modified = $last_modified;
|
2565 |
+
$this->content_type = $content_type;
|
2566 |
+
$this->content_length = $content_length;
|
2567 |
+
$this->metadata = $metadata;
|
2568 |
+
$this->headers = $headers;
|
2569 |
+
$this->manifest = $manifest;
|
2570 |
+
return True;
|
2571 |
+
}
|
2572 |
+
/**
|
2573 |
+
* Generate a Temp Url for a object
|
2574 |
+
* Example:
|
2575 |
+
* <code>
|
2576 |
+
* # ... authentication code excluded (see previous examples) ...
|
2577 |
+
* $conn = new CF_Connection($auth);
|
2578 |
+
* $container = $conn->get_container("foo");
|
2579 |
+
* $obj = $container->get_object("foo");
|
2580 |
+
* $tempurl = $obj->get_temp_url("shared_secret", "expire_time_in_seconds", "{HTTP_METHOD}"); (note: replace {HTTP_METHOD} with the request method: GET, POST, PUT, DELETE, etc.
|
2581 |
+
* </code>
|
2582 |
+
* @returns The temp url
|
2583 |
+
*/
|
2584 |
+
public function get_temp_url($key, $expires, $method)
|
2585 |
+
{
|
2586 |
+
|
2587 |
+
$expires += time();
|
2588 |
+
$url = $this->container->cfs_http->getStorageUrl() . '/' . $this->container->name . '/' . $this->name;
|
2589 |
+
return $url . '?temp_url_sig=' . hash_hmac('sha1', strtoupper($method) .
|
2590 |
+
"\n" . $expires . "\n" . parse_url($url, PHP_URL_PATH), $key) .
|
2591 |
+
'&temp_url_expires=' . $expires;
|
2592 |
+
}
|
2593 |
+
/**
|
2594 |
+
* Generate hidden input for form post.
|
2595 |
+
* @returns array Returns an associative array with form post input.
|
2596 |
+
*/
|
2597 |
+
public function get_form_post_input($key, $expires, $redirect, $max_file_size=5368709120, $max_file_count=1)
|
2598 |
+
{
|
2599 |
+
|
2600 |
+
$expires += time();
|
2601 |
+
$url = $this->container->cfs_http->getStorageUrl() . '/' . $this->container->name . '/' . $this->name;
|
2602 |
+
$form_post = array('action' => $url, 'redirect' => $redirect, 'max_file_size' => $max_file_size, 'expires' => $expires, 'file' => $this->name);
|
2603 |
+
$form_post['signature'] = hash_hmac('sha1', parse_url($url, PHP_URL_PATH) . "\n" . $redirect . "\n" . $max_file_size . "\n" . $max_file_count . "\n" . $expires, $key );
|
2604 |
+
return $form_post;
|
2605 |
+
}
|
2606 |
+
#private function _re_auth()
|
2607 |
+
#{
|
2608 |
+
# $new_auth = new CF_Authentication(
|
2609 |
+
# $this->cfs_auth->username,
|
2610 |
+
# $this->cfs_auth->api_key,
|
2611 |
+
# $this->cfs_auth->auth_host,
|
2612 |
+
# $this->cfs_auth->account);
|
2613 |
+
# $new_auth->authenticate();
|
2614 |
+
# $this->container->cfs_auth = $new_auth;
|
2615 |
+
# $this->container->cfs_http->setCFAuth($this->cfs_auth);
|
2616 |
+
# return True;
|
2617 |
+
#}
|
2618 |
+
}
|
2619 |
+
|
2620 |
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
2621 |
+
|
2622 |
+
/*
|
2623 |
+
* Local variables:
|
2624 |
+
* tab-width: 4
|
2625 |
+
* c-basic-offset: 4
|
2626 |
+
* c-hanging-comment-ender-p: nil
|
2627 |
+
* End:
|
2628 |
+
*/
|
2629 |
+
?>
|
includes/cloudfiles/cloudfiles_exceptions.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Custom Exceptions for the CloudFiles API
|
4 |
+
*
|
5 |
+
* Requres PHP 5.x (for Exceptions and OO syntax)
|
6 |
+
*
|
7 |
+
* See COPYING for license information.
|
8 |
+
*
|
9 |
+
* @author Eric "EJ" Johnson <ej@racklabs.com>
|
10 |
+
* @copyright Copyright (c) 2008, Rackspace US, Inc.
|
11 |
+
* @package php-cloudfiles-exceptions
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Custom Exceptions for the CloudFiles API
|
16 |
+
* @package php-cloudfiles-exceptions
|
17 |
+
*/
|
18 |
+
class SyntaxException extends Exception { }
|
19 |
+
class AuthenticationException extends Exception { }
|
20 |
+
class InvalidResponseException extends Exception { }
|
21 |
+
class NonEmptyContainerException extends Exception { }
|
22 |
+
class NoSuchObjectException extends Exception { }
|
23 |
+
class NoSuchContainerException extends Exception { }
|
24 |
+
class NoSuchAccountException extends Exception { }
|
25 |
+
class MisMatchedChecksumException extends Exception { }
|
26 |
+
class IOException extends Exception { }
|
27 |
+
class CDNNotEnabledException extends Exception { }
|
28 |
+
class BadContentTypeException extends Exception { }
|
29 |
+
class InvalidUTF8Exception extends Exception { }
|
30 |
+
class ConnectionNotOpenException extends Exception { }
|
31 |
+
|
32 |
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
33 |
+
|
34 |
+
/*
|
35 |
+
* Local variables:
|
36 |
+
* tab-width: 4
|
37 |
+
* c-basic-offset: 4
|
38 |
+
* c-hanging-comment-ender-p: nil
|
39 |
+
* End:
|
40 |
+
*/
|
41 |
+
?>
|
includes/cloudfiles/cloudfiles_http.php
ADDED
@@ -0,0 +1,1582 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This is an HTTP client class for Cloud Files. It uses PHP's cURL module
|
4 |
+
* to handle the actual HTTP request/response. This is NOT a generic HTTP
|
5 |
+
* client class and is only used to abstract out the HTTP communication for
|
6 |
+
* the PHP Cloud Files API.
|
7 |
+
*
|
8 |
+
* This module was designed to re-use existing HTTP(S) connections between
|
9 |
+
* subsequent operations. For example, performing multiple PUT operations
|
10 |
+
* will re-use the same connection.
|
11 |
+
*
|
12 |
+
* This modules also provides support for streaming content into and out
|
13 |
+
* of Cloud Files. The majority (all?) of the PHP HTTP client modules expect
|
14 |
+
* to read the server's response into a string variable. This will not work
|
15 |
+
* with large files without killing your server. Methods like,
|
16 |
+
* get_object_to_stream() and put_object() take an open filehandle
|
17 |
+
* argument for streaming data out of or into Cloud Files.
|
18 |
+
*
|
19 |
+
* Requres PHP 5.x (for Exceptions and OO syntax)
|
20 |
+
*
|
21 |
+
* See COPYING for license information.
|
22 |
+
*
|
23 |
+
* @author Eric "EJ" Johnson <ej@racklabs.com>
|
24 |
+
* @copyright Copyright (c) 2008, Rackspace US, Inc.
|
25 |
+
* @package php-cloudfiles-http
|
26 |
+
*/
|
27 |
+
|
28 |
+
/**
|
29 |
+
*/
|
30 |
+
require_once("cloudfiles_exceptions.php");
|
31 |
+
|
32 |
+
@define("PHP_CF_VERSION", "1.7.11");
|
33 |
+
@define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
|
34 |
+
@define("MAX_HEADER_NAME_LEN", 128);
|
35 |
+
@define("MAX_HEADER_VALUE_LEN", 256);
|
36 |
+
@define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
|
37 |
+
@define("ACCOUNT_BYTES_USED", "X-Account-Bytes-Used");
|
38 |
+
@define("ACCOUNT_KEY", "X-Account-Meta-Key");
|
39 |
+
@define("ACCOUNT_METADATA_HEADER_PREFIX", "X-Account-Meta-");
|
40 |
+
@define("CONTAINER_OBJ_COUNT", "X-Container-Object-Count");
|
41 |
+
@define("CONTAINER_BYTES_USED", "X-Container-Bytes-Used");
|
42 |
+
@define("CONTAINER_METADATA_HEADER_PREFIX", "X-Container-Meta-");
|
43 |
+
@define("DELETE_AFTER", "X-Delete-After");
|
44 |
+
@define("DELETE_AT", "X-Delete-At");
|
45 |
+
@define("MANIFEST_HEADER", "X-Object-Manifest");
|
46 |
+
@define("METADATA_HEADER_PREFIX", "X-Object-Meta-");
|
47 |
+
@define("CONTENT_HEADER_PREFIX", "Content-");
|
48 |
+
@define("ACCESS_CONTROL_HEADER_PREFIX", "Access-Control-");
|
49 |
+
@define("ORIGIN_HEADER", "Origin");
|
50 |
+
@define("CDN_URI", "X-CDN-URI");
|
51 |
+
@define("CDN_SSL_URI", "X-CDN-SSL-URI");
|
52 |
+
@define("CDN_STREAMING_URI", "X-CDN-Streaming-URI");
|
53 |
+
@define("CDN_ENABLED", "X-CDN-Enabled");
|
54 |
+
@define("CDN_LOG_RETENTION", "X-Log-Retention");
|
55 |
+
@define("CDN_ACL_USER_AGENT", "X-User-Agent-ACL");
|
56 |
+
@define("CDN_ACL_REFERRER", "X-Referrer-ACL");
|
57 |
+
@define("CDN_TTL", "X-TTL");
|
58 |
+
@define("CDNM_URL", "X-CDN-Management-Url");
|
59 |
+
@define("STORAGE_URL", "X-Storage-Url");
|
60 |
+
@define("AUTH_TOKEN", "X-Auth-Token");
|
61 |
+
@define("AUTH_USER_HEADER", "X-Auth-User");
|
62 |
+
@define("AUTH_KEY_HEADER", "X-Auth-Key");
|
63 |
+
@define("AUTH_USER_HEADER_LEGACY", "X-Storage-User");
|
64 |
+
@define("AUTH_KEY_HEADER_LEGACY", "X-Storage-Pass");
|
65 |
+
@define("AUTH_TOKEN_LEGACY", "X-Storage-Token");
|
66 |
+
@define("CDN_EMAIL", "X-Purge-Email");
|
67 |
+
@define("DESTINATION", "Destination");
|
68 |
+
@define("ETAG_HEADER", "ETag");
|
69 |
+
@define("LAST_MODIFIED_HEADER", "Last-Modified");
|
70 |
+
@define("CONTENT_TYPE_HEADER", "Content-Type");
|
71 |
+
@define("CONTENT_LENGTH_HEADER", "Content-Length");
|
72 |
+
@define("USER_AGENT_HEADER", "User-Agent");
|
73 |
+
|
74 |
+
/**
|
75 |
+
* HTTP/cURL wrapper for Cloud Files
|
76 |
+
*
|
77 |
+
* This class should not be used directly. It's only purpose is to abstract
|
78 |
+
* out the HTTP communication from the main API.
|
79 |
+
*
|
80 |
+
* @package php-cloudfiles-http
|
81 |
+
*/
|
82 |
+
class UpdraftPlus_CF_Http
|
83 |
+
{
|
84 |
+
private $error_str;
|
85 |
+
private $dbug;
|
86 |
+
private $cabundle_path;
|
87 |
+
private $api_version;
|
88 |
+
# Authentication instance variables
|
89 |
+
#
|
90 |
+
private $storage_url;
|
91 |
+
private $cdnm_url;
|
92 |
+
private $auth_token;
|
93 |
+
|
94 |
+
# Request/response variables
|
95 |
+
#
|
96 |
+
private $response_status;
|
97 |
+
private $response_reason;
|
98 |
+
private $connections;
|
99 |
+
|
100 |
+
# Variables used for content/header callbacks
|
101 |
+
#
|
102 |
+
private $_user_read_progress_callback_func;
|
103 |
+
private $_user_write_progress_callback_func;
|
104 |
+
private $_write_callback_type;
|
105 |
+
private $_text_list;
|
106 |
+
private $_account_metadata;
|
107 |
+
private $_account_container_count;
|
108 |
+
private $_account_bytes_used;
|
109 |
+
private $_account_key;
|
110 |
+
private $_container_metadata;
|
111 |
+
private $_container_object_count;
|
112 |
+
private $_container_bytes_used;
|
113 |
+
private $_obj_delete_after;
|
114 |
+
private $_obj_delete_at;
|
115 |
+
private $_obj_etag;
|
116 |
+
private $_obj_last_modified;
|
117 |
+
private $_obj_content_type;
|
118 |
+
private $_obj_content_length;
|
119 |
+
private $_obj_metadata;
|
120 |
+
private $_obj_headers;
|
121 |
+
private $_obj_manifest;
|
122 |
+
private $_obj_write_resource;
|
123 |
+
private $_obj_write_string;
|
124 |
+
private $_cdn_enabled;
|
125 |
+
private $_cdn_ssl_uri;
|
126 |
+
private $_cdn_streaming_uri;
|
127 |
+
private $_cdn_uri;
|
128 |
+
private $_cdn_ttl;
|
129 |
+
private $_cdn_log_retention;
|
130 |
+
private $_cdn_acl_user_agent;
|
131 |
+
private $_cdn_acl_referrer;
|
132 |
+
|
133 |
+
function __construct($api_version)
|
134 |
+
{
|
135 |
+
$this->dbug = False;
|
136 |
+
$this->cabundle_path = NULL;
|
137 |
+
$this->api_version = $api_version;
|
138 |
+
$this->error_str = NULL;
|
139 |
+
|
140 |
+
$this->storage_url = NULL;
|
141 |
+
$this->cdnm_url = NULL;
|
142 |
+
$this->auth_token = NULL;
|
143 |
+
|
144 |
+
$this->response_status = NULL;
|
145 |
+
$this->response_reason = NULL;
|
146 |
+
|
147 |
+
# Curl connections array - since there is no way to "re-set" the
|
148 |
+
# connection paramaters for a cURL handle, we keep an array of
|
149 |
+
# the unique use-cases and funnel all of those same type
|
150 |
+
# requests through the appropriate curl connection.
|
151 |
+
#
|
152 |
+
$this->connections = array(
|
153 |
+
"GET_CALL" => NULL, # GET objects/containers/lists
|
154 |
+
"PUT_OBJ" => NULL, # PUT object
|
155 |
+
"HEAD" => NULL, # HEAD requests
|
156 |
+
"PUT_CONT" => NULL, # PUT container
|
157 |
+
"DEL_POST" => NULL, # DELETE containers/objects, POST objects
|
158 |
+
"COPY" => null, # COPY objects
|
159 |
+
);
|
160 |
+
|
161 |
+
$this->_user_read_progress_callback_func = NULL;
|
162 |
+
$this->_user_write_progress_callback_func = NULL;
|
163 |
+
$this->_write_callback_type = NULL;
|
164 |
+
$this->_text_list = array();
|
165 |
+
$this->_return_list = NULL;
|
166 |
+
$this->_account_metadata = array();
|
167 |
+
$this->_account_key = NULL;
|
168 |
+
$this->_account_container_count = 0;
|
169 |
+
$this->_account_bytes_used = 0;
|
170 |
+
$this->_container_metadata = array();
|
171 |
+
$this->_container_object_count = 0;
|
172 |
+
$this->_container_bytes_used = 0;
|
173 |
+
$this->_obj_delete_after = NULL;
|
174 |
+
$this->_obj_delete_at = NULL;
|
175 |
+
$this->_obj_write_resource = NULL;
|
176 |
+
$this->_obj_write_string = "";
|
177 |
+
$this->_obj_etag = NULL;
|
178 |
+
$this->_obj_last_modified = NULL;
|
179 |
+
$this->_obj_content_type = NULL;
|
180 |
+
$this->_obj_content_length = NULL;
|
181 |
+
$this->_obj_metadata = array();
|
182 |
+
$this->_obj_manifest = NULL;
|
183 |
+
$this->_obj_headers = NULL;
|
184 |
+
$this->_cdn_enabled = NULL;
|
185 |
+
$this->_cdn_ssl_uri = NULL;
|
186 |
+
$this->_cdn_streaming_uri = NULL;
|
187 |
+
$this->_cdn_uri = NULL;
|
188 |
+
$this->_cdn_ttl = NULL;
|
189 |
+
$this->_cdn_log_retention = NULL;
|
190 |
+
$this->_cdn_acl_user_agent = NULL;
|
191 |
+
$this->_cdn_acl_referrer = NULL;
|
192 |
+
|
193 |
+
# The OS list with a PHP without an updated CA File for CURL to
|
194 |
+
# connect to SSL Websites. It is the first 3 letters of the PHP_OS
|
195 |
+
# variable.
|
196 |
+
$OS_CAFILE_NONUPDATED=array(
|
197 |
+
"win","dar"
|
198 |
+
);
|
199 |
+
|
200 |
+
// We don't want this happening automatically - since the UpdraftPlus default is to use our own certificate already
|
201 |
+
// if (in_array((strtolower (substr(PHP_OS, 0,3))), $OS_CAFILE_NONUPDATED))
|
202 |
+
// $this->ssl_use_cabundle();
|
203 |
+
|
204 |
+
}
|
205 |
+
|
206 |
+
function ssl_use_cabundle($path=NULL)
|
207 |
+
{
|
208 |
+
if ($path) {
|
209 |
+
$this->cabundle_path = $path;
|
210 |
+
} else {
|
211 |
+
$this->cabundle_path = UPDRAFTPLUS_DIR.'/includes/cacert.pem';
|
212 |
+
}
|
213 |
+
if (!file_exists($this->cabundle_path)) {
|
214 |
+
throw new IOException("Could not use CA bundle: "
|
215 |
+
. $this->cabundle_path);
|
216 |
+
}
|
217 |
+
return;
|
218 |
+
}
|
219 |
+
|
220 |
+
# Uses separate cURL connection to authenticate
|
221 |
+
#
|
222 |
+
function authenticate($user, $pass, $acct=NULL, $host=NULL)
|
223 |
+
{
|
224 |
+
$path = array();
|
225 |
+
if (isset($acct)){
|
226 |
+
$headers = array(
|
227 |
+
sprintf("%s: %s", AUTH_USER_HEADER_LEGACY, $user),
|
228 |
+
sprintf("%s: %s", AUTH_KEY_HEADER_LEGACY, $pass),
|
229 |
+
);
|
230 |
+
$path[] = $host;
|
231 |
+
$path[] = rawurlencode(sprintf("v%d",$this->api_version));
|
232 |
+
$path[] = rawurlencode($acct);
|
233 |
+
} else {
|
234 |
+
$headers = array(
|
235 |
+
sprintf("%s: %s", AUTH_USER_HEADER, $user),
|
236 |
+
sprintf("%s: %s", AUTH_KEY_HEADER, $pass),
|
237 |
+
);
|
238 |
+
$path[] = $host;
|
239 |
+
}
|
240 |
+
$path[] = "v1.0";
|
241 |
+
$url = implode("/", $path);
|
242 |
+
|
243 |
+
$curl_ch = curl_init();
|
244 |
+
if (!is_null($this->cabundle_path)) {
|
245 |
+
curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
|
246 |
+
}
|
247 |
+
if (defined('UPDRAFTPLUS_SSL_DISABLEVERIFY')) {
|
248 |
+
curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, UPDRAFTPLUS_SSL_DISABLEVERIFY);
|
249 |
+
} elseif (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) {
|
250 |
+
curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, false);
|
251 |
+
} else {
|
252 |
+
curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, true);
|
253 |
+
}
|
254 |
+
|
255 |
+
curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
|
256 |
+
curl_setopt($curl_ch, CURLOPT_FOLLOWLOCATION, 1);
|
257 |
+
curl_setopt($curl_ch, CURLOPT_MAXREDIRS, 4);
|
258 |
+
curl_setopt($curl_ch, CURLOPT_HEADER, 0);
|
259 |
+
curl_setopt($curl_ch, CURLOPT_HTTPHEADER, $headers);
|
260 |
+
curl_setopt($curl_ch, CURLOPT_USERAGENT, USER_AGENT);
|
261 |
+
curl_setopt($curl_ch, CURLOPT_RETURNTRANSFER, TRUE);
|
262 |
+
curl_setopt($curl_ch, CURLOPT_HEADERFUNCTION,array(&$this,'_auth_hdr_cb'));
|
263 |
+
curl_setopt($curl_ch, CURLOPT_CONNECTTIMEOUT, 10);
|
264 |
+
curl_setopt($curl_ch, CURLOPT_URL, $url);
|
265 |
+
curl_exec($curl_ch);
|
266 |
+
curl_close($curl_ch);
|
267 |
+
|
268 |
+
return array($this->response_status, $this->response_reason,
|
269 |
+
$this->storage_url, $this->cdnm_url, $this->auth_token);
|
270 |
+
}
|
271 |
+
|
272 |
+
# (CDN) GET /v1/Account
|
273 |
+
#
|
274 |
+
function list_cdn_containers($enabled_only)
|
275 |
+
{
|
276 |
+
$conn_type = "GET_CALL";
|
277 |
+
$url_path = $this->_make_path("CDN");
|
278 |
+
|
279 |
+
$this->_write_callback_type = "TEXT_LIST";
|
280 |
+
if ($enabled_only)
|
281 |
+
{
|
282 |
+
$return_code = $this->_send_request($conn_type, $url_path .
|
283 |
+
'/?enabled_only=true');
|
284 |
+
}
|
285 |
+
else
|
286 |
+
{
|
287 |
+
$return_code = $this->_send_request($conn_type, $url_path);
|
288 |
+
}
|
289 |
+
if (!$return_code) {
|
290 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
291 |
+
return array(0,$this->error_str,array());
|
292 |
+
}
|
293 |
+
if ($return_code == 401) {
|
294 |
+
return array($return_code,"Unauthorized",array());
|
295 |
+
}
|
296 |
+
if ($return_code == 404) {
|
297 |
+
return array($return_code,"Account not found.",array());
|
298 |
+
}
|
299 |
+
if ($return_code == 204) {
|
300 |
+
return array($return_code,"Account has no CDN enabled Containers.",
|
301 |
+
array());
|
302 |
+
}
|
303 |
+
if ($return_code == 200) {
|
304 |
+
$this->create_array();
|
305 |
+
return array($return_code,$this->response_reason,$this->_text_list);
|
306 |
+
}
|
307 |
+
$this->error_str = "Unexpected HTTP response: ".$this->response_reason;
|
308 |
+
return array($return_code,$this->error_str,array());
|
309 |
+
}
|
310 |
+
|
311 |
+
# (CDN) DELETE /v1/Account/Container or /v1/Account/Container/Object
|
312 |
+
#
|
313 |
+
function purge_from_cdn($path, $email=null)
|
314 |
+
{
|
315 |
+
if(!$path)
|
316 |
+
throw new SyntaxException("Path not set");
|
317 |
+
$url_path = $this->_make_path("CDN", NULL, $path);
|
318 |
+
if($email)
|
319 |
+
{
|
320 |
+
$hdrs = array(CDN_EMAIL => $email);
|
321 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"DELETE");
|
322 |
+
}
|
323 |
+
else
|
324 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,null,"DELETE");
|
325 |
+
return $return_code;
|
326 |
+
}
|
327 |
+
|
328 |
+
# (CDN) POST /v1/Account/Container
|
329 |
+
function update_cdn_container($container_name, $ttl=86400, $cdn_log_retention=False,
|
330 |
+
$cdn_acl_user_agent="", $cdn_acl_referrer)
|
331 |
+
{
|
332 |
+
if ($container_name == "")
|
333 |
+
throw new SyntaxException("Container name not set.");
|
334 |
+
|
335 |
+
if ($container_name != "0" and !isset($container_name))
|
336 |
+
throw new SyntaxException("Container name not set.");
|
337 |
+
|
338 |
+
$url_path = $this->_make_path("CDN", $container_name);
|
339 |
+
$hdrs = array(
|
340 |
+
CDN_ENABLED => "True",
|
341 |
+
CDN_TTL => $ttl,
|
342 |
+
CDN_LOG_RETENTION => $cdn_log_retention ? "True" : "False",
|
343 |
+
CDN_ACL_USER_AGENT => $cdn_acl_user_agent,
|
344 |
+
CDN_ACL_REFERRER => $cdn_acl_referrer,
|
345 |
+
);
|
346 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
|
347 |
+
if ($return_code == 401) {
|
348 |
+
$this->error_str = "Unauthorized";
|
349 |
+
return array($return_code, $this->error_str, NULL);
|
350 |
+
}
|
351 |
+
if ($return_code == 404) {
|
352 |
+
$this->error_str = "Container not found.";
|
353 |
+
return array($return_code, $this->error_str, NULL);
|
354 |
+
}
|
355 |
+
if ($return_code != 202) {
|
356 |
+
$this->error_str="Unexpected HTTP response: ".$this->response_reason;
|
357 |
+
return array($return_code, $this->error_str, NULL);
|
358 |
+
}
|
359 |
+
return array($return_code, "Accepted", $this->_cdn_uri, $this->_cdn_ssl_uri);
|
360 |
+
|
361 |
+
}
|
362 |
+
|
363 |
+
# (CDN) PUT /v1/Account/Container
|
364 |
+
#
|
365 |
+
function add_cdn_container($container_name, $ttl=86400)
|
366 |
+
{
|
367 |
+
if ($container_name == "")
|
368 |
+
throw new SyntaxException("Container name not set.");
|
369 |
+
|
370 |
+
if ($container_name != "0" and !isset($container_name))
|
371 |
+
throw new SyntaxException("Container name not set.");
|
372 |
+
|
373 |
+
$url_path = $this->_make_path("CDN", $container_name);
|
374 |
+
$hdrs = array(
|
375 |
+
CDN_ENABLED => "True",
|
376 |
+
CDN_TTL => $ttl,
|
377 |
+
);
|
378 |
+
$return_code = $this->_send_request("PUT_CONT", $url_path, $hdrs);
|
379 |
+
if ($return_code == 401) {
|
380 |
+
$this->error_str = "Unauthorized";
|
381 |
+
return array($return_code,$this->response_reason,False);
|
382 |
+
}
|
383 |
+
if (!in_array($return_code, array(201,202))) {
|
384 |
+
$this->error_str="Unexpected HTTP response: ".$this->response_reason;
|
385 |
+
return array($return_code,$this->response_reason,False);
|
386 |
+
}
|
387 |
+
return array($return_code,$this->response_reason,$this->_cdn_uri,
|
388 |
+
$this->_cdn_ssl_uri);
|
389 |
+
}
|
390 |
+
|
391 |
+
# (CDN) POST /v1/Account/Container
|
392 |
+
#
|
393 |
+
function remove_cdn_container($container_name)
|
394 |
+
{
|
395 |
+
if ($container_name == "")
|
396 |
+
throw new SyntaxException("Container name not set.");
|
397 |
+
|
398 |
+
if ($container_name != "0" and !isset($container_name))
|
399 |
+
throw new SyntaxException("Container name not set.");
|
400 |
+
|
401 |
+
$url_path = $this->_make_path("CDN", $container_name);
|
402 |
+
$hdrs = array(CDN_ENABLED => "False");
|
403 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
|
404 |
+
if ($return_code == 401) {
|
405 |
+
$this->error_str = "Unauthorized";
|
406 |
+
return array($return_code, $this->error_str);
|
407 |
+
}
|
408 |
+
if ($return_code == 404) {
|
409 |
+
$this->error_str = "Container not found.";
|
410 |
+
return array($return_code, $this->error_str);
|
411 |
+
}
|
412 |
+
if ($return_code != 202) {
|
413 |
+
$this->error_str="Unexpected HTTP response: ".$this->response_reason;
|
414 |
+
return array($return_code, $this->error_str);
|
415 |
+
}
|
416 |
+
return array($return_code, "Accepted");
|
417 |
+
}
|
418 |
+
|
419 |
+
# (CDN) HEAD /v1/Account
|
420 |
+
#
|
421 |
+
function head_cdn_container($container_name)
|
422 |
+
{
|
423 |
+
if ($container_name == "")
|
424 |
+
throw new SyntaxException("Container name not set.");
|
425 |
+
|
426 |
+
if ($container_name != "0" and !isset($container_name))
|
427 |
+
throw new SyntaxException("Container name not set.");
|
428 |
+
|
429 |
+
$conn_type = "HEAD";
|
430 |
+
$url_path = $this->_make_path("CDN", $container_name);
|
431 |
+
$return_code = $this->_send_request($conn_type, $url_path, NULL, "GET", True);
|
432 |
+
|
433 |
+
if (!$return_code) {
|
434 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
435 |
+
return array(0,$this->error_str,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
436 |
+
}
|
437 |
+
if ($return_code == 401) {
|
438 |
+
return array($return_code,"Unauthorized",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
439 |
+
}
|
440 |
+
if ($return_code == 404) {
|
441 |
+
return array($return_code,"Account not found.",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
442 |
+
}
|
443 |
+
if ($return_code == 204) {
|
444 |
+
return array($return_code,$this->response_reason,
|
445 |
+
$this->_cdn_enabled, $this->_cdn_ssl_uri,
|
446 |
+
$this->_cdn_streaming_uri,
|
447 |
+
$this->_cdn_uri, $this->_cdn_ttl,
|
448 |
+
$this->_cdn_log_retention,
|
449 |
+
$this->_cdn_acl_user_agent,
|
450 |
+
$this->_cdn_acl_referrer
|
451 |
+
);
|
452 |
+
}
|
453 |
+
return array($return_code,$this->response_reason,
|
454 |
+
NULL,NULL,NULL,NULL,
|
455 |
+
$this->_cdn_log_retention,
|
456 |
+
$this->_cdn_acl_user_agent,
|
457 |
+
$this->_cdn_acl_referrer,
|
458 |
+
NULL
|
459 |
+
);
|
460 |
+
}
|
461 |
+
|
462 |
+
# GET /v1/Account
|
463 |
+
#
|
464 |
+
function list_containers($limit=0, $marker=NULL)
|
465 |
+
{
|
466 |
+
$conn_type = "GET_CALL";
|
467 |
+
$url_path = $this->_make_path();
|
468 |
+
|
469 |
+
$limit = intval($limit);
|
470 |
+
$params = array();
|
471 |
+
if ($limit > 0) {
|
472 |
+
$params[] = "limit=$limit";
|
473 |
+
}
|
474 |
+
if ($marker) {
|
475 |
+
$params[] = "marker=".rawurlencode($marker);
|
476 |
+
}
|
477 |
+
if (!empty($params)) {
|
478 |
+
$url_path .= "?" . implode("&", $params);
|
479 |
+
}
|
480 |
+
|
481 |
+
$this->_write_callback_type = "TEXT_LIST";
|
482 |
+
$return_code = $this->_send_request($conn_type, $url_path);
|
483 |
+
|
484 |
+
if (!$return_code) {
|
485 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
486 |
+
return array(0,$this->error_str,array());
|
487 |
+
}
|
488 |
+
if ($return_code == 204) {
|
489 |
+
return array($return_code, "Account has no containers.", array());
|
490 |
+
}
|
491 |
+
if ($return_code == 404) {
|
492 |
+
$this->error_str = "Invalid account name for authentication token.";
|
493 |
+
return array($return_code,$this->error_str,array());
|
494 |
+
}
|
495 |
+
if ($return_code == 200) {
|
496 |
+
$this->create_array();
|
497 |
+
return array($return_code, $this->response_reason, $this->_text_list);
|
498 |
+
}
|
499 |
+
$this->error_str = "Unexpected HTTP response: ".$this->response_reason;
|
500 |
+
return array($return_code,$this->error_str,array());
|
501 |
+
}
|
502 |
+
|
503 |
+
# GET /v1/Account?format=json
|
504 |
+
#
|
505 |
+
function list_containers_info($limit=0, $marker=NULL)
|
506 |
+
{
|
507 |
+
$conn_type = "GET_CALL";
|
508 |
+
$url_path = $this->_make_path() . "?format=json";
|
509 |
+
|
510 |
+
$limit = intval($limit);
|
511 |
+
$params = array();
|
512 |
+
if ($limit > 0) {
|
513 |
+
$params[] = "limit=$limit";
|
514 |
+
}
|
515 |
+
if ($marker) {
|
516 |
+
$params[] = "marker=".rawurlencode($marker);
|
517 |
+
}
|
518 |
+
if (!empty($params)) {
|
519 |
+
$url_path .= "&" . implode("&", $params);
|
520 |
+
}
|
521 |
+
|
522 |
+
$this->_write_callback_type = "OBJECT_STRING";
|
523 |
+
$return_code = $this->_send_request($conn_type, $url_path);
|
524 |
+
|
525 |
+
if (!$return_code) {
|
526 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
527 |
+
return array(0,$this->error_str,array());
|
528 |
+
}
|
529 |
+
if ($return_code == 204) {
|
530 |
+
return array($return_code, "Account has no containers.", array());
|
531 |
+
}
|
532 |
+
if ($return_code == 404) {
|
533 |
+
$this->error_str = "Invalid account name for authentication token.";
|
534 |
+
return array($return_code,$this->error_str,array());
|
535 |
+
}
|
536 |
+
if ($return_code == 200) {
|
537 |
+
$json_body = json_decode($this->_obj_write_string, True);
|
538 |
+
return array($return_code, $this->response_reason, $json_body);
|
539 |
+
}
|
540 |
+
$this->error_str = "Unexpected HTTP response: ".$this->response_reason;
|
541 |
+
return array($return_code,$this->error_str,array());
|
542 |
+
}
|
543 |
+
|
544 |
+
# HEAD /v1/Account
|
545 |
+
#
|
546 |
+
function head_account()
|
547 |
+
{
|
548 |
+
$conn_type = "HEAD";
|
549 |
+
|
550 |
+
$url_path = $this->_make_path();
|
551 |
+
$return_code = $this->_send_request($conn_type,$url_path);
|
552 |
+
|
553 |
+
if (!$return_code) {
|
554 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
555 |
+
return array(0,$this->error_str,0,0, NULL, array());
|
556 |
+
}
|
557 |
+
if ($return_code == 404) {
|
558 |
+
return array($return_code,"Account not found.",0,0, NULL, array());
|
559 |
+
}
|
560 |
+
if ($return_code == 204) {
|
561 |
+
return array($return_code,$this->response_reason,
|
562 |
+
$this->_account_container_count, $this->_account_bytes_used,
|
563 |
+
$this->_account_key, $this->account_metadata);
|
564 |
+
}
|
565 |
+
return array($return_code,$this->response_reason,0,0, NULL, array());
|
566 |
+
}
|
567 |
+
|
568 |
+
# PUT /v1/Account/Container
|
569 |
+
#
|
570 |
+
function create_container($container_name)
|
571 |
+
{
|
572 |
+
if ($container_name == "")
|
573 |
+
throw new SyntaxException("Container name not set.");
|
574 |
+
|
575 |
+
if ($container_name != "0" and !isset($container_name))
|
576 |
+
throw new SyntaxException("Container name not set.");
|
577 |
+
|
578 |
+
$url_path = $this->_make_path("STORAGE", $container_name);
|
579 |
+
$return_code = $this->_send_request("PUT_CONT",$url_path);
|
580 |
+
|
581 |
+
if (!$return_code) {
|
582 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
583 |
+
return False;
|
584 |
+
}
|
585 |
+
return $return_code;
|
586 |
+
}
|
587 |
+
|
588 |
+
# DELETE /v1/Account/Container
|
589 |
+
#
|
590 |
+
function delete_container($container_name)
|
591 |
+
{
|
592 |
+
if ($container_name == "")
|
593 |
+
throw new SyntaxException("Container name not set.");
|
594 |
+
|
595 |
+
if ($container_name != "0" and !isset($container_name))
|
596 |
+
throw new SyntaxException("Container name not set.");
|
597 |
+
|
598 |
+
$url_path = $this->_make_path("STORAGE", $container_name);
|
599 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,array(),"DELETE");
|
600 |
+
|
601 |
+
switch ($return_code) {
|
602 |
+
case 204:
|
603 |
+
break;
|
604 |
+
case 0:
|
605 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";;
|
606 |
+
break;
|
607 |
+
case 409:
|
608 |
+
$this->error_str = "Container must be empty prior to removing it.";
|
609 |
+
break;
|
610 |
+
case 404:
|
611 |
+
$this->error_str = "Specified container did not exist to delete.";
|
612 |
+
break;
|
613 |
+
default:
|
614 |
+
$this->error_str = "Unexpected HTTP return code: $return_code.";
|
615 |
+
}
|
616 |
+
return $return_code;
|
617 |
+
}
|
618 |
+
|
619 |
+
# GET /v1/Account/Container
|
620 |
+
#
|
621 |
+
function list_objects($cname,$limit=0,$marker=NULL,$prefix=NULL,$path=NULL)
|
622 |
+
{
|
623 |
+
if (!$cname) {
|
624 |
+
$this->error_str = "Container name not set.";
|
625 |
+
return array(0, $this->error_str, array());
|
626 |
+
}
|
627 |
+
|
628 |
+
$url_path = $this->_make_path("STORAGE", $cname);
|
629 |
+
|
630 |
+
$limit = intval($limit);
|
631 |
+
$params = array();
|
632 |
+
if ($limit > 0) {
|
633 |
+
$params[] = "limit=$limit";
|
634 |
+
}
|
635 |
+
if ($marker) {
|
636 |
+
$params[] = "marker=".rawurlencode($marker);
|
637 |
+
}
|
638 |
+
if ($prefix) {
|
639 |
+
$params[] = "prefix=".rawurlencode($prefix);
|
640 |
+
}
|
641 |
+
if ($path) {
|
642 |
+
$params[] = "path=".rawurlencode($path);
|
643 |
+
}
|
644 |
+
if (!empty($params)) {
|
645 |
+
$url_path .= "?" . implode("&", $params);
|
646 |
+
}
|
647 |
+
|
648 |
+
$conn_type = "GET_CALL";
|
649 |
+
$this->_write_callback_type = "TEXT_LIST";
|
650 |
+
$return_code = $this->_send_request($conn_type,$url_path);
|
651 |
+
|
652 |
+
if (!$return_code) {
|
653 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
654 |
+
return array(0,$this->error_str,array());
|
655 |
+
}
|
656 |
+
if ($return_code == 204) {
|
657 |
+
$this->error_str = "Container has no Objects.";
|
658 |
+
return array($return_code,$this->error_str,array());
|
659 |
+
}
|
660 |
+
if ($return_code == 404) {
|
661 |
+
$this->error_str = "Container has no Objects.";
|
662 |
+
return array($return_code,$this->error_str,array());
|
663 |
+
}
|
664 |
+
if ($return_code == 200) {
|
665 |
+
$this->create_array();
|
666 |
+
return array($return_code,$this->response_reason, $this->_text_list);
|
667 |
+
}
|
668 |
+
$this->error_str = "Unexpected HTTP response code: $return_code";
|
669 |
+
return array(0,$this->error_str,array());
|
670 |
+
}
|
671 |
+
|
672 |
+
# GET /v1/Account/Container?format=json
|
673 |
+
#
|
674 |
+
function get_objects($cname,$limit=0,$marker=NULL,$prefix=NULL,$path=NULL,$delimiter=NULL)
|
675 |
+
{
|
676 |
+
if (strlen($cname) == 0) {
|
677 |
+
$this->error_str = "Container name not set.";
|
678 |
+
return array(0, $this->error_str, array());
|
679 |
+
}
|
680 |
+
$url_path = $this->_make_path("STORAGE", $cname);
|
681 |
+
|
682 |
+
$limit = intval($limit);
|
683 |
+
$params = array();
|
684 |
+
$params[] = "format=json";
|
685 |
+
if ($limit > 0) {
|
686 |
+
$params[] = "limit=$limit";
|
687 |
+
}
|
688 |
+
if ($marker) {
|
689 |
+
$params[] = "marker=".rawurlencode($marker);
|
690 |
+
}
|
691 |
+
if ($prefix) {
|
692 |
+
$params[] = "prefix=".rawurlencode($prefix);
|
693 |
+
}
|
694 |
+
if ($path) {
|
695 |
+
$params[] = "path=".rawurlencode($path);
|
696 |
+
}
|
697 |
+
if ($delimiter) {
|
698 |
+
$params[] = "delimiter=".rawurlencode($delimiter);
|
699 |
+
}
|
700 |
+
if (!empty($params)) {
|
701 |
+
$url_path .= "?" . implode("&", $params);
|
702 |
+
}
|
703 |
+
|
704 |
+
$conn_type = "GET_CALL";
|
705 |
+
$this->_write_callback_type = "OBJECT_STRING";
|
706 |
+
$return_code = $this->_send_request($conn_type,$url_path);
|
707 |
+
|
708 |
+
if (!$return_code) {
|
709 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
710 |
+
return array(0,$this->error_str,array());
|
711 |
+
}
|
712 |
+
if ($return_code == 204) {
|
713 |
+
$this->error_str = "Container has no Objects.";
|
714 |
+
return array($return_code,$this->error_str,array());
|
715 |
+
}
|
716 |
+
if ($return_code == 404) {
|
717 |
+
$this->error_str = "Container has no Objects.";
|
718 |
+
return array($return_code,$this->error_str,array());
|
719 |
+
}
|
720 |
+
if ($return_code == 200) {
|
721 |
+
$json_body = json_decode($this->_obj_write_string, True);
|
722 |
+
return array($return_code,$this->response_reason, $json_body);
|
723 |
+
}
|
724 |
+
$this->error_str = "Unexpected HTTP response code: $return_code";
|
725 |
+
return array(0,$this->error_str,array());
|
726 |
+
}
|
727 |
+
|
728 |
+
|
729 |
+
# HEAD /v1/Account/Container
|
730 |
+
#
|
731 |
+
function head_container($container_name)
|
732 |
+
{
|
733 |
+
|
734 |
+
if ($container_name == "") {
|
735 |
+
$this->error_str = "Container name not set.";
|
736 |
+
return False;
|
737 |
+
}
|
738 |
+
|
739 |
+
if ($container_name != "0" and !isset($container_name)) {
|
740 |
+
$this->error_str = "Container name not set.";
|
741 |
+
return False;
|
742 |
+
}
|
743 |
+
|
744 |
+
$conn_type = "HEAD";
|
745 |
+
|
746 |
+
$url_path = $this->_make_path("STORAGE", $container_name);
|
747 |
+
$return_code = $this->_send_request($conn_type,$url_path);
|
748 |
+
|
749 |
+
if (!$return_code) {
|
750 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
751 |
+
return array(0,$this->error_str,0,0, array());
|
752 |
+
}
|
753 |
+
if ($return_code == 404) {
|
754 |
+
return array($return_code,"Container not found.",0,0, array());
|
755 |
+
}
|
756 |
+
if ($return_code == 204 || $return_code == 200) {
|
757 |
+
return array($return_code,$this->response_reason,
|
758 |
+
$this->_container_object_count, $this->_container_bytes_used,
|
759 |
+
$this->_container_metadata);
|
760 |
+
}
|
761 |
+
return array($return_code,$this->response_reason,0,0, array());
|
762 |
+
}
|
763 |
+
|
764 |
+
# GET /v1/Account/Container/Object
|
765 |
+
#
|
766 |
+
function get_object_to_string(&$obj, $hdrs=array())
|
767 |
+
{
|
768 |
+
if (!is_object($obj) || get_class($obj) != "CF_Object") {
|
769 |
+
throw new SyntaxException(
|
770 |
+
"Method argument is not a valid CF_Object.");
|
771 |
+
}
|
772 |
+
|
773 |
+
$conn_type = "GET_CALL";
|
774 |
+
|
775 |
+
$url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
|
776 |
+
$this->_write_callback_type = "OBJECT_STRING";
|
777 |
+
$return_code = $this->_send_request($conn_type,$url_path,$hdrs);
|
778 |
+
|
779 |
+
if (!$return_code) {
|
780 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
781 |
+
return array($return_code0,$this->error_str,NULL);
|
782 |
+
}
|
783 |
+
if ($return_code == 404) {
|
784 |
+
$this->error_str = "Object not found.";
|
785 |
+
return array($return_code0,$this->error_str,NULL);
|
786 |
+
}
|
787 |
+
if (($return_code < 200) || ($return_code > 299
|
788 |
+
&& $return_code != 412 && $return_code != 304)) {
|
789 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
790 |
+
return array($return_code,$this->error_str,NULL);
|
791 |
+
}
|
792 |
+
return array($return_code,$this->response_reason, $this->_obj_write_string);
|
793 |
+
}
|
794 |
+
|
795 |
+
# GET /v1/Account/Container/Object
|
796 |
+
#
|
797 |
+
function get_object_to_stream(&$obj, &$resource=NULL, $hdrs=array())
|
798 |
+
{
|
799 |
+
if (!is_object($obj) || get_class($obj) != "CF_Object") {
|
800 |
+
throw new SyntaxException(
|
801 |
+
"Method argument is not a valid CF_Object.");
|
802 |
+
}
|
803 |
+
if (!is_resource($resource)) {
|
804 |
+
throw new SyntaxException(
|
805 |
+
"Resource argument not a valid PHP resource.");
|
806 |
+
}
|
807 |
+
|
808 |
+
$conn_type = "GET_CALL";
|
809 |
+
|
810 |
+
$url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
|
811 |
+
$this->_obj_write_resource = $resource;
|
812 |
+
$this->_write_callback_type = "OBJECT_STREAM";
|
813 |
+
$return_code = $this->_send_request($conn_type,$url_path,$hdrs);
|
814 |
+
|
815 |
+
if (!$return_code) {
|
816 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
817 |
+
return array($return_code,$this->error_str);
|
818 |
+
}
|
819 |
+
if ($return_code == 404) {
|
820 |
+
$this->error_str = "Object not found.";
|
821 |
+
return array($return_code,$this->error_str);
|
822 |
+
}
|
823 |
+
if (($return_code < 200) || ($return_code > 299
|
824 |
+
&& $return_code != 412 && $return_code != 304)) {
|
825 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
826 |
+
return array($return_code,$this->error_str);
|
827 |
+
}
|
828 |
+
return array($return_code,$this->response_reason);
|
829 |
+
}
|
830 |
+
|
831 |
+
# PUT /v1/Account/Container/Object
|
832 |
+
#
|
833 |
+
function put_object(&$obj, &$fp)
|
834 |
+
{
|
835 |
+
if (!is_object($obj) || get_class($obj) != "CF_Object") {
|
836 |
+
throw new SyntaxException(
|
837 |
+
"Method argument is not a valid CF_Object.");
|
838 |
+
}
|
839 |
+
if (!is_resource($fp)) {
|
840 |
+
throw new SyntaxException(
|
841 |
+
"File pointer argument is not a valid resource.");
|
842 |
+
}
|
843 |
+
|
844 |
+
$conn_type = "PUT_OBJ";
|
845 |
+
$url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
|
846 |
+
$hdrs = $this->_headers($obj);
|
847 |
+
|
848 |
+
$etag = $obj->getETag();
|
849 |
+
if (isset($etag)) {
|
850 |
+
$hdrs[] = "ETag: " . $etag;
|
851 |
+
}
|
852 |
+
if (!$obj->content_type) {
|
853 |
+
$hdrs[] = "Content-Type: application/octet-stream";
|
854 |
+
} else {
|
855 |
+
$hdrs[] = "Content-Type: " . $obj->content_type;
|
856 |
+
}
|
857 |
+
|
858 |
+
$this->_init($conn_type);
|
859 |
+
curl_setopt($this->connections[$conn_type],
|
860 |
+
CURLOPT_INFILE, $fp);
|
861 |
+
if (!$obj->content_length) {
|
862 |
+
# We don''t know the Content-Length, so assumed "chunked" PUT
|
863 |
+
#
|
864 |
+
curl_setopt($this->connections[$conn_type], CURLOPT_UPLOAD, True);
|
865 |
+
$hdrs[] = 'Transfer-Encoding: chunked';
|
866 |
+
} else {
|
867 |
+
# We know the Content-Length, so use regular transfer
|
868 |
+
#
|
869 |
+
curl_setopt($this->connections[$conn_type],
|
870 |
+
CURLOPT_INFILESIZE, $obj->content_length);
|
871 |
+
}
|
872 |
+
$return_code = $this->_send_request($conn_type,$url_path,$hdrs);
|
873 |
+
|
874 |
+
if (!$return_code) {
|
875 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
876 |
+
return array(0,$this->error_str,NULL);
|
877 |
+
}
|
878 |
+
if ($return_code == 412) {
|
879 |
+
$this->error_str = "Missing Content-Type header";
|
880 |
+
return array($return_code,$this->error_str,NULL);
|
881 |
+
}
|
882 |
+
if ($return_code == 422) {
|
883 |
+
$this->error_str = "Derived and computed checksums do not match.";
|
884 |
+
return array($return_code,$this->error_str,NULL);
|
885 |
+
}
|
886 |
+
if ($return_code != 201) {
|
887 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
888 |
+
return array($return_code,$this->error_str,NULL);
|
889 |
+
}
|
890 |
+
return array($return_code,$this->response_reason,$this->_obj_etag);
|
891 |
+
}
|
892 |
+
function post_account(&$conn)
|
893 |
+
{
|
894 |
+
if (!is_object($conn) || get_class($conn) != "CF_Connection") {
|
895 |
+
throw new SyntaxException(
|
896 |
+
"Method argument is not a valid CF_Connection object.");
|
897 |
+
}
|
898 |
+
if (!is_array($conn->metadata)) {
|
899 |
+
throw new SyntaxException("Metadata array is empty");
|
900 |
+
}
|
901 |
+
$return_code = $this->_send_request("DEL_POST", $this->_make_path("STORAGE"), $conn->metadata, "POST");
|
902 |
+
switch ($return_code) {
|
903 |
+
case 202:
|
904 |
+
case 201:
|
905 |
+
break;
|
906 |
+
case 0:
|
907 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
908 |
+
$return_code = 0;
|
909 |
+
break;
|
910 |
+
case 404:
|
911 |
+
$this->error_str = "Account, Container, or Object not found.";
|
912 |
+
break;
|
913 |
+
default:
|
914 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
915 |
+
break;
|
916 |
+
}
|
917 |
+
return $return_code;
|
918 |
+
}
|
919 |
+
function post_container(&$cont)
|
920 |
+
{
|
921 |
+
if (!is_object($cont) || get_class($cont) != "CF_Container") {
|
922 |
+
throw new SyntaxException(
|
923 |
+
"Method argument is not a valid CF_Container object.");
|
924 |
+
}
|
925 |
+
if (!is_array($cont->metadata)) {
|
926 |
+
throw new SyntaxException("Metadata array is empty");
|
927 |
+
}
|
928 |
+
$return_code = $this->_send_request("DEL_POST", $this->_make_path("STORAGE", $cont->name), $cont->metadata, "POST");
|
929 |
+
switch ($return_code) {
|
930 |
+
case 201:
|
931 |
+
case 202:
|
932 |
+
break;
|
933 |
+
case 0:
|
934 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
935 |
+
$return_code = 0;
|
936 |
+
break;
|
937 |
+
case 404:
|
938 |
+
$this->error_str = "Account, Container, or Object not found.";
|
939 |
+
break;
|
940 |
+
default:
|
941 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
942 |
+
break;
|
943 |
+
}
|
944 |
+
return $return_code;
|
945 |
+
}
|
946 |
+
|
947 |
+
# POST /v1/Account/Container/Object
|
948 |
+
#
|
949 |
+
function update_object(&$obj)
|
950 |
+
{
|
951 |
+
if (!is_object($obj) || get_class($obj) != "CF_Object") {
|
952 |
+
throw new SyntaxException(
|
953 |
+
"Method argument is not a valid CF_Object.");
|
954 |
+
}
|
955 |
+
|
956 |
+
# TODO: The is_array check isn't in sync with the error message
|
957 |
+
if (!$obj->manifest && !(is_array($obj->metadata) || is_array($obj->headers))) {
|
958 |
+
$this->error_str = "Metadata and headers arrays are empty.";
|
959 |
+
return 0;
|
960 |
+
}
|
961 |
+
|
962 |
+
$url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
|
963 |
+
|
964 |
+
$hdrs = $this->_headers($obj);
|
965 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
|
966 |
+
switch ($return_code) {
|
967 |
+
case 202:
|
968 |
+
break;
|
969 |
+
case 0:
|
970 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
971 |
+
$return_code = 0;
|
972 |
+
break;
|
973 |
+
case 404:
|
974 |
+
$this->error_str = "Account, Container, or Object not found.";
|
975 |
+
break;
|
976 |
+
default:
|
977 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
978 |
+
break;
|
979 |
+
}
|
980 |
+
return $return_code;
|
981 |
+
}
|
982 |
+
|
983 |
+
# HEAD /v1/Account/Container/Object
|
984 |
+
#
|
985 |
+
function head_object(&$obj)
|
986 |
+
{
|
987 |
+
if (!is_object($obj) || get_class($obj) != "CF_Object") {
|
988 |
+
throw new SyntaxException(
|
989 |
+
"Method argument is not a valid CF_Object.");
|
990 |
+
}
|
991 |
+
|
992 |
+
$conn_type = "HEAD";
|
993 |
+
|
994 |
+
$url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
|
995 |
+
$return_code = $this->_send_request($conn_type,$url_path);
|
996 |
+
|
997 |
+
if (!$return_code) {
|
998 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
999 |
+
return array(0, $this->error_str." ".$this->response_reason,
|
1000 |
+
NULL, NULL, NULL, NULL, array(), NULL, NULL, NULL, array());
|
1001 |
+
}
|
1002 |
+
|
1003 |
+
if ($return_code == 404) {
|
1004 |
+
return array($return_code, $this->response_reason,
|
1005 |
+
NULL, NULL, NULL, NULL, array(), NULL, NULL, NULL, array());
|
1006 |
+
}
|
1007 |
+
if ($return_code == 204 || $return_code == 200) {
|
1008 |
+
return array($return_code,$this->response_reason,
|
1009 |
+
$this->_obj_etag,
|
1010 |
+
$this->_obj_last_modified,
|
1011 |
+
$this->_obj_content_type,
|
1012 |
+
$this->_obj_content_length,
|
1013 |
+
$this->_obj_metadata,
|
1014 |
+
$this->_obj_manifest,
|
1015 |
+
$this->_obj_delete_at,
|
1016 |
+
$this->_obj_delete_after,
|
1017 |
+
$this->_obj_headers);
|
1018 |
+
}
|
1019 |
+
$this->error_str = "Unexpected HTTP return code: $return_code";
|
1020 |
+
return array($return_code, $this->error_str." ".$this->response_reason,
|
1021 |
+
NULL, NULL, NULL, NULL, array(), NULL, NULL, NULL, array());
|
1022 |
+
}
|
1023 |
+
|
1024 |
+
# COPY /v1/Account/Container/Object
|
1025 |
+
#
|
1026 |
+
function copy_object($src_obj_name, $dest_obj_name, $container_name_source, $container_name_target, $metadata=NULL, $headers=NULL)
|
1027 |
+
{
|
1028 |
+
if (!$src_obj_name) {
|
1029 |
+
$this->error_str = "Object name not set.";
|
1030 |
+
return 0;
|
1031 |
+
}
|
1032 |
+
|
1033 |
+
if ($container_name_source == "") {
|
1034 |
+
$this->error_str = "Container name source not set.";
|
1035 |
+
return 0;
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
if ($container_name_source != "0" and !isset($container_name_source)) {
|
1039 |
+
$this->error_str = "Container name source not set.";
|
1040 |
+
return 0;
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
if ($container_name_target == "") {
|
1044 |
+
$this->error_str = "Container name target not set.";
|
1045 |
+
return 0;
|
1046 |
+
}
|
1047 |
+
|
1048 |
+
if ($container_name_target != "0" and !isset($container_name_target)) {
|
1049 |
+
$this->error_str = "Container name target not set.";
|
1050 |
+
return 0;
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
$conn_type = "COPY";
|
1054 |
+
|
1055 |
+
$url_path = $this->_make_path("STORAGE", $container_name_source, rawurlencode($src_obj_name));
|
1056 |
+
$destination = rawurlencode($container_name_target."/".$dest_obj_name);
|
1057 |
+
|
1058 |
+
$hdrs = self::_process_headers($metadata, $headers);
|
1059 |
+
$hdrs[DESTINATION] = $destination;
|
1060 |
+
|
1061 |
+
$return_code = $this->_send_request($conn_type,$url_path,$hdrs,"COPY");
|
1062 |
+
switch ($return_code) {
|
1063 |
+
case 201:
|
1064 |
+
break;
|
1065 |
+
case 0:
|
1066 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
1067 |
+
$return_code = 0;
|
1068 |
+
break;
|
1069 |
+
case 404:
|
1070 |
+
$this->error_str = "Specified container/object did not exist.";
|
1071 |
+
break;
|
1072 |
+
default:
|
1073 |
+
$this->error_str = "Unexpected HTTP return code: $return_code.";
|
1074 |
+
}
|
1075 |
+
return $return_code;
|
1076 |
+
}
|
1077 |
+
|
1078 |
+
# DELETE /v1/Account/Container/Object
|
1079 |
+
#
|
1080 |
+
function delete_object($container_name, $object_name)
|
1081 |
+
{
|
1082 |
+
if ($container_name == "") {
|
1083 |
+
$this->error_str = "Container name not set.";
|
1084 |
+
return 0;
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
if ($container_name != "0" and !isset($container_name)) {
|
1088 |
+
$this->error_str = "Container name not set.";
|
1089 |
+
return 0;
|
1090 |
+
}
|
1091 |
+
|
1092 |
+
if (!$object_name) {
|
1093 |
+
$this->error_str = "Object name not set.";
|
1094 |
+
return 0;
|
1095 |
+
}
|
1096 |
+
|
1097 |
+
$url_path = $this->_make_path("STORAGE", $container_name,$object_name);
|
1098 |
+
$return_code = $this->_send_request("DEL_POST",$url_path,NULL,"DELETE");
|
1099 |
+
switch ($return_code) {
|
1100 |
+
case 204:
|
1101 |
+
break;
|
1102 |
+
case 0:
|
1103 |
+
$this->error_str .= ": Failed to obtain valid HTTP response.";
|
1104 |
+
$return_code = 0;
|
1105 |
+
break;
|
1106 |
+
case 404:
|
1107 |
+
$this->error_str = "Specified container did not exist to delete.";
|
1108 |
+
break;
|
1109 |
+
default:
|
1110 |
+
$this->error_str = "Unexpected HTTP return code: $return_code.";
|
1111 |
+
}
|
1112 |
+
return $return_code;
|
1113 |
+
}
|
1114 |
+
|
1115 |
+
function get_error()
|
1116 |
+
{
|
1117 |
+
return $this->error_str;
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
function setDebug($bool)
|
1121 |
+
{
|
1122 |
+
$this->dbug = $bool;
|
1123 |
+
foreach ($this->connections as $k => $v) {
|
1124 |
+
if (!is_null($v)) {
|
1125 |
+
curl_setopt($this->connections[$k], CURLOPT_VERBOSE, $this->dbug);
|
1126 |
+
}
|
1127 |
+
}
|
1128 |
+
}
|
1129 |
+
|
1130 |
+
function getCDNMUrl()
|
1131 |
+
{
|
1132 |
+
return $this->cdnm_url;
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
function getStorageUrl()
|
1136 |
+
{
|
1137 |
+
return $this->storage_url;
|
1138 |
+
}
|
1139 |
+
|
1140 |
+
function getAuthToken()
|
1141 |
+
{
|
1142 |
+
return $this->auth_token;
|
1143 |
+
}
|
1144 |
+
|
1145 |
+
function setCFAuth($cfs_auth, $servicenet=False)
|
1146 |
+
{
|
1147 |
+
if ($servicenet) {
|
1148 |
+
$this->storage_url = "https://snet-" . substr($cfs_auth->storage_url, 8);
|
1149 |
+
} else {
|
1150 |
+
$this->storage_url = $cfs_auth->storage_url;
|
1151 |
+
}
|
1152 |
+
$this->auth_token = $cfs_auth->auth_token;
|
1153 |
+
$this->cdnm_url = $cfs_auth->cdnm_url;
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
function setReadProgressFunc($func_name)
|
1157 |
+
{
|
1158 |
+
$this->_user_read_progress_callback_func = $func_name;
|
1159 |
+
}
|
1160 |
+
|
1161 |
+
function setWriteProgressFunc($func_name)
|
1162 |
+
{
|
1163 |
+
$this->_user_write_progress_callback_func = $func_name;
|
1164 |
+
}
|
1165 |
+
private function _header_cb($ch, $header)
|
1166 |
+
{
|
1167 |
+
$header_len = strlen($header);
|
1168 |
+
|
1169 |
+
if (preg_match("/^(HTTP\/1\.[01]) (\d{3}) (.*)/", $header, $matches)) {
|
1170 |
+
$this->response_status = $matches[2];
|
1171 |
+
$this->response_reason = $matches[3];
|
1172 |
+
return $header_len;
|
1173 |
+
}
|
1174 |
+
|
1175 |
+
if (strpos($header, ":") === False)
|
1176 |
+
return $header_len;
|
1177 |
+
list($name, $value) = explode(":", $header, 2);
|
1178 |
+
$value = trim($value);
|
1179 |
+
|
1180 |
+
switch (strtolower($name)) {
|
1181 |
+
case strtolower(CDN_ENABLED):
|
1182 |
+
$this->_cdn_enabled = strtolower($value) == "true";
|
1183 |
+
break;
|
1184 |
+
case strtolower(CDN_URI):
|
1185 |
+
$this->_cdn_uri = $value;
|
1186 |
+
break;
|
1187 |
+
case strtolower(CDN_SSL_URI):
|
1188 |
+
$this->_cdn_ssl_uri = $value;
|
1189 |
+
break;
|
1190 |
+
case strtolower(CDN_STREAMING_URI):
|
1191 |
+
$this->_cdn_streaming_uri = $value;
|
1192 |
+
break;
|
1193 |
+
case strtolower(CDN_TTL):
|
1194 |
+
$this->_cdn_ttl = $value;
|
1195 |
+
break;
|
1196 |
+
case strtolower(MANIFEST_HEADER):
|
1197 |
+
$this->_obj_manifest = $value;
|
1198 |
+
break;
|
1199 |
+
case strtolower(CDN_LOG_RETENTION):
|
1200 |
+
$this->_cdn_log_retention = strtolower($value) == "true";
|
1201 |
+
break;
|
1202 |
+
case strtolower(CDN_ACL_USER_AGENT):
|
1203 |
+
$this->_cdn_acl_user_agent = $value;
|
1204 |
+
break;
|
1205 |
+
case strtolower(CDN_ACL_REFERRER):
|
1206 |
+
$this->_cdn_acl_referrer = $value;
|
1207 |
+
break;
|
1208 |
+
case strtolower(ACCOUNT_CONTAINER_COUNT):
|
1209 |
+
$this->_account_container_count = (float)$value+0;
|
1210 |
+
break;
|
1211 |
+
case strtolower(ACCOUNT_BYTES_USED):
|
1212 |
+
$this->_account_bytes_used = (float)$value+0;
|
1213 |
+
break;
|
1214 |
+
case strtolower(CONTAINER_OBJ_COUNT):
|
1215 |
+
$this->_container_object_count = (float)$value+0;
|
1216 |
+
break;
|
1217 |
+
case strtolower(CONTAINER_BYTES_USED):
|
1218 |
+
$this->_container_bytes_used = (float)$value+0;
|
1219 |
+
break;
|
1220 |
+
case strtolower(ETAG_HEADER):
|
1221 |
+
$this->_obj_etag = $value;
|
1222 |
+
break;
|
1223 |
+
case strtolower(LAST_MODIFIED_HEADER):
|
1224 |
+
$this->_obj_last_modified = $value;
|
1225 |
+
break;
|
1226 |
+
case strtolower(CONTENT_TYPE_HEADER):
|
1227 |
+
$this->_obj_content_type = $value;
|
1228 |
+
break;
|
1229 |
+
case strtolower(CONTENT_LENGTH_HEADER):
|
1230 |
+
$this->_obj_content_length = (float)$value+0;
|
1231 |
+
break;
|
1232 |
+
case strtolower(ORIGIN_HEADER):
|
1233 |
+
$this->_obj_headers[ORIGIN_HEADER] = $value;
|
1234 |
+
break;
|
1235 |
+
case strtolower(ACCOUNT_KEY):
|
1236 |
+
$this->_account_key = $value;
|
1237 |
+
break;
|
1238 |
+
default:
|
1239 |
+
if (strncasecmp($name, METADATA_HEADER_PREFIX, strlen(METADATA_HEADER_PREFIX)) == 0) {
|
1240 |
+
$name = substr($name, strlen(METADATA_HEADER_PREFIX));
|
1241 |
+
$this->_obj_metadata[$name] = $value;
|
1242 |
+
}
|
1243 |
+
elseif ((strncasecmp($name, CONTENT_HEADER_PREFIX, strlen(CONTENT_HEADER_PREFIX)) == 0) ||
|
1244 |
+
(strncasecmp($name, ACCESS_CONTROL_HEADER_PREFIX, strlen(ACCESS_CONTROL_HEADER_PREFIX)) == 0)) {
|
1245 |
+
$this->_obj_headers[$name] = $value;
|
1246 |
+
}
|
1247 |
+
elseif (strncasecmp($name, ACCOUNT_METADATA_HEADER_PREFIX, strlen(ACCOUNT_METADATA_HEADER_PREFIX)) == 0) {
|
1248 |
+
$this->_account_metadata[$name] = $value;
|
1249 |
+
}
|
1250 |
+
elseif (strncasecmp($name, CONTAINER_METADATA_HEADER_PREFIX, strlen(CONTAINER_METADATA_HEADER_PREFIX)) == 0) {
|
1251 |
+
$this->_container_metadata[$name] = $value;
|
1252 |
+
}
|
1253 |
+
}
|
1254 |
+
return $header_len;
|
1255 |
+
}
|
1256 |
+
|
1257 |
+
private function _read_cb($ch, $fd, $length)
|
1258 |
+
{
|
1259 |
+
$data = fread($fd, $length);
|
1260 |
+
$len = strlen($data);
|
1261 |
+
if (isset($this->_user_write_progress_callback_func)) {
|
1262 |
+
call_user_func($this->_user_write_progress_callback_func, $len);
|
1263 |
+
}
|
1264 |
+
return $data;
|
1265 |
+
}
|
1266 |
+
|
1267 |
+
private function _write_cb($ch, $data)
|
1268 |
+
{
|
1269 |
+
$dlen = strlen($data);
|
1270 |
+
switch ($this->_write_callback_type) {
|
1271 |
+
case "TEXT_LIST":
|
1272 |
+
$this->_return_list = $this->_return_list . $data;
|
1273 |
+
//= explode("\n",$data); # keep tab,space
|
1274 |
+
//his->_text_list[] = rtrim($data,"\n\r\x0B"); # keep tab,space
|
1275 |
+
break;
|
1276 |
+
case "OBJECT_STREAM":
|
1277 |
+
fwrite($this->_obj_write_resource, $data, $dlen);
|
1278 |
+
break;
|
1279 |
+
case "OBJECT_STRING":
|
1280 |
+
$this->_obj_write_string .= $data;
|
1281 |
+
break;
|
1282 |
+
}
|
1283 |
+
if (isset($this->_user_read_progress_callback_func)) {
|
1284 |
+
call_user_func($this->_user_read_progress_callback_func, $dlen);
|
1285 |
+
}
|
1286 |
+
return $dlen;
|
1287 |
+
}
|
1288 |
+
|
1289 |
+
private function _auth_hdr_cb($ch, $header)
|
1290 |
+
{
|
1291 |
+
preg_match("/^HTTP\/1\.[01] (\d{3}) (.*)/", $header, $matches);
|
1292 |
+
if (isset($matches[1])) {
|
1293 |
+
$this->response_status = $matches[1];
|
1294 |
+
}
|
1295 |
+
if (isset($matches[2])) {
|
1296 |
+
$this->response_reason = $matches[2];
|
1297 |
+
}
|
1298 |
+
if (stripos($header, STORAGE_URL) === 0) {
|
1299 |
+
$this->storage_url = trim(substr($header, strlen(STORAGE_URL)+1));
|
1300 |
+
}
|
1301 |
+
if (stripos($header, CDNM_URL) === 0) {
|
1302 |
+
$this->cdnm_url = trim(substr($header, strlen(CDNM_URL)+1));
|
1303 |
+
}
|
1304 |
+
if (stripos($header, AUTH_TOKEN) === 0) {
|
1305 |
+
$this->auth_token = trim(substr($header, strlen(AUTH_TOKEN)+1));
|
1306 |
+
}
|
1307 |
+
if (stripos($header, AUTH_TOKEN_LEGACY) === 0) {
|
1308 |
+
$this->auth_token = trim(substr($header,strlen(AUTH_TOKEN_LEGACY)+1));
|
1309 |
+
}
|
1310 |
+
return strlen($header);
|
1311 |
+
}
|
1312 |
+
|
1313 |
+
private function _make_headers($hdrs=NULL)
|
1314 |
+
{
|
1315 |
+
$new_headers = array();
|
1316 |
+
$has_stoken = False;
|
1317 |
+
$has_uagent = False;
|
1318 |
+
if (is_array($hdrs)) {
|
1319 |
+
foreach ($hdrs as $h => $v) {
|
1320 |
+
if (is_int($h)) {
|
1321 |
+
list($h, $v) = explode(":", $v, 2);
|
1322 |
+
}
|
1323 |
+
|
1324 |
+
if (strncasecmp($h, AUTH_TOKEN, strlen(AUTH_TOKEN)) === 0) {
|
1325 |
+
$has_stoken = True;
|
1326 |
+
}
|
1327 |
+
if (strncasecmp($h, USER_AGENT_HEADER, strlen(USER_AGENT_HEADER)) === 0) {
|
1328 |
+
$has_uagent = True;
|
1329 |
+
}
|
1330 |
+
$new_headers[] = $h . ": " . trim($v);
|
1331 |
+
}
|
1332 |
+
}
|
1333 |
+
if (!$has_stoken) {
|
1334 |
+
$new_headers[] = AUTH_TOKEN . ": " . $this->auth_token;
|
1335 |
+
}
|
1336 |
+
if (!$has_uagent) {
|
1337 |
+
$new_headers[] = USER_AGENT_HEADER . ": " . USER_AGENT;
|
1338 |
+
}
|
1339 |
+
return $new_headers;
|
1340 |
+
}
|
1341 |
+
|
1342 |
+
private function _init($conn_type, $force_new=False)
|
1343 |
+
{
|
1344 |
+
if (!array_key_exists($conn_type, $this->connections)) {
|
1345 |
+
$this->error_str = "Invalid CURL_XXX connection type";
|
1346 |
+
return False;
|
1347 |
+
}
|
1348 |
+
|
1349 |
+
if (is_null($this->connections[$conn_type]) || $force_new) {
|
1350 |
+
$ch = curl_init();
|
1351 |
+
} else {
|
1352 |
+
return;
|
1353 |
+
}
|
1354 |
+
|
1355 |
+
if ($this->dbug) { curl_setopt($ch, CURLOPT_VERBOSE, 1); }
|
1356 |
+
|
1357 |
+
if (!is_null($this->cabundle_path)) {
|
1358 |
+
curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
|
1359 |
+
}
|
1360 |
+
if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) {
|
1361 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
1362 |
+
} else {
|
1363 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
1364 |
+
}
|
1365 |
+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
1366 |
+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
1367 |
+
curl_setopt($ch, CURLOPT_MAXREDIRS, 4);
|
1368 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
1369 |
+
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$this, '_header_cb'));
|
1370 |
+
|
1371 |
+
if ($conn_type == "GET_CALL") {
|
1372 |
+
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(&$this, '_write_cb'));
|
1373 |
+
}
|
1374 |
+
|
1375 |
+
if ($conn_type == "PUT_OBJ") {
|
1376 |
+
curl_setopt($ch, CURLOPT_PUT, 1);
|
1377 |
+
curl_setopt($ch, CURLOPT_READFUNCTION, array(&$this, '_read_cb'));
|
1378 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
1379 |
+
}
|
1380 |
+
if ($conn_type == "HEAD") {
|
1381 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "HEAD");
|
1382 |
+
curl_setopt($ch, CURLOPT_NOBODY, 1);
|
1383 |
+
}
|
1384 |
+
if ($conn_type == "PUT_CONT") {
|
1385 |
+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
|
1386 |
+
curl_setopt($ch, CURLOPT_INFILESIZE, 0);
|
1387 |
+
curl_setopt($ch, CURLOPT_NOBODY, 1);
|
1388 |
+
}
|
1389 |
+
if ($conn_type == "DEL_POST") {
|
1390 |
+
curl_setopt($ch, CURLOPT_NOBODY, 1);
|
1391 |
+
}
|
1392 |
+
if ($conn_type == "COPY") {
|
1393 |
+
curl_setopt($ch, CURLOPT_NOBODY, 1);
|
1394 |
+
}
|
1395 |
+
$this->connections[$conn_type] = $ch;
|
1396 |
+
return;
|
1397 |
+
}
|
1398 |
+
|
1399 |
+
private function _reset_callback_vars()
|
1400 |
+
{
|
1401 |
+
$this->_text_list = array();
|
1402 |
+
$this->_return_list = NULL;
|
1403 |
+
$this->_account_metadata = array();
|
1404 |
+
$this->_account_key = NULL;
|
1405 |
+
$this->_account_container_count = 0;
|
1406 |
+
$this->_account_bytes_used = 0;
|
1407 |
+
$this->_container_metadata = array();
|
1408 |
+
$this->_container_object_count = 0;
|
1409 |
+
$this->_container_bytes_used = 0;
|
1410 |
+
$this->_obj_delete_at = NULL;
|
1411 |
+
$this->_obj_delete_after = NULL;
|
1412 |
+
$this->_obj_etag = NULL;
|
1413 |
+
$this->_obj_last_modified = NULL;
|
1414 |
+
$this->_obj_content_type = NULL;
|
1415 |
+
$this->_obj_content_length = NULL;
|
1416 |
+
$this->_obj_metadata = array();
|
1417 |
+
$this->_obj_manifest = NULL;
|
1418 |
+
$this->_obj_headers = NULL;
|
1419 |
+
$this->_obj_write_string = "";
|
1420 |
+
$this->_cdn_streaming_uri = NULL;
|
1421 |
+
$this->_cdn_enabled = NULL;
|
1422 |
+
$this->_cdn_ssl_uri = NULL;
|
1423 |
+
$this->_cdn_uri = NULL;
|
1424 |
+
$this->_cdn_ttl = NULL;
|
1425 |
+
$this->response_status = 0;
|
1426 |
+
$this->response_reason = "";
|
1427 |
+
}
|
1428 |
+
|
1429 |
+
private function _make_path($t="STORAGE",$c=NULL,$o=NULL)
|
1430 |
+
{
|
1431 |
+
$path = array();
|
1432 |
+
switch ($t) {
|
1433 |
+
case "STORAGE":
|
1434 |
+
$path[] = $this->storage_url; break;
|
1435 |
+
case "CDN":
|
1436 |
+
$path[] = $this->cdnm_url; break;
|
1437 |
+
}
|
1438 |
+
if ($c != "") {
|
1439 |
+
$path[] = rawurlencode($c);
|
1440 |
+
}
|
1441 |
+
if ($o) {
|
1442 |
+
# mimic Python''s urllib.quote() feature of a "safe" '/' character
|
1443 |
+
#
|
1444 |
+
$path[] = str_replace("%2F","/",rawurlencode($o));
|
1445 |
+
}
|
1446 |
+
return implode("/",$path);
|
1447 |
+
}
|
1448 |
+
|
1449 |
+
private function _headers(&$obj)
|
1450 |
+
{
|
1451 |
+
$hdrs = self::_process_headers($obj->metadata, $obj->headers);
|
1452 |
+
if ($obj->manifest)
|
1453 |
+
$hdrs[MANIFEST_HEADER] = $obj->manifest;
|
1454 |
+
|
1455 |
+
return $hdrs;
|
1456 |
+
}
|
1457 |
+
|
1458 |
+
private function _process_headers($metadata=null, $headers=null)
|
1459 |
+
{
|
1460 |
+
$rules = array(
|
1461 |
+
array(
|
1462 |
+
'prefix' => METADATA_HEADER_PREFIX,
|
1463 |
+
),
|
1464 |
+
array(
|
1465 |
+
'prefix' => '',
|
1466 |
+
'filter' => array( # key order is important, first match decides
|
1467 |
+
CONTENT_TYPE_HEADER => false,
|
1468 |
+
CONTENT_LENGTH_HEADER => false,
|
1469 |
+
CONTENT_HEADER_PREFIX => true,
|
1470 |
+
ACCESS_CONTROL_HEADER_PREFIX => true,
|
1471 |
+
ORIGIN_HEADER => true,
|
1472 |
+
),
|
1473 |
+
),
|
1474 |
+
);
|
1475 |
+
|
1476 |
+
$hdrs = array();
|
1477 |
+
$argc = func_num_args();
|
1478 |
+
$argv = func_get_args();
|
1479 |
+
for ($argi = 0; $argi < $argc; $argi++) {
|
1480 |
+
if(!is_array($argv[$argi])) continue;
|
1481 |
+
|
1482 |
+
$rule = $rules[$argi];
|
1483 |
+
foreach ($argv[$argi] as $k => $v) {
|
1484 |
+
$k = trim($k);
|
1485 |
+
$v = trim($v);
|
1486 |
+
if (strpos($k, ":") !== False) throw new SyntaxException(
|
1487 |
+
"Header names cannot contain a ':' character.");
|
1488 |
+
|
1489 |
+
if (array_key_exists('filter', $rule)) {
|
1490 |
+
$result = null;
|
1491 |
+
foreach ($rule['filter'] as $p => $f) {
|
1492 |
+
if (strncasecmp($k, $p, strlen($p)) == 0) {
|
1493 |
+
$result = $f;
|
1494 |
+
break;
|
1495 |
+
}
|
1496 |
+
}
|
1497 |
+
if (!$result) throw new SyntaxException(sprintf(
|
1498 |
+
"Header name %s is not allowed", $k));
|
1499 |
+
}
|
1500 |
+
|
1501 |
+
$k = $rule['prefix'] . $k;
|
1502 |
+
if (strlen($k) > MAX_HEADER_NAME_LEN || strlen($v) > MAX_HEADER_VALUE_LEN)
|
1503 |
+
throw new SyntaxException(sprintf(
|
1504 |
+
"Header %s exceeds maximum length: %d/%d",
|
1505 |
+
$k, strlen($k), strlen($v)));
|
1506 |
+
|
1507 |
+
$hdrs[$k] = $v;
|
1508 |
+
}
|
1509 |
+
}
|
1510 |
+
|
1511 |
+
return $hdrs;
|
1512 |
+
}
|
1513 |
+
|
1514 |
+
private function _send_request($conn_type, $url_path, $hdrs=NULL, $method="GET", $force_new=False)
|
1515 |
+
{
|
1516 |
+
$this->_init($conn_type, $force_new);
|
1517 |
+
$this->_reset_callback_vars();
|
1518 |
+
$headers = $this->_make_headers($hdrs);
|
1519 |
+
|
1520 |
+
if (gettype($this->connections[$conn_type]) == "unknown type")
|
1521 |
+
throw new ConnectionNotOpenException (
|
1522 |
+
"Connection is not open."
|
1523 |
+
);
|
1524 |
+
|
1525 |
+
switch ($method) {
|
1526 |
+
case "COPY":
|
1527 |
+
curl_setopt($this->connections[$conn_type],
|
1528 |
+
CURLOPT_CUSTOMREQUEST, "COPY");
|
1529 |
+
break;
|
1530 |
+
case "DELETE":
|
1531 |
+
curl_setopt($this->connections[$conn_type],
|
1532 |
+
CURLOPT_CUSTOMREQUEST, "DELETE");
|
1533 |
+
break;
|
1534 |
+
case "POST":
|
1535 |
+
curl_setopt($this->connections[$conn_type],
|
1536 |
+
CURLOPT_CUSTOMREQUEST, "POST");
|
1537 |
+
default:
|
1538 |
+
break;
|
1539 |
+
}
|
1540 |
+
|
1541 |
+
curl_setopt($this->connections[$conn_type],
|
1542 |
+
CURLOPT_HTTPHEADER, $headers);
|
1543 |
+
|
1544 |
+
curl_setopt($this->connections[$conn_type],
|
1545 |
+
CURLOPT_URL, $url_path);
|
1546 |
+
|
1547 |
+
if (!curl_exec($this->connections[$conn_type]) && curl_errno($this->connections[$conn_type]) !== 0) {
|
1548 |
+
$this->error_str = "(curl error: "
|
1549 |
+
. curl_errno($this->connections[$conn_type]) . ") ";
|
1550 |
+
$this->error_str .= curl_error($this->connections[$conn_type]);
|
1551 |
+
return False;
|
1552 |
+
}
|
1553 |
+
return curl_getinfo($this->connections[$conn_type], CURLINFO_HTTP_CODE);
|
1554 |
+
}
|
1555 |
+
|
1556 |
+
function close()
|
1557 |
+
{
|
1558 |
+
foreach ($this->connections as $cnx) {
|
1559 |
+
if (isset($cnx)) {
|
1560 |
+
curl_close($cnx);
|
1561 |
+
$this->connections[$cnx] = NULL;
|
1562 |
+
}
|
1563 |
+
}
|
1564 |
+
}
|
1565 |
+
private function create_array()
|
1566 |
+
{
|
1567 |
+
$this->_text_list = explode("\n",rtrim($this->_return_list,"\n\x0B"));
|
1568 |
+
return True;
|
1569 |
+
}
|
1570 |
+
|
1571 |
+
}
|
1572 |
+
|
1573 |
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
1574 |
+
|
1575 |
+
/*
|
1576 |
+
* Local variables:
|
1577 |
+
* tab-width: 4
|
1578 |
+
* c-basic-offset: 4
|
1579 |
+
* c-hanging-comment-ender-p: nil
|
1580 |
+
* End:
|
1581 |
+
*/
|
1582 |
+
?>
|
includes/ftp.class.php
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
<?php
|
2 |
-
/* from http://www.solutionbot.com/2009/01/02/php-ftp-class/ */
|
3 |
-
class UpdraftPlus_ftp_wrapper
|
4 |
-
{
|
5 |
private $conn_id;
|
6 |
private $host;
|
7 |
private $username;
|
@@ -10,6 +9,7 @@ class UpdraftPlus_ftp_wrapper
|
|
10 |
public $timeout = 90;
|
11 |
public $passive = true;
|
12 |
public $system_type = '';
|
|
|
13 |
public $login_type = 'non-encrypted';
|
14 |
|
15 |
public function __construct($host, $username, $password, $port = 21)
|
@@ -22,7 +22,7 @@ class UpdraftPlus_ftp_wrapper
|
|
22 |
|
23 |
public function connect()
|
24 |
{
|
25 |
-
$this->conn_id = ftp_connect($this->host, $this->port);
|
26 |
|
27 |
if ($this->conn_id === false) return false;
|
28 |
|
@@ -51,69 +51,125 @@ class UpdraftPlus_ftp_wrapper
|
|
51 |
}
|
52 |
}
|
53 |
|
54 |
-
public function put($local_file_path, $remote_file_path, $mode =
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
return false;
|
63 |
}
|
|
|
|
|
|
|
64 |
}
|
65 |
|
66 |
-
public function get($local_file_path, $remote_file_path, $mode =
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
71 |
}
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
}
|
77 |
-
|
78 |
-
public function chmod($permissions, $remote_filename)
|
79 |
-
|
80 |
-
if ($this->is_octal($permissions))
|
81 |
-
{
|
82 |
$result = ftp_chmod($this->conn_id, $permissions, $remote_filename);
|
83 |
-
if ($result)
|
84 |
-
{
|
85 |
return true;
|
86 |
-
}
|
87 |
-
else
|
88 |
-
{
|
89 |
return false;
|
90 |
}
|
91 |
-
}
|
92 |
-
else
|
93 |
-
{
|
94 |
throw new Exception('$permissions must be an octal number');
|
95 |
}
|
96 |
}
|
97 |
|
98 |
-
public function chdir($directory)
|
99 |
-
{
|
100 |
ftp_chdir($this->conn_id, $directory);
|
101 |
}
|
102 |
|
103 |
-
public function delete($remote_file_path)
|
104 |
-
|
105 |
-
if (ftp_delete($this->conn_id, $remote_file_path))
|
106 |
-
{
|
107 |
return true;
|
108 |
-
}
|
109 |
-
else
|
110 |
-
{
|
111 |
return false;
|
112 |
}
|
113 |
}
|
114 |
|
115 |
-
public function make_dir($directory)
|
116 |
-
{
|
117 |
if (ftp_mkdir($this->conn_id, $directory))
|
118 |
{
|
119 |
return true;
|
@@ -124,8 +180,7 @@ class UpdraftPlus_ftp_wrapper
|
|
124 |
}
|
125 |
}
|
126 |
|
127 |
-
public function rename($old_name, $new_name)
|
128 |
-
{
|
129 |
if (ftp_rename($this->conn_id, $old_name, $new_name))
|
130 |
{
|
131 |
return true;
|
@@ -136,8 +191,7 @@ class UpdraftPlus_ftp_wrapper
|
|
136 |
}
|
137 |
}
|
138 |
|
139 |
-
public function remove_dir($directory)
|
140 |
-
{
|
141 |
if (ftp_rmdir($this->conn_id, $directory))
|
142 |
{
|
143 |
return true;
|
@@ -148,29 +202,24 @@ class UpdraftPlus_ftp_wrapper
|
|
148 |
}
|
149 |
}
|
150 |
|
151 |
-
public function dir_list($directory)
|
152 |
-
{
|
153 |
$contents = ftp_nlist($this->conn_id, $directory);
|
154 |
return $contents;
|
155 |
}
|
156 |
|
157 |
-
public function cdup()
|
158 |
-
{
|
159 |
ftp_cdup($this->conn_id);
|
160 |
}
|
161 |
|
162 |
-
public function current_dir()
|
163 |
-
{
|
164 |
return ftp_pwd($this->conn_id);
|
165 |
}
|
166 |
|
167 |
-
private function is_octal($i)
|
168 |
-
{
|
169 |
return decoct(octdec($i)) == $i;
|
170 |
}
|
171 |
|
172 |
-
public function __destruct()
|
173 |
-
{
|
174 |
if ($this->conn_id)
|
175 |
{
|
176 |
ftp_close($this->conn_id);
|
1 |
<?php
|
2 |
+
/* Adapted from http://www.solutionbot.com/2009/01/02/php-ftp-class/ */
|
3 |
+
class UpdraftPlus_ftp_wrapper {
|
|
|
4 |
private $conn_id;
|
5 |
private $host;
|
6 |
private $username;
|
9 |
public $timeout = 90;
|
10 |
public $passive = true;
|
11 |
public $system_type = '';
|
12 |
+
public $ssl = false;
|
13 |
public $login_type = 'non-encrypted';
|
14 |
|
15 |
public function __construct($host, $username, $password, $port = 21)
|
22 |
|
23 |
public function connect()
|
24 |
{
|
25 |
+
$this->conn_id = ftp_connect($this->host, $this->port, 30);
|
26 |
|
27 |
if ($this->conn_id === false) return false;
|
28 |
|
51 |
}
|
52 |
}
|
53 |
|
54 |
+
public function put($local_file_path, $remote_file_path, $mode = FTP_BINARY, $resume = false, $updraftplus = false) {
|
55 |
+
|
56 |
+
$file_size = filesize($local_file_path);
|
57 |
+
|
58 |
+
$existing_size = 0;
|
59 |
+
if ($resume) {
|
60 |
+
$existing_size = ftp_size($this->conn_id, $remote_file_path);
|
61 |
+
if ($existing_size <=0) { $resume = false; $existing_size = 0; }
|
62 |
+
elseif ($updraftplus) {
|
63 |
+
$updraftplus->log("File already exists at remote site: size $existing_size. Will attempt resumption.");
|
64 |
+
if ($existing_size >= $file_size) {
|
65 |
+
$updraftplus->log("File is apparently already completely uploaded");
|
66 |
+
return true;
|
67 |
+
}
|
68 |
+
}
|
69 |
}
|
70 |
+
|
71 |
+
// From here on, $file_size is only used for logging calculations. We want to avoid divsion by zero.
|
72 |
+
$file_size = max($file_size, 1);
|
73 |
+
|
74 |
+
if (!$fh = fopen($local_file_path, 'rb')) return false;
|
75 |
+
if ($existing_size) fseek($fh, $existing_size);
|
76 |
+
|
77 |
+
$ret = ftp_nb_fput($this->conn_id, $remote_file_path, $fh, FTP_BINARY, $existing_size);
|
78 |
+
|
79 |
+
// $existing_size can now be re-purposed
|
80 |
+
|
81 |
+
while ($ret == FTP_MOREDATA) {
|
82 |
+
if ($updraftplus) {
|
83 |
+
$new_size = ftell($fh);
|
84 |
+
if ($new_size - $existing_size > 524288) {
|
85 |
+
$existing_size = $new_size;
|
86 |
+
$percent = round(100*$new_size/$file_size,1);
|
87 |
+
$updraftplus->record_uploaded_chunk($percent, '', $local_file_path);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
// Continue upload
|
91 |
+
$ret = ftp_nb_continue($this->conn_id);
|
92 |
+
}
|
93 |
+
|
94 |
+
fclose($fh);
|
95 |
+
|
96 |
+
if ($ret != FTP_FINISHED) {
|
97 |
+
if ($updraftplus) $updraftplus->log("FTP upload: error ($ret)");
|
98 |
return false;
|
99 |
}
|
100 |
+
|
101 |
+
return true;
|
102 |
+
|
103 |
}
|
104 |
|
105 |
+
public function get($local_file_path, $remote_file_path, $mode = FTP_BINARY, $resume = false, $updraftplus = false) {
|
106 |
+
|
107 |
+
$file_last_size = 0;
|
108 |
+
|
109 |
+
if ($resume) {
|
110 |
+
if (!$fh = fopen($local_file_path, 'ab')) return false;
|
111 |
+
clearstatcache($local_file_path);
|
112 |
+
$file_last_size = filesize($local_file_path);
|
113 |
+
} else {
|
114 |
+
if (!$fh = fopen($local_file_path, 'wb')) return false;
|
115 |
}
|
116 |
+
|
117 |
+
$ret = ftp_nb_fget($this->conn_id, $fh, $remote_file_path, $mode, $file_last_size);
|
118 |
+
|
119 |
+
if (false == $ret) return false;
|
120 |
+
|
121 |
+
while ($ret == FTP_MOREDATA) {
|
122 |
+
|
123 |
+
if ($updraftplus) {
|
124 |
+
$file_now_size = filesize($local_file_path);
|
125 |
+
if ($file_now_size - $file_last_size > 524288) {
|
126 |
+
$updraftplus->log("FTP fetch: file size is now: ".sprintf("%0.2f",filesize($local_file_path)/1048576)." Mb");
|
127 |
+
$file_last_size = $file_now_size;
|
128 |
+
}
|
129 |
+
clearstatcache($local_file_path);
|
130 |
+
}
|
131 |
+
|
132 |
+
$ret = ftp_nb_continue($this->conn_id);
|
133 |
}
|
134 |
+
|
135 |
+
fclose($fh);
|
136 |
+
|
137 |
+
if ($ret == FTP_FINISHED) {
|
138 |
+
if ($updraftplus) $updraftplus->log("FTP fetch: fetch complete");
|
139 |
+
return true;
|
140 |
+
} else {
|
141 |
+
if ($updraftplus) $updraftplus->log("FTP fetch: fetch failed");
|
142 |
+
return false;
|
143 |
+
}
|
144 |
+
|
145 |
}
|
146 |
+
|
147 |
+
public function chmod($permissions, $remote_filename) {
|
148 |
+
if ($this->is_octal($permissions)) {
|
|
|
|
|
149 |
$result = ftp_chmod($this->conn_id, $permissions, $remote_filename);
|
150 |
+
if ($result) {
|
|
|
151 |
return true;
|
152 |
+
} else {
|
|
|
|
|
153 |
return false;
|
154 |
}
|
155 |
+
} else {
|
|
|
|
|
156 |
throw new Exception('$permissions must be an octal number');
|
157 |
}
|
158 |
}
|
159 |
|
160 |
+
public function chdir($directory) {
|
|
|
161 |
ftp_chdir($this->conn_id, $directory);
|
162 |
}
|
163 |
|
164 |
+
public function delete($remote_file_path) {
|
165 |
+
if (ftp_delete($this->conn_id, $remote_file_path)) {
|
|
|
|
|
166 |
return true;
|
167 |
+
} else {
|
|
|
|
|
168 |
return false;
|
169 |
}
|
170 |
}
|
171 |
|
172 |
+
public function make_dir($directory) {
|
|
|
173 |
if (ftp_mkdir($this->conn_id, $directory))
|
174 |
{
|
175 |
return true;
|
180 |
}
|
181 |
}
|
182 |
|
183 |
+
public function rename($old_name, $new_name) {
|
|
|
184 |
if (ftp_rename($this->conn_id, $old_name, $new_name))
|
185 |
{
|
186 |
return true;
|
191 |
}
|
192 |
}
|
193 |
|
194 |
+
public function remove_dir($directory) {
|
|
|
195 |
if (ftp_rmdir($this->conn_id, $directory))
|
196 |
{
|
197 |
return true;
|
202 |
}
|
203 |
}
|
204 |
|
205 |
+
public function dir_list($directory) {
|
|
|
206 |
$contents = ftp_nlist($this->conn_id, $directory);
|
207 |
return $contents;
|
208 |
}
|
209 |
|
210 |
+
public function cdup() {
|
|
|
211 |
ftp_cdup($this->conn_id);
|
212 |
}
|
213 |
|
214 |
+
public function current_dir() {
|
|
|
215 |
return ftp_pwd($this->conn_id);
|
216 |
}
|
217 |
|
218 |
+
private function is_octal($i) {
|
|
|
219 |
return decoct(octdec($i)) == $i;
|
220 |
}
|
221 |
|
222 |
+
public function __destruct() {
|
|
|
223 |
if ($this->conn_id)
|
224 |
{
|
225 |
ftp_close($this->conn_id);
|
includes/ud-plupload.js
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($){
|
2 |
+
|
3 |
+
// create the uploader and pass the config from above
|
4 |
+
var uploader = new plupload.Uploader(updraft_plupload_config);
|
5 |
+
|
6 |
+
// checks if browser supports drag and drop upload, makes some css adjustments if necessary
|
7 |
+
uploader.bind('Init', function(up){
|
8 |
+
var uploaddiv = $('#plupload-upload-ui');
|
9 |
+
|
10 |
+
if(up.features.dragdrop){
|
11 |
+
uploaddiv.addClass('drag-drop');
|
12 |
+
$('#drag-drop-area')
|
13 |
+
.bind('dragover.wp-uploader', function(){ uploaddiv.addClass('drag-over'); })
|
14 |
+
.bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });
|
15 |
+
|
16 |
+
} else {
|
17 |
+
uploaddiv.removeClass('drag-drop');
|
18 |
+
$('#drag-drop-area').unbind('.wp-uploader');
|
19 |
+
}
|
20 |
+
});
|
21 |
+
|
22 |
+
uploader.init();
|
23 |
+
|
24 |
+
// a file was added in the queue
|
25 |
+
uploader.bind('FilesAdded', function(up, files){
|
26 |
+
// var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
|
27 |
+
|
28 |
+
plupload.each(files, function(file){
|
29 |
+
|
30 |
+
if (! /^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz|gz\.crypt)$/i.test(file.name)) {
|
31 |
+
alert(file.name+': This file is a zip, but does not appear to be an UpdraftPlus backup archive (such files are .zip files which have a name like: backup_(time)_(site name)_(code)_(type).zip)');
|
32 |
+
uploader.removeFile(file);
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
// a file was added, you may want to update your DOM here...
|
37 |
+
$('#filelist').append(
|
38 |
+
'<div class="file" id="' + file.id + '"><b>' +
|
39 |
+
file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
|
40 |
+
'<div class="fileprogress"></div></div>');
|
41 |
+
});
|
42 |
+
|
43 |
+
up.refresh();
|
44 |
+
up.start();
|
45 |
+
});
|
46 |
+
|
47 |
+
uploader.bind('UploadProgress', function(up, file) {
|
48 |
+
|
49 |
+
$('#' + file.id + " .fileprogress").width(file.percent + "%");
|
50 |
+
$('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
|
51 |
+
});
|
52 |
+
|
53 |
+
uploader.bind('Error', function(up, error) {
|
54 |
+
|
55 |
+
alert('Upload error (code '+error.code+") : "+error.message+" (make sure that you were trying to upload a zip file previously created by UpdraftPlus)");
|
56 |
+
|
57 |
+
});
|
58 |
+
|
59 |
+
|
60 |
+
// a file was uploaded
|
61 |
+
uploader.bind('FileUploaded', function(up, file, response) {
|
62 |
+
|
63 |
+
if (response.status == '200') {
|
64 |
+
// this is your ajax response, update the DOM with it or something...
|
65 |
+
if (response.response.substring(0,6) == 'ERROR:') {
|
66 |
+
alert("Upload error: "+response.response.substring(6));
|
67 |
+
} else if (response.response.substring(0,3) == 'OK:') {
|
68 |
+
updraft_updatehistory(1);
|
69 |
+
} else {
|
70 |
+
alert('Unknown server response: '+response.response);
|
71 |
+
}
|
72 |
+
} else {
|
73 |
+
alert('Unknown server response status: '+response.code);
|
74 |
+
}
|
75 |
+
|
76 |
+
});
|
77 |
+
|
78 |
+
});
|
79 |
+
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
|
84 |
+
|
85 |
+
|
86 |
+
// Next: the encrypted database pluploader
|
87 |
+
|
88 |
+
jQuery(document).ready(function($){
|
89 |
+
|
90 |
+
// create the uploader and pass the config from above
|
91 |
+
var uploader = new plupload.Uploader(updraft_plupload_config2);
|
92 |
+
|
93 |
+
// checks if browser supports drag and drop upload, makes some css adjustments if necessary
|
94 |
+
uploader.bind('Init', function(up){
|
95 |
+
var uploaddiv = $('#plupload-upload-ui2');
|
96 |
+
|
97 |
+
if(up.features.dragdrop){
|
98 |
+
uploaddiv.addClass('drag-drop');
|
99 |
+
$('#drag-drop-area2')
|
100 |
+
.bind('dragover.wp-uploader', function(){ uploaddiv.addClass('drag-over'); })
|
101 |
+
.bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });
|
102 |
+
} else {
|
103 |
+
uploaddiv.removeClass('drag-drop');
|
104 |
+
$('#drag-drop-area2').unbind('.wp-uploader');
|
105 |
+
}
|
106 |
+
});
|
107 |
+
|
108 |
+
uploader.init();
|
109 |
+
|
110 |
+
// a file was added in the queue
|
111 |
+
uploader.bind('FilesAdded', function(up, files){
|
112 |
+
// var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
|
113 |
+
|
114 |
+
plupload.each(files, function(file){
|
115 |
+
|
116 |
+
if (! /^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i.test(file.name)) {
|
117 |
+
alert(file.name+': This file does not appear to be an UpdraftPlus encrypted database archive (such files are .gz.crypt files which have a name like: backup_(time)_(site name)_(code)_db.crypt.gz)');
|
118 |
+
uploader.removeFile(file);
|
119 |
+
return;
|
120 |
+
}
|
121 |
+
|
122 |
+
// a file was added, you may want to update your DOM here...
|
123 |
+
$('#filelist2').append(
|
124 |
+
'<div class="file" id="' + file.id + '"><b>' +
|
125 |
+
file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
|
126 |
+
'<div class="fileprogress"></div></div>');
|
127 |
+
});
|
128 |
+
|
129 |
+
up.refresh();
|
130 |
+
up.start();
|
131 |
+
});
|
132 |
+
|
133 |
+
uploader.bind('UploadProgress', function(up, file) {
|
134 |
+
|
135 |
+
$('#' + file.id + " .fileprogress").width(file.percent + "%");
|
136 |
+
$('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
|
137 |
+
});
|
138 |
+
|
139 |
+
uploader.bind('Error', function(up, error) {
|
140 |
+
|
141 |
+
alert('Upload error (code '+error.code+") : "+error.message+" (make sure that you were trying to upload a backup file previously created by UpdraftPlus)");
|
142 |
+
|
143 |
+
});
|
144 |
+
|
145 |
+
// a file was uploaded
|
146 |
+
uploader.bind('FileUploaded', function(up, file, response) {
|
147 |
+
|
148 |
+
if (response.status == '200') {
|
149 |
+
// this is your ajax response, update the DOM with it or something...
|
150 |
+
if (response.response.substring(0,6) == 'ERROR:') {
|
151 |
+
alert("Upload error: "+response.response.substring(6));
|
152 |
+
} else if (response.response.substring(0,3) == 'OK:') {
|
153 |
+
bkey = response.response.substring(3);
|
154 |
+
// $('#' + file.id + " .fileprogress").width("100%");
|
155 |
+
// $('#' + file.id + " span").append('<button type="button" onclick="updraftplus_downloadstage2(\'db\', \'db\'">Download to your computer</button>');
|
156 |
+
// $('#' + file.id + " span").append('<form action="admin-ajax.php" onsubmit="return updraft_downloader(\'+bkey+''\', \'db\')" method="post"><input type="hidden" name="_wpnonce" value="'+updraft_downloader_nonce+'"><input type="hidden" name="action" value="updraft_download_backup" /><input type="hidden" name="type" value="db" /><input type="hidden" name="timestamp" value="'+bkey+'" /><input type="submit" value="Download" /></form>');
|
157 |
+
$('#' + file.id + " .fileprogress").hide();
|
158 |
+
$('#' + file.id).append('The file was uploaded. <a href="?page=updraftplus&action=downloadfile&updraftplus_file='+bkey+'&decrypt_key='+$('#updraftplus_db_decrypt').val()+'">Follow this link to attempt decryption and download the database file to your computer.</a> This decryption key will be attempted: '+$('#updraftplus_db_decrypt').val().replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"));
|
159 |
+
} else {
|
160 |
+
alert('Unknown server response: '+response.response);
|
161 |
+
}
|
162 |
+
} else {
|
163 |
+
alert('Unknown server response status: '+response.code);
|
164 |
+
}
|
165 |
+
|
166 |
+
});
|
167 |
+
|
168 |
+
});
|
includes/updraft-restorer.php
CHANGED
@@ -2,16 +2,139 @@
|
|
2 |
class Updraft_Restorer extends WP_Upgrader {
|
3 |
|
4 |
function backup_strings() {
|
|
|
5 |
$this->strings['no_package'] = __('Backup file not available.','updraftplus');
|
6 |
$this->strings['unpack_package'] = __('Unpacking backup...','updraftplus');
|
|
|
|
|
7 |
$this->strings['moving_old'] = __('Moving old directory out of the way...','updraftplus');
|
8 |
$this->strings['moving_backup'] = __('Moving unpacked backup in place...','updraftplus');
|
|
|
9 |
$this->strings['cleaning_up'] = __('Cleaning up rubbish...','updraftplus');
|
10 |
-
$this->strings['
|
|
|
11 |
$this->strings['new_move_failed'] = __('Could not move new directory into place. Check your wp-content/upgrade folder.','updraftplus');
|
12 |
$this->strings['delete_failed'] = __('Failed to delete working directory after restoring.','updraftplus');
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
function restore_backup($backup_file, $type, $service, $info) {
|
16 |
|
17 |
global $wp_filesystem;
|
@@ -25,9 +148,10 @@ class Updraft_Restorer extends WP_Upgrader {
|
|
25 |
|
26 |
$wp_dir = trailingslashit($wp_filesystem->abspath());
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
31 |
|
32 |
$delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
|
33 |
if ('none' == $service) {
|
@@ -37,69 +161,163 @@ class Updraft_Restorer extends WP_Upgrader {
|
|
37 |
|
38 |
$working_dir = $this->unpack_package($download, $delete);
|
39 |
if (is_wp_error($working_dir)) return $working_dir;
|
40 |
-
|
|
|
|
|
41 |
if ($type == 'others' ) {
|
42 |
|
43 |
// In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find
|
44 |
|
45 |
-
$
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
}
|
67 |
-
}
|
68 |
-
# Now, move in the new one
|
69 |
-
if ( !$wp_filesystem->move($working_dir . "/$file", $wp_dir . "wp-content/$file", true) ) {
|
70 |
-
return new WP_Error('new_move_failed', $this->strings['new_move_failed']);
|
71 |
-
}
|
72 |
}
|
73 |
}
|
|
|
|
|
|
|
|
|
74 |
}
|
|
|
|
|
|
|
|
|
75 |
|
76 |
} else {
|
77 |
-
|
78 |
show_message($this->strings['moving_old']);
|
79 |
-
if ( !$wp_filesystem->move($wp_dir . "wp-content/$dirname", $wp_dir . "wp-content/$dirname-old", true) ) {
|
80 |
-
return new WP_Error('old_move_failed', $this->strings['old_move_failed']);
|
81 |
-
}
|
82 |
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
}
|
87 |
-
|
88 |
}
|
89 |
|
|
|
90 |
show_message($this->strings['cleaning_up']);
|
91 |
-
if (
|
92 |
-
return new WP_Error('delete_failed', $this->strings['delete_failed']);
|
93 |
}
|
94 |
|
95 |
switch($type) {
|
|
|
|
|
|
|
96 |
case 'uploads':
|
97 |
@$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", 0775, true);
|
98 |
break;
|
|
|
|
|
99 |
default:
|
100 |
@$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", FS_CHMOD_DIR);
|
101 |
}
|
102 |
}
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
?>
|
2 |
class Updraft_Restorer extends WP_Upgrader {
|
3 |
|
4 |
function backup_strings() {
|
5 |
+
$this->strings['not_possible'] = __('UpdraftPlus is not able to directly restore this kind of entity. It must be restored manually.','updraftplus');
|
6 |
$this->strings['no_package'] = __('Backup file not available.','updraftplus');
|
7 |
$this->strings['unpack_package'] = __('Unpacking backup...','updraftplus');
|
8 |
+
$this->strings['decrypt_database'] = __('Decrypting database (can take a while)...','updraftplus');
|
9 |
+
$this->strings['decrypted_database'] = __('Database successfully decrypted.','updraftplus');
|
10 |
$this->strings['moving_old'] = __('Moving old directory out of the way...','updraftplus');
|
11 |
$this->strings['moving_backup'] = __('Moving unpacked backup in place...','updraftplus');
|
12 |
+
$this->strings['restore_database'] = __('Restoring the database (on a large site this can take a long time - if it times out (which can happen if your web hosting company has configured your hosting to limit resources) then you should use a different method, such as phpMyAdmin)...','updraftplus');
|
13 |
$this->strings['cleaning_up'] = __('Cleaning up rubbish...','updraftplus');
|
14 |
+
$this->strings['old_delete_failed'] = __('Could not move old directory out of the way. Perhaps you already have -old directories that need deleting first?','updraftplus');
|
15 |
+
$this->strings['old_move_failed'] = __('Could not delete old directory.','updraftplus');
|
16 |
$this->strings['new_move_failed'] = __('Could not move new directory into place. Check your wp-content/upgrade folder.','updraftplus');
|
17 |
$this->strings['delete_failed'] = __('Failed to delete working directory after restoring.','updraftplus');
|
18 |
}
|
19 |
|
20 |
+
function unpack_package($package, $delete_package = true) {
|
21 |
+
|
22 |
+
// If not database, then it is a zip - unpack in the usual way
|
23 |
+
if (!preg_match('/db\.gz(\.crypt)?$/i', $package)) return parent::unpack_package($package, $delete_package);
|
24 |
+
|
25 |
+
// Unpack a database. The general shape of the following is copied from class-wp-upgrader.php
|
26 |
+
|
27 |
+
@set_time_limit(1800);
|
28 |
+
|
29 |
+
global $wp_filesystem;
|
30 |
+
|
31 |
+
$this->skin->feedback('unpack_package');
|
32 |
+
|
33 |
+
$upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
|
34 |
+
|
35 |
+
//Clean up contents of upgrade directory beforehand.
|
36 |
+
$upgrade_files = $wp_filesystem->dirlist($upgrade_folder);
|
37 |
+
if ( !empty($upgrade_files) ) {
|
38 |
+
foreach ( $upgrade_files as $file )
|
39 |
+
$wp_filesystem->delete($upgrade_folder . $file['name'], true);
|
40 |
+
}
|
41 |
+
|
42 |
+
//We need a working directory
|
43 |
+
$working_dir = $upgrade_folder . basename($package, '.crypt');
|
44 |
+
|
45 |
+
// Clean up working directory
|
46 |
+
if ( $wp_filesystem->is_dir($working_dir) )
|
47 |
+
$wp_filesystem->delete($working_dir, true);
|
48 |
+
|
49 |
+
if (!$wp_filesystem->mkdir($working_dir, 0775)) return new WP_Error('mkdir_failed', __('Failed to create a temporary directory','updraftplus'));
|
50 |
+
|
51 |
+
// Unpack package to working directory
|
52 |
+
if (preg_match('/\.crypt$/i', $package)) {
|
53 |
+
$this->skin->feedback('decrypt_database');
|
54 |
+
$encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
|
55 |
+
if (!$encryption) return new WP_Error('no_encryption_key', __('Decryption failed. The database file is encrypted, but you have no encryption key entered.', 'updraftplus'));
|
56 |
+
|
57 |
+
// Encrypted - decrypt it
|
58 |
+
require_once(UPDRAFTPLUS_DIR.'/includes/phpseclib/Crypt/Rijndael.php');
|
59 |
+
$rijndael = new Crypt_Rijndael();
|
60 |
+
|
61 |
+
// Get decryption key
|
62 |
+
$rijndael->setKey($encryption);
|
63 |
+
$ciphertext = $rijndael->decrypt($wp_filesystem->get_contents($package));
|
64 |
+
if ($ciphertext) {
|
65 |
+
$this->skin->feedback('decrypted_database');
|
66 |
+
if (!$wp_filesystem->put_contents($working_dir.'/backup.db.gz', $ciphertext)) {
|
67 |
+
return new WP_Error('write_failed', __('Failed to write out the decrypted database to the filesystem','updraftplus'));
|
68 |
+
}
|
69 |
+
} else {
|
70 |
+
return new WP_Error('decryption_failed', __('Decryption failed. The most likely cause is that you used the wrong key.','updraftplus'));
|
71 |
+
}
|
72 |
+
} else {
|
73 |
+
$wp_filesystem->copy($package, $working_dir.'/backup.db.gz');
|
74 |
+
}
|
75 |
+
|
76 |
+
// Once extracted, delete the package if required.
|
77 |
+
if ( $delete_package )
|
78 |
+
unlink($package);
|
79 |
+
|
80 |
+
return $working_dir;
|
81 |
+
|
82 |
+
}
|
83 |
+
|
84 |
+
// For moving files out of a directory into their new location
|
85 |
+
// The only purpose of the $type parameter is to detect 'others' and apply a historical bugfix
|
86 |
+
// Must use only wp_filesystem
|
87 |
+
// $dest_dir must already have a trailing slash
|
88 |
+
function move_backup_in($working_dir, $dest_dir, $make_backup = true, $do_not_overwrite = array('plugins', 'themes', 'uploads', 'upgrade'), $type = 'not-others') {
|
89 |
+
|
90 |
+
global $wp_filesystem;
|
91 |
+
|
92 |
+
$upgrade_files = $wp_filesystem->dirlist($working_dir);
|
93 |
+
|
94 |
+
if ( !empty($upgrade_files) ) {
|
95 |
+
foreach ( $upgrade_files as $filestruc ) {
|
96 |
+
$file = $filestruc['name'];
|
97 |
+
|
98 |
+
// Correctly restore files in 'others' in no directory that were wrongly backed up in versions 1.4.0 - 1.4.48
|
99 |
+
if ('others' == $type && preg_match('/^([\-_A-Za-z0-9]+\.php)$/', $file, $matches) && $wp_filesystem->exists($working_dir . "/$file/$file")) {
|
100 |
+
echo "Found file: $file/$file: presuming this is a backup with a known fault (backup made with versions 1.4.0 - 1.4.48); will rename to simply $file<br>";
|
101 |
+
$file = $matches[1];
|
102 |
+
$tmp_file = rand(0,999999999).'.php';
|
103 |
+
// Rename directory
|
104 |
+
$wp_filesystem->move($working_dir . "/$file", $working_dir . "/".$tmp_file, true);
|
105 |
+
$wp_filesystem->move($working_dir . "/$tmp_file/$file", $working_dir ."/".$file, true);
|
106 |
+
$wp_filesystem->rmdir($working_dir . "/$tmp_file", false);
|
107 |
+
}
|
108 |
+
|
109 |
+
# Sanity check (should not be possible as these were excluded at backup time)
|
110 |
+
if (!in_array($file, $do_not_overwrite)) {
|
111 |
+
# First, move the existing one, if necessary (may not be present)
|
112 |
+
if ($wp_filesystem->exists($dest_dir.$file)) {
|
113 |
+
if ($make_backup) {
|
114 |
+
if ( !$wp_filesystem->move($dest_dir.$file, $dest_dir.$file.'-old', true) ) {
|
115 |
+
return new WP_Error('old_move_failed', $this->strings['old_move_failed']." (wp-content/$file)");
|
116 |
+
}
|
117 |
+
} else {
|
118 |
+
if (!$wp_filesystem->delete($dest_dir.$file, true)) {
|
119 |
+
return new WP_Error('old_delete_failed', $this->strings['old_delete_failed']." ($file)");
|
120 |
+
}
|
121 |
+
// if ( !$wp_filesystem->move($dest_dir.$file, $working_dir.'/'.$file.'-old', true) ) {
|
122 |
+
// return new WP_Error('old_move_failed', $this->strings['old_move_failed']." (wp-content/$file)");
|
123 |
+
// }
|
124 |
+
}
|
125 |
+
}
|
126 |
+
# Now, move in the new one
|
127 |
+
if ( !$wp_filesystem->move($working_dir . "/".$file, $dest_dir.$file, true) ) {
|
128 |
+
return new WP_Error('new_move_failed', $this->strings['new_move_failed']);
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
return true;
|
135 |
+
|
136 |
+
}
|
137 |
+
|
138 |
function restore_backup($backup_file, $type, $service, $info) {
|
139 |
|
140 |
global $wp_filesystem;
|
148 |
|
149 |
$wp_dir = trailingslashit($wp_filesystem->abspath());
|
150 |
|
151 |
+
@set_time_limit(1800);
|
152 |
+
|
153 |
+
$download = $this->download_package($backup_file);
|
154 |
+
if ( is_wp_error($download) ) return $download;
|
155 |
|
156 |
$delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
|
157 |
if ('none' == $service) {
|
161 |
|
162 |
$working_dir = $this->unpack_package($download, $delete);
|
163 |
if (is_wp_error($working_dir)) return $working_dir;
|
164 |
+
|
165 |
+
@set_time_limit(1800);
|
166 |
+
|
167 |
if ($type == 'others' ) {
|
168 |
|
169 |
// In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find
|
170 |
|
171 |
+
$this->move_backup_in($working_dir, $wp_dir."wp-content/", true, array('plugins', 'themes', 'uploads', 'upgrade'), 'others');
|
172 |
+
|
173 |
+
} elseif ('db' == $type) {
|
174 |
+
|
175 |
+
// There is a file backup.db.gz inside the working directory
|
176 |
+
|
177 |
+
# The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
|
178 |
+
if(@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
|
179 |
+
echo "<p>".__('Warning: PHP safe_mode is active on your server. Timeouts are much more likely. If these happen, then you will need to manually restore the file via phpMyAdmin or another method.', 'updraftplus')."</p><br/>";
|
180 |
+
return false;
|
181 |
+
}
|
182 |
+
|
183 |
+
|
184 |
+
global $wpdb;
|
185 |
+
|
186 |
+
if (!is_readable($working_dir.'/backup.db.gz')) return new WP_Error('gzopen_failed',__('Failed to find database file','updraftplus'));
|
187 |
+
|
188 |
+
$this->skin->feedback('restore_database');
|
189 |
+
|
190 |
+
// Read-only access: don't need to go through WP_Filesystem
|
191 |
+
$dbhandle = gzopen($working_dir.'/backup.db.gz', 'r');
|
192 |
+
if (!$dbhandle) return new WP_Error('gzopen_failed',__('Failed to open database file','updraftplus'));
|
193 |
+
|
194 |
+
$line = 0;
|
195 |
+
|
196 |
+
// Line up a wpdb-like object to use
|
197 |
+
// mysql_query will throw E_DEPRECATED from PHP 5.5, so we expect WordPress to have switched to something else by then
|
198 |
+
$use_wpdb = (version_compare(phpversion(), '5.5', '>=') || !function_exists('mysql_query') || !$wpdb->is_mysql || !$wpdb->ready) ? true : false;
|
199 |
+
|
200 |
+
if (false == $use_wpdb) {
|
201 |
+
// We have our own extension which drops lots of the overhead on the query
|
202 |
+
$wpdb_obj = new UpdraftPlus_WPDB( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
|
203 |
+
// Was that successful?
|
204 |
+
if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
|
205 |
+
$use_wpdb = true;
|
206 |
+
} else {
|
207 |
+
$mysql_dbh = $wpdb_obj->updraftplus_getdbh();
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
if (true == $use_wpdb) {
|
212 |
+
_e('Database access: Direct MySQL access is not available, so we are falling back to wpdb (this will be considerably slower)','updraftplus');
|
213 |
+
} else {
|
214 |
+
@mysql_query( 'SET SESSION query_cache_type = OFF;', $mysql_dbh );
|
215 |
+
}
|
216 |
+
|
217 |
+
$errors = 0;
|
218 |
+
|
219 |
+
$sql_line = "";
|
220 |
+
|
221 |
+
$start_time = microtime(true);
|
222 |
+
|
223 |
+
while (!gzeof($dbhandle)) {
|
224 |
+
// Up to 1Mb
|
225 |
+
$buffer = rtrim(gzgets($dbhandle, 1048576));
|
226 |
+
// Discard comments
|
227 |
+
if (substr($buffer, 0, 1) == '#' || empty($buffer)) continue;
|
228 |
+
|
229 |
+
$sql_line .= $buffer;
|
230 |
+
|
231 |
+
# Do we have a complete line yet?
|
232 |
+
if (';' != substr($sql_line, -1, 1)) continue;
|
233 |
+
|
234 |
+
$line++;
|
235 |
+
|
236 |
+
# The timed overhead of this is negligible
|
237 |
+
if (preg_match('/^\s*create table \`?([^\`]*)`?\s+\(/i', $sql_line, $matches)) {
|
238 |
+
echo __('Restoring table','updraftplus').": ".htmlspecialchars($matches[1])."<br>";
|
239 |
+
}
|
240 |
+
|
241 |
+
if ($use_wpdb) {
|
242 |
+
$req = $wpdb->query($sql_line);
|
243 |
+
if (!$req) $last_error = $wpdb->last_error;
|
244 |
+
} else {
|
245 |
+
$req = mysql_unbuffered_query( $sql_line, $mysql_dbh );
|
246 |
+
if (!$req) $last_error = mysql_error($mysql_dbh);
|
247 |
+
}
|
248 |
+
|
249 |
+
if (!$req) {
|
250 |
+
echo sprintf(_x('An error (%s) occured:', 'The user is being told the number of times an error has happened, e.g. An error (27) occurred', 'updraftplus'), $errors).' '.$wpdb_obj->last_error.' - '.__('the database query being run was: ','updraftplus').' '.htmlspecialchars($sql_line).'<br>';
|
251 |
+
$errors++;
|
252 |
+
if ($errors>49) {
|
253 |
+
return new WP_Error('too_many_db_errors', __('Too many database errors have occurred - aborting restoration (you will need to restore manually)','updraftplus'));
|
254 |
}
|
255 |
+
}
|
256 |
+
|
257 |
+
if ($line%50 == 0) {
|
258 |
+
if ($line%250 == 0 || $line<250) {
|
259 |
+
$time_taken = microtime(true) - $start_time;
|
260 |
+
echo sprintf(__('Database lines processed: %d in %.2f seconds','updraftplus'),$line, $time_taken)."<br>";
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
}
|
262 |
}
|
263 |
+
|
264 |
+
# Reset
|
265 |
+
$sql_line = '';
|
266 |
+
|
267 |
}
|
268 |
+
$time_taken = microtime(true) - $start_time;
|
269 |
+
echo sprintf(__('Finished: lines processed: %d in %.2f seconds','updraftplus'),$line, $time_taken)."<br>";
|
270 |
+
gzclose($dbhandle);
|
271 |
+
@unlink($working_dir.'/backup.db.gz');
|
272 |
|
273 |
} else {
|
274 |
+
|
275 |
show_message($this->strings['moving_old']);
|
|
|
|
|
|
|
276 |
|
277 |
+
$movedin = apply_filters('updraftplus_restore_movein_'.$type, $working_dir, $wp_dir);
|
278 |
+
// A filter, to allow add-ons to perform the install of non-standard entities, or to indicate that it's not possible
|
279 |
+
if ($movedin === false) {
|
280 |
+
show_message($this->strings['not_possible']);
|
281 |
+
} elseif ($movedin !== true) {
|
282 |
+
if ( !$wp_filesystem->move($wp_dir . "wp-content/$dirname", $wp_dir . "wp-content/$dirname-old", true) ) {
|
283 |
+
return new WP_Error('old_move_failed', $this->strings['old_move_failed']);
|
284 |
+
}
|
285 |
+
|
286 |
+
show_message($this->strings['moving_backup']);
|
287 |
+
if ( !$wp_filesystem->move($working_dir . "/$dirname", $wp_dir . "wp-content/$dirname", true) ) {
|
288 |
+
return new WP_Error('new_move_failed', $this->strings['new_move_failed']);
|
289 |
+
}
|
290 |
}
|
|
|
291 |
}
|
292 |
|
293 |
+
// Non-recursive, so the directory needs to be empty
|
294 |
show_message($this->strings['cleaning_up']);
|
295 |
+
if (!$wp_filesystem->delete($working_dir) ) {
|
296 |
+
return new WP_Error('delete_failed', $this->strings['delete_failed'].' ('.$working_dir.')');
|
297 |
}
|
298 |
|
299 |
switch($type) {
|
300 |
+
case 'wpcore':
|
301 |
+
@$wp_filesystem->chmod($wp_dir, FS_CHMOD_DIR);
|
302 |
+
break;
|
303 |
case 'uploads':
|
304 |
@$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", 0775, true);
|
305 |
break;
|
306 |
+
case 'db':
|
307 |
+
break;
|
308 |
default:
|
309 |
@$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", FS_CHMOD_DIR);
|
310 |
}
|
311 |
}
|
312 |
|
313 |
+
}
|
314 |
+
|
315 |
+
// Get a protected property
|
316 |
+
class UpdraftPlus_WPDB extends wpdb {
|
317 |
+
|
318 |
+
function updraftplus_getdbh() {
|
319 |
+
return $this->dbh;
|
320 |
+
}
|
321 |
+
|
322 |
}
|
323 |
?>
|
languages/updraftplus-de_DE.po
CHANGED
@@ -453,8 +453,7 @@ msgid ""
|
|
453 |
"<em>will</em> be useless.</strong> Presently, only the database file is "
|
454 |
"encrypted. This is also the key used to decrypt backups from this admin "
|
455 |
"interface (so if you change it, then automatic decryption will not work "
|
456 |
-
"until you change it back).
|
457 |
-
"from inside the UpdraftPlus plugin directory to decrypt manually."
|
458 |
msgstr ""
|
459 |
"Wenn du einen Text hier eingibst, wird dieser benutzt um die Sicherungen zu "
|
460 |
"verschlüsseln (Rijndael). <strong>Sichere diesen Text an einer sicheren "
|
@@ -462,9 +461,7 @@ msgstr ""
|
|
462 |
"<em>nutzlos</em> wenn du den Text vergisst.</strong> Aktuell wird nur die "
|
463 |
"Datenbank-Datei verschlüsselt. Der Text dient außerdem zur Entschlüsselung "
|
464 |
"der Sicherungen aus dieser Oberfläche (daher funktioniert Entschlüsselung "
|
465 |
-
"älterer Sicherungen nicht, wenn du diesen änderst).
|
466 |
-
"Beispiel example-decrypt.php aus dem UpdraftPlus Plugin-Verzeichnis "
|
467 |
-
"verwenden, um manuell zu entschlüsseln."
|
468 |
|
469 |
#: updraftplus.php:2403
|
470 |
msgid "Copying Your Backup To Remote Storage"
|
@@ -1837,7 +1834,7 @@ msgid "SFTP user setting"
|
|
1837 |
msgstr "SFTP-Benutzereinstellungen"
|
1838 |
|
1839 |
#: addons/sftp.php:32
|
1840 |
-
msgid "SFTP
|
1841 |
msgstr "SFTP-Passwort"
|
1842 |
|
1843 |
#: addons/sftp.php:50 addons/sftp.php:293
|
453 |
"<em>will</em> be useless.</strong> Presently, only the database file is "
|
454 |
"encrypted. This is also the key used to decrypt backups from this admin "
|
455 |
"interface (so if you change it, then automatic decryption will not work "
|
456 |
+
"until you change it back)."
|
|
|
457 |
msgstr ""
|
458 |
"Wenn du einen Text hier eingibst, wird dieser benutzt um die Sicherungen zu "
|
459 |
"verschlüsseln (Rijndael). <strong>Sichere diesen Text an einer sicheren "
|
461 |
"<em>nutzlos</em> wenn du den Text vergisst.</strong> Aktuell wird nur die "
|
462 |
"Datenbank-Datei verschlüsselt. Der Text dient außerdem zur Entschlüsselung "
|
463 |
"der Sicherungen aus dieser Oberfläche (daher funktioniert Entschlüsselung "
|
464 |
+
"älterer Sicherungen nicht, wenn du diesen änderst)."
|
|
|
|
|
465 |
|
466 |
#: updraftplus.php:2403
|
467 |
msgid "Copying Your Backup To Remote Storage"
|
1834 |
msgstr "SFTP-Benutzereinstellungen"
|
1835 |
|
1836 |
#: addons/sftp.php:32
|
1837 |
+
msgid "SFTP password"
|
1838 |
msgstr "SFTP-Passwort"
|
1839 |
|
1840 |
#: addons/sftp.php:50 addons/sftp.php:293
|
languages/updraftplus-es_ES.mo
ADDED
Binary file
|
languages/updraftplus-es_ES.po
ADDED
@@ -0,0 +1,1914 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
msgid ""
|
2 |
+
msgstr ""
|
3 |
+
"Project-Id-Version: UpdraftPlus\n"
|
4 |
+
"Report-Msgid-Bugs-To: \n"
|
5 |
+
"POT-Creation-Date: 2013-03-30 17:26+0100\n"
|
6 |
+
"PO-Revision-Date: 2013-04-11 16:51-0430\n"
|
7 |
+
"Last-Translator: Fernando Villasmil <villasmil.fernando@gmail.com>\n"
|
8 |
+
"Language-Team: <contact@updraftplus.com>\n"
|
9 |
+
"MIME-Version: 1.0\n"
|
10 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
11 |
+
"Content-Transfer-Encoding: 8bit\n"
|
12 |
+
"X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_x;_e\n"
|
13 |
+
"X-Poedit-Basepath: /home/david/MissionaryHosting/UpdraftPlus/svn/trunk\n"
|
14 |
+
"X-Generator: Poedit 1.5.5\n"
|
15 |
+
"Language: Spanish\n"
|
16 |
+
"X-Poedit-SearchPath-0: .\n"
|
17 |
+
|
18 |
+
#: options.php:26
|
19 |
+
msgid "UpdraftPlus Backups"
|
20 |
+
msgstr "Respaldo UpdraftPlus"
|
21 |
+
|
22 |
+
#: updraftplus.php:261
|
23 |
+
msgid ""
|
24 |
+
"Bad filename format - this does not look like a file created by UpdraftPlus"
|
25 |
+
msgstr "Formato de archivo errado - Esté no parece ser creado por UpdraftPlus"
|
26 |
+
|
27 |
+
#: updraftplus.php:295
|
28 |
+
msgid "Allowed Files"
|
29 |
+
msgstr "Archivos Permitidos"
|
30 |
+
|
31 |
+
#: updraftplus.php:372
|
32 |
+
msgid "Settings"
|
33 |
+
msgstr "Configuración"
|
34 |
+
|
35 |
+
#: updraftplus.php:376
|
36 |
+
msgid "Add-Ons / Pro Support"
|
37 |
+
msgstr "Adiciones / Pro Support"
|
38 |
+
|
39 |
+
#: updraftplus.php:462
|
40 |
+
msgid "Plugins"
|
41 |
+
msgstr "Plugins"
|
42 |
+
|
43 |
+
#: updraftplus.php:463
|
44 |
+
msgid "Themes"
|
45 |
+
msgstr "Temas"
|
46 |
+
|
47 |
+
#: updraftplus.php:464
|
48 |
+
msgid "Uploads"
|
49 |
+
msgstr "Uploads (subidos)"
|
50 |
+
|
51 |
+
#: updraftplus.php:478
|
52 |
+
msgid "Others"
|
53 |
+
msgstr "Otros"
|
54 |
+
|
55 |
+
#: updraftplus.php:710
|
56 |
+
msgid ""
|
57 |
+
"Could not create files in the backup directory. Backup aborted - check your "
|
58 |
+
"UpdraftPlus settings."
|
59 |
+
msgstr ""
|
60 |
+
"No se pudo crear los archivos al directorio de respaldo - Respaldo abortado "
|
61 |
+
"- Chequee la configuración"
|
62 |
+
|
63 |
+
#: updraftplus.php:778
|
64 |
+
msgid "Encryption error occurred when encrypting database. Encryption aborted."
|
65 |
+
msgstr ""
|
66 |
+
"Un error ocurrió mientras se cifraba la base de datos. El cifrado fue "
|
67 |
+
"abortado."
|
68 |
+
|
69 |
+
#: updraftplus.php:812
|
70 |
+
msgid "The backup apparently succeeded and is now complete"
|
71 |
+
msgstr "El respaldo aparentemente se logró y fue completado"
|
72 |
+
|
73 |
+
#: updraftplus.php:815
|
74 |
+
msgid "The backup attempt has finished, apparently unsuccessfully"
|
75 |
+
msgstr "El proceso del respaldo termino, aparentemente sin éxito"
|
76 |
+
|
77 |
+
#: updraftplus.php:818
|
78 |
+
msgid "The backup has not finished; a resumption is scheduled within 5 minutes"
|
79 |
+
msgstr ""
|
80 |
+
"El respaldo no ha terminado; se reiniciará dentro de los próximos 5 minutos"
|
81 |
+
|
82 |
+
#: updraftplus.php:869
|
83 |
+
msgid "Backed up"
|
84 |
+
msgstr "Respaldado"
|
85 |
+
|
86 |
+
#: updraftplus.php:869
|
87 |
+
msgid "WordPress backup is complete"
|
88 |
+
msgstr "El respaldo de WordPress está completo"
|
89 |
+
|
90 |
+
#: updraftplus.php:869
|
91 |
+
msgid "Backup contains"
|
92 |
+
msgstr "El respaldo contiene"
|
93 |
+
|
94 |
+
#: updraftplus.php:869
|
95 |
+
msgid "Latest status"
|
96 |
+
msgstr "Ultimo estatus"
|
97 |
+
|
98 |
+
#: updraftplus.php:1124
|
99 |
+
#, php-format
|
100 |
+
msgid "Could not create %s zip. Consult the log file for more information."
|
101 |
+
msgstr ""
|
102 |
+
"No se pudo crear el %s zip. Consulte el archivo log para más información."
|
103 |
+
|
104 |
+
#: updraftplus.php:1158
|
105 |
+
#, php-format
|
106 |
+
msgid "Backup directory (%s) is not writable, or does not exist."
|
107 |
+
msgstr "En el directorio de respaldo %s no se puede escribir o no existe "
|
108 |
+
|
109 |
+
#: updraftplus.php:1248
|
110 |
+
msgid "Could not read the content directory"
|
111 |
+
msgstr "No se pudo leer el directorio de contenido"
|
112 |
+
|
113 |
+
#: updraftplus.php:1278
|
114 |
+
msgid ""
|
115 |
+
"Could not save backup history because we have no backup array. Backup "
|
116 |
+
"probably failed."
|
117 |
+
msgstr ""
|
118 |
+
"No se pudo guardar la historia del respaldo. El respaldo probablemente "
|
119 |
+
"fracaso"
|
120 |
+
|
121 |
+
#: updraftplus.php:1307
|
122 |
+
msgid "Could not open the backup file for writing"
|
123 |
+
msgstr "No se pudo abrir el archivo del respaldo para escribirle "
|
124 |
+
|
125 |
+
#: updraftplus.php:1316
|
126 |
+
#, php-format
|
127 |
+
msgid "Generated: %s"
|
128 |
+
msgstr "Generado: %s"
|
129 |
+
|
130 |
+
#: updraftplus.php:1317
|
131 |
+
#, php-format
|
132 |
+
msgid "Hostname: %s"
|
133 |
+
msgstr "Servidor: %s"
|
134 |
+
|
135 |
+
#: updraftplus.php:1318
|
136 |
+
#, php-format
|
137 |
+
msgid "Database: %s"
|
138 |
+
msgstr "Base de Datos: %s"
|
139 |
+
|
140 |
+
#: updraftplus.php:1362
|
141 |
+
msgid "The backup directory is not writable."
|
142 |
+
msgstr "El directorio de respaldo no esta disponible"
|
143 |
+
|
144 |
+
#: updraftplus.php:1383
|
145 |
+
#, php-format
|
146 |
+
msgid "Table: %s"
|
147 |
+
msgstr "Tabla %s"
|
148 |
+
|
149 |
+
#: updraftplus.php:1388
|
150 |
+
#, php-format
|
151 |
+
msgid "Skipping non-WP table: %s"
|
152 |
+
msgstr "Saltando tablas no-WP %s"
|
153 |
+
|
154 |
+
#: updraftplus.php:1479
|
155 |
+
#, php-format
|
156 |
+
msgid "Delete any existing table %s"
|
157 |
+
msgstr "Borrando todas las tablas existentes %s"
|
158 |
+
|
159 |
+
#: updraftplus.php:1488
|
160 |
+
#, php-format
|
161 |
+
msgid "Table structure of table %s"
|
162 |
+
msgstr "Estructura de tablas de tabla %s"
|
163 |
+
|
164 |
+
#: updraftplus.php:1494
|
165 |
+
#, php-format
|
166 |
+
msgid "Error with SHOW CREATE TABLE for %s."
|
167 |
+
msgstr "Error en MOSTRAR TABLA CREADA de %s"
|
168 |
+
|
169 |
+
#: updraftplus.php:1501
|
170 |
+
#, php-format
|
171 |
+
msgid "Error getting table structure of %s"
|
172 |
+
msgstr "Error obteniendo estructura de tabla %s"
|
173 |
+
|
174 |
+
#: updraftplus.php:1507
|
175 |
+
#, php-format
|
176 |
+
msgid "Data contents of table %s"
|
177 |
+
msgstr "Contenido de data de la tabla %s"
|
178 |
+
|
179 |
+
#: updraftplus.php:1563
|
180 |
+
#, php-format
|
181 |
+
msgid "End of data contents of table %s"
|
182 |
+
msgstr "Final de contenido de data de la tabla %s"
|
183 |
+
|
184 |
+
#: updraftplus.php:1815
|
185 |
+
msgid "Nothing yet logged"
|
186 |
+
msgstr "No ha iniciado ninguna sesión todavía"
|
187 |
+
|
188 |
+
#: updraftplus.php:1836
|
189 |
+
msgid "File downloading"
|
190 |
+
msgstr "Bajando archivo "
|
191 |
+
|
192 |
+
#: updraftplus.php:1838
|
193 |
+
msgid "No local copy present."
|
194 |
+
msgstr "No hay copia local presente."
|
195 |
+
|
196 |
+
#: updraftplus.php:2014
|
197 |
+
msgid "File not found"
|
198 |
+
msgstr "Archivo no encontrado"
|
199 |
+
|
200 |
+
#: updraftplus.php:2033
|
201 |
+
#, php-format
|
202 |
+
msgid ""
|
203 |
+
"The backup archive for restoring this file could not be found. The remote "
|
204 |
+
"storage method in use (%s) does not allow us to retrieve files. To proceed "
|
205 |
+
"with this restoration, you need to obtain a copy of this file and place it "
|
206 |
+
"inside UpdraftPlus's working folder"
|
207 |
+
msgstr ""
|
208 |
+
"El sitio de almacenaje de respaldo para restaurar este archivo no se puede "
|
209 |
+
"encontrar. El sistema remoto de almacenaje en uso (%s) no nos permite "
|
210 |
+
"retirar archivos. Para continuar restauración, necesita obtener una copia de "
|
211 |
+
"este archivo y ponerlo dentro de la carpeta de respaldo de UpdraftPlus"
|
212 |
+
|
213 |
+
#: updraftplus.php:2043
|
214 |
+
msgid ""
|
215 |
+
"This backup does not exist in the backup history - restoration aborted. "
|
216 |
+
"Timestamp:"
|
217 |
+
msgstr ""
|
218 |
+
"Este respaldo no existe en la historia de respaldos - restauración abortada. "
|
219 |
+
"Fecha y hora:"
|
220 |
+
|
221 |
+
#: updraftplus.php:2056
|
222 |
+
msgid "UpdraftPlus Restoration: Progress"
|
223 |
+
msgstr "Restauración de UpdraftPlus: Progreso"
|
224 |
+
|
225 |
+
#: updraftplus.php:2063
|
226 |
+
msgid "ABORT: Could not find the information on which entities to restore."
|
227 |
+
msgstr ""
|
228 |
+
"ABORTADO: No se puede conseguir la información a que entidades debe ser "
|
229 |
+
"restaurado."
|
230 |
+
|
231 |
+
#: updraftplus.php:2077 updraftplus.php:2820 updraftplus.php:3072
|
232 |
+
msgid "Database"
|
233 |
+
msgstr "Base de datos"
|
234 |
+
|
235 |
+
#: updraftplus.php:2083
|
236 |
+
msgid "This component was not selected for restoration - skipping."
|
237 |
+
msgstr "Este componente no fue seleccionado para restaurar - saltando."
|
238 |
+
|
239 |
+
#: updraftplus.php:2091
|
240 |
+
msgid ""
|
241 |
+
"File is not locally present - needs retrieving from remote storage (for "
|
242 |
+
"large files, it is better to do this in advance from the download console)"
|
243 |
+
msgstr ""
|
244 |
+
"Este archivo no está localmente presente - necesita obtenerlo de un "
|
245 |
+
"almacenaje externo (para archivos grandes, es mejor hacerlo en la consola de "
|
246 |
+
"modo avanzado)"
|
247 |
+
|
248 |
+
#: updraftplus.php:2097
|
249 |
+
msgid "Archive is expected to be size:"
|
250 |
+
msgstr "Tamaño esperado del archivo:"
|
251 |
+
|
252 |
+
#: updraftplus.php:2102
|
253 |
+
msgid "ERROR"
|
254 |
+
msgstr "ERROR"
|
255 |
+
|
256 |
+
#: updraftplus.php:2105
|
257 |
+
msgid ""
|
258 |
+
"The backup records do not contain information about the proper size of this "
|
259 |
+
"file."
|
260 |
+
msgstr ""
|
261 |
+
"El datos del respaldo no contiene información del tamaño adecuado de este "
|
262 |
+
"archivo."
|
263 |
+
|
264 |
+
#: updraftplus.php:2117
|
265 |
+
msgid "Error message"
|
266 |
+
msgstr "Mensaje de ERROR"
|
267 |
+
|
268 |
+
#: updraftplus.php:2123 updraftplus.php:2124
|
269 |
+
msgid "Could not find one of the files for restoration"
|
270 |
+
msgstr "No se pudo encontrar uno de los archivos a restaurar"
|
271 |
+
|
272 |
+
#: updraftplus.php:2126
|
273 |
+
msgid ""
|
274 |
+
"Databases are not yet restored through this mechanism - use your web host's "
|
275 |
+
"control panel, phpMyAdmin or a similar tool"
|
276 |
+
msgstr ""
|
277 |
+
"Base de datos no fue restaurado por este mecanismo - use el panel de control "
|
278 |
+
"del proveedor de hospedaje, phpMyAdmin o herramienta similar"
|
279 |
+
|
280 |
+
#: updraftplus.php:2132
|
281 |
+
msgid ""
|
282 |
+
"Database could not be restored because PHP safe_mode is active on your "
|
283 |
+
"server. You will need to manually restore the file via phpMyAdmin or "
|
284 |
+
"another method."
|
285 |
+
msgstr ""
|
286 |
+
"Base de datos no fue restaurada porque su servidor tiene activo el safe_mode "
|
287 |
+
"(modo seguro) del PHP. Necesita restaurar el archivo manualmente vía "
|
288 |
+
"phpMyAdmin u otro método."
|
289 |
+
|
290 |
+
#: updraftplus.php:2156
|
291 |
+
msgid "Delete"
|
292 |
+
msgstr "Borrar"
|
293 |
+
|
294 |
+
#: updraftplus.php:2290
|
295 |
+
msgid "Find UpdraftPlus useful?"
|
296 |
+
msgstr "A sido UpdraftPlus util?"
|
297 |
+
|
298 |
+
#: updraftplus.php:2290
|
299 |
+
msgid "Please make a donation"
|
300 |
+
msgstr "Haga una donación por favor\" "
|
301 |
+
|
302 |
+
#: updraftplus.php:2295
|
303 |
+
msgid "Like UpdraftPlus and can spare one minute?"
|
304 |
+
msgstr "Le gusta UpdraftPlus y nos puede dar un minuto?"
|
305 |
+
|
306 |
+
#: updraftplus.php:2295
|
307 |
+
msgid "Please help UpdraftPlus by giving a positive review at wordpress.org"
|
308 |
+
msgstr ""
|
309 |
+
"Por favor ayude a UpdraftPlus dando una reseña (review) positiva en "
|
310 |
+
"wordpress.org"
|
311 |
+
|
312 |
+
#: updraftplus.php:2302
|
313 |
+
msgid "Need even more features and support? Check out UpdraftPlus Premium"
|
314 |
+
msgstr ""
|
315 |
+
"Necesita todavía mas funciones y soporte? Lea sobre UpdraftPlus Premium"
|
316 |
+
|
317 |
+
#: updraftplus.php:2311
|
318 |
+
msgid "Check out UpdraftPlus.Com for help, add-ons and support"
|
319 |
+
msgstr "Consulte UpdraftPlus.Com para ayuda, adiciones y soporte"
|
320 |
+
|
321 |
+
#: updraftplus.php:2314
|
322 |
+
msgid "Want to say thank-you for UpdraftPlus?"
|
323 |
+
msgstr "Quisiera dar las gracias por UpdraftPlus?"
|
324 |
+
|
325 |
+
#: updraftplus.php:2314
|
326 |
+
msgid "Please buy our very cheap 'no adverts' add-on."
|
327 |
+
msgstr "Por favor compre nuestras adiciones de bajo costo sin anuncios"
|
328 |
+
|
329 |
+
#: updraftplus.php:2325
|
330 |
+
msgid "File backup intervals"
|
331 |
+
msgstr "Intervalos de archivos de respaldo"
|
332 |
+
|
333 |
+
#: updraftplus.php:2328
|
334 |
+
msgid "Manual"
|
335 |
+
msgstr "Manual"
|
336 |
+
|
337 |
+
#: updraftplus.php:2328
|
338 |
+
msgid "Every 4 hours"
|
339 |
+
msgstr "Cada 4 horas"
|
340 |
+
|
341 |
+
#: updraftplus.php:2328
|
342 |
+
msgid "Every 8 hours"
|
343 |
+
msgstr "Cada 8 horas"
|
344 |
+
|
345 |
+
#: updraftplus.php:2328
|
346 |
+
msgid "Every 12 hours"
|
347 |
+
msgstr "Cada 12 horas"
|
348 |
+
|
349 |
+
#: updraftplus.php:2328
|
350 |
+
msgid "Daily"
|
351 |
+
msgstr "Diario"
|
352 |
+
|
353 |
+
#: updraftplus.php:2328
|
354 |
+
msgid "Weekly"
|
355 |
+
msgstr "Semanal"
|
356 |
+
|
357 |
+
#: updraftplus.php:2328
|
358 |
+
msgid "Fortnightly"
|
359 |
+
msgstr "Quincenal"
|
360 |
+
|
361 |
+
#: updraftplus.php:2328
|
362 |
+
msgid "Monthly"
|
363 |
+
msgstr "Mensual"
|
364 |
+
|
365 |
+
#: updraftplus.php:2337 updraftplus.php:2355
|
366 |
+
msgid "and retain this many backups"
|
367 |
+
msgstr "Retener esta cantidad de respaldos"
|
368 |
+
|
369 |
+
#: updraftplus.php:2344
|
370 |
+
msgid "Database backup intervals"
|
371 |
+
msgstr "Intervalos de respaldos de la Base de datos"
|
372 |
+
|
373 |
+
#: updraftplus.php:2362
|
374 |
+
msgid ""
|
375 |
+
"If you would like to automatically schedule backups, choose schedules from "
|
376 |
+
"the dropdowns above. Backups will occur at the intervals specified. If the "
|
377 |
+
"two schedules are the same, then the two backups will take place together. "
|
378 |
+
"If you choose \"manual\" then you must click the \"Backup Now\" button "
|
379 |
+
"whenever you wish a backup to occur."
|
380 |
+
msgstr ""
|
381 |
+
"Si usted desea seleccionar respaldos automaticos, seleccionar horario desde "
|
382 |
+
"el menu anterior. Los respaldos se haran en los intervalos especificados. Si "
|
383 |
+
"los dos horarios son iguales, entonces los dos respaldos seran ejecutados al "
|
384 |
+
"mismo tiempo. Si usted selecciona \"manual\" usted debe seleccionar el boton "
|
385 |
+
"\"Respaldar Ahora\" cada vez que desee respaldar"
|
386 |
+
|
387 |
+
#: updraftplus.php:2363
|
388 |
+
msgid "To fix the time at which a backup should take place,"
|
389 |
+
msgstr "Para arreglar el horario cuando el respaldo deba iniciar"
|
390 |
+
|
391 |
+
#: updraftplus.php:2363
|
392 |
+
msgid "e.g. if your server is busy at day and you want to run overnight"
|
393 |
+
msgstr "ej. Si su servidor esta ocupado de dia y desea respaldar en la noche"
|
394 |
+
|
395 |
+
#: updraftplus.php:2363
|
396 |
+
msgid "use the \"Fix Time\" add-on"
|
397 |
+
msgstr "Usar la adicion \"Fix TIme\" (Arreglo de hora)"
|
398 |
+
|
399 |
+
#: updraftplus.php:2377
|
400 |
+
msgid ""
|
401 |
+
"Any other directories found inside wp-content but exclude these directories:"
|
402 |
+
msgstr ""
|
403 |
+
"Cualquier otro directorio encontrado dentro de wp-content pero excluye estos "
|
404 |
+
"directorios"
|
405 |
+
|
406 |
+
#: updraftplus.php:2383
|
407 |
+
msgid ""
|
408 |
+
"Include all of these, unless you are backing them up outside of UpdraftPlus. "
|
409 |
+
"The above directories are usually everything (except for WordPress core "
|
410 |
+
"itself which you can download afresh from WordPress.org). But if you have "
|
411 |
+
"made customised modifications outside of these directories, you need to back "
|
412 |
+
"them up another way."
|
413 |
+
msgstr ""
|
414 |
+
"Incluye todos estos, a menos que usted los esté respaldando fuera de "
|
415 |
+
"UpdraftPlus. Los directorios anteriores son usualmente todos los archivos "
|
416 |
+
"(excepto por el programa de WordPress mismo, que puede bajar desde Wordpress."
|
417 |
+
"org).Pero si usted ha hecho modificaciones fuera de estos directorios, "
|
418 |
+
"tendrá que respaldarlo de otro modo"
|
419 |
+
|
420 |
+
#: updraftplus.php:2383
|
421 |
+
msgid "Use WordShell for automatic backup, version control and patching"
|
422 |
+
msgstr "Use WordShell para respaldos automaticos, control de version y parches"
|
423 |
+
|
424 |
+
#: updraftplus.php:2387
|
425 |
+
msgid "Email"
|
426 |
+
msgstr "Email"
|
427 |
+
|
428 |
+
#: updraftplus.php:2388
|
429 |
+
msgid ""
|
430 |
+
"Enter an address here to have a report sent (and the whole backup, if you "
|
431 |
+
"choose) to it."
|
432 |
+
msgstr ""
|
433 |
+
"Entre una dirección aqui para enviar el reporte (y todo el respaldo, si lo "
|
434 |
+
"desea)"
|
435 |
+
|
436 |
+
#: updraftplus.php:2392
|
437 |
+
msgid "Database encryption phrase"
|
438 |
+
msgstr "Frase de cifrado-Base de Datos "
|
439 |
+
|
440 |
+
#: updraftplus.php:2399
|
441 |
+
msgid ""
|
442 |
+
"If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do "
|
443 |
+
"make a separate record of it and do not lose it, or all your backups "
|
444 |
+
"<em>will</em> be useless.</strong> Presently, only the database file is "
|
445 |
+
"encrypted. This is also the key used to decrypt backups from this admin "
|
446 |
+
"interface (so if you change it, then automatic decryption will not work "
|
447 |
+
"until you change it back). You can also use the file example-decrypt.php "
|
448 |
+
"from inside the UpdraftPlus plugin directory to decrypt manually."
|
449 |
+
msgstr ""
|
450 |
+
"Si usted entra texto aquí, es usado para cifrar el respaldo (Rijndael). "
|
451 |
+
"<strong>Haga una anotación aparte y guárdela, no la pierda porque su "
|
452 |
+
"respaldo <em>será</em> inutilizable.</strong> En la actualidad solo se "
|
453 |
+
"cifra el archivo de la base de datos. Esta es también la llave usada para "
|
454 |
+
"cifrar respaldos de la interface de admin (por eso si la cambia, entonces el "
|
455 |
+
"descifrado automático deja de funcionar hasta que la cambie a la anterior). "
|
456 |
+
"Usted también puede usar el archivo example-decrypt.php desde adentro de "
|
457 |
+
"UpdraftPlus en el directorio del plugin para descifrar manualmente"
|
458 |
+
|
459 |
+
#: updraftplus.php:2403
|
460 |
+
msgid "Copying Your Backup To Remote Storage"
|
461 |
+
msgstr "Copiando su respaldo a un almacenaje externo"
|
462 |
+
|
463 |
+
#: updraftplus.php:2407
|
464 |
+
msgid "Choose your remote storage"
|
465 |
+
msgstr "Seleccione su almacenaje externo"
|
466 |
+
|
467 |
+
#: updraftplus.php:2419
|
468 |
+
msgid "None"
|
469 |
+
msgstr "Ninguno"
|
470 |
+
|
471 |
+
#: updraftplus.php:2500 updraftplus.php:2838 updraftplus.php:3109
|
472 |
+
msgid "Restore"
|
473 |
+
msgstr "Restaurar"
|
474 |
+
|
475 |
+
#: updraftplus.php:2514 updraftplus.php:2524
|
476 |
+
msgid "Cancel"
|
477 |
+
msgstr "Cancelar"
|
478 |
+
|
479 |
+
#: updraftplus.php:2521 updraftplus.php:2830
|
480 |
+
msgid "Backup Now"
|
481 |
+
msgstr "Respaldar Ahora"
|
482 |
+
|
483 |
+
#: updraftplus.php:2548
|
484 |
+
msgid "Advanced / Debugging Settings"
|
485 |
+
msgstr "Avansado / Configuración depurar"
|
486 |
+
|
487 |
+
#: updraftplus.php:2551
|
488 |
+
msgid "Debug mode"
|
489 |
+
msgstr "Modo de depuración"
|
490 |
+
|
491 |
+
#: updraftplus.php:2552
|
492 |
+
msgid ""
|
493 |
+
"Check this to receive more information and emails on the backup process - "
|
494 |
+
"useful if something is going wrong. You <strong>must</strong> send us this "
|
495 |
+
"log if you are filing a bug report."
|
496 |
+
msgstr ""
|
497 |
+
"Haga clic para recibir más información y correos de los procesos de "
|
498 |
+
"respaldos - útil para saber si hubo algún error. Usted <strong>debe</"
|
499 |
+
"strong>enviar a nosotros este registro (log) para enviar un reporte de "
|
500 |
+
"errores"
|
501 |
+
|
502 |
+
#: updraftplus.php:2555
|
503 |
+
msgid "Expert settings"
|
504 |
+
msgstr "Configuración Expertos"
|
505 |
+
|
506 |
+
#: updraftplus.php:2556
|
507 |
+
msgid "Show expert settings"
|
508 |
+
msgstr "Abra configuración expertos"
|
509 |
+
|
510 |
+
#: updraftplus.php:2556
|
511 |
+
msgid ""
|
512 |
+
"click this to show some further options; don't bother with this unless you "
|
513 |
+
"have a problem or are curious."
|
514 |
+
msgstr ""
|
515 |
+
"haga clic aquí para mostrar otras opciones; no lo utilice a menos que tenga "
|
516 |
+
"un problema o es curioso"
|
517 |
+
|
518 |
+
#: updraftplus.php:2563
|
519 |
+
msgid "Delete local backup"
|
520 |
+
msgstr "Borre respaldos locales"
|
521 |
+
|
522 |
+
#: updraftplus.php:2564
|
523 |
+
msgid ""
|
524 |
+
"Uncheck this to prevent deletion of any superfluous backup files from your "
|
525 |
+
"server after the backup run finishes (i.e. any files despatched remotely "
|
526 |
+
"will also remain locally, and any files being kept locally will not be "
|
527 |
+
"subject to the retention limits)."
|
528 |
+
msgstr ""
|
529 |
+
"Deseleccione esto para prevenir que se borre algún archivo de respaldo en su "
|
530 |
+
"servidor luego que su respaldo termine (i.e. cualquier archivo despachado "
|
531 |
+
"remotamente también se quedara localmente, y cualquier archivo local no será "
|
532 |
+
"sujeto a límites de retención"
|
533 |
+
|
534 |
+
#: updraftplus.php:2568
|
535 |
+
msgid "Backup directory"
|
536 |
+
msgstr "Directorio de respaldo"
|
537 |
+
|
538 |
+
#: updraftplus.php:2576
|
539 |
+
msgid "Backup directory specified is writable, which is good."
|
540 |
+
msgstr "Directorio especificado de respaldo es grabable, esto es bueno."
|
541 |
+
|
542 |
+
#: updraftplus.php:2578
|
543 |
+
msgid "Backup directory specified is <b>not</b> writable, or does not exist."
|
544 |
+
msgstr ""
|
545 |
+
"El directorio especificado de respaldo <b>no</b> es grabable o no existe."
|
546 |
+
|
547 |
+
#: updraftplus.php:2578
|
548 |
+
msgid "Click here to attempt to create the directory and set the permissions"
|
549 |
+
msgstr "Haga clic aquí para tratar de crear el directorio y fijar los permisos"
|
550 |
+
|
551 |
+
#: updraftplus.php:2578
|
552 |
+
msgid "or, to reset this option"
|
553 |
+
msgstr "o para resetear la opción"
|
554 |
+
|
555 |
+
#: updraftplus.php:2578
|
556 |
+
msgid "click here"
|
557 |
+
msgstr "Clic aqui"
|
558 |
+
|
559 |
+
#: updraftplus.php:2578
|
560 |
+
msgid ""
|
561 |
+
"If that is unsuccessful check the permissions on your server or change it to "
|
562 |
+
"another directory that is writable by your web server process."
|
563 |
+
msgstr ""
|
564 |
+
"Si no lo logro verifique los permisos en su servidor o cambie a otro "
|
565 |
+
"directorio que sea grabable por su servidor de procesos del web"
|
566 |
+
|
567 |
+
#: updraftplus.php:2581
|
568 |
+
msgid ""
|
569 |
+
"This is where UpdraftPlus will write the zip files it creates initially. "
|
570 |
+
"This directory must be writable by your web server. Typically you'll want to "
|
571 |
+
"have it inside your wp-content folder (this is the default). <b>Do not</b> "
|
572 |
+
"place it inside your uploads dir, as that will cause recursion issues "
|
573 |
+
"(backups of backups of backups of...)."
|
574 |
+
msgstr ""
|
575 |
+
"Este es donde UpdraftPlus va a escribir el archivo zip que crea "
|
576 |
+
"inicialmente. Este directorio debe de ser grabable por su servidor del web. "
|
577 |
+
"Normalmente debe de estar situado dentro del directorio wp-content "
|
578 |
+
"(directorio por defecto) <b>NO</b> lo ponga dentro del directorio de "
|
579 |
+
"uploads, porque causara problemas (respaldos de respaldos de respaldos "
|
580 |
+
"de....."
|
581 |
+
|
582 |
+
#: updraftplus.php:2602
|
583 |
+
msgid "Save Changes"
|
584 |
+
msgstr "Guardar cambios"
|
585 |
+
|
586 |
+
#: updraftplus.php:2626
|
587 |
+
msgid "Download log file"
|
588 |
+
msgstr "Baje el archivo de registro (log)"
|
589 |
+
|
590 |
+
#: updraftplus.php:2632
|
591 |
+
msgid "No backup has been completed."
|
592 |
+
msgstr "Ningun respaldo fue completado."
|
593 |
+
|
594 |
+
#: updraftplus.php:2652
|
595 |
+
msgid "Restore successful!"
|
596 |
+
msgstr "Restauración exitosa"
|
597 |
+
|
598 |
+
#: updraftplus.php:2653 updraftplus.php:2688 updraftplus.php:2704
|
599 |
+
msgid "Actions"
|
600 |
+
msgstr "Acciones"
|
601 |
+
|
602 |
+
#: updraftplus.php:2653 updraftplus.php:2668 updraftplus.php:2688
|
603 |
+
#: updraftplus.php:2704
|
604 |
+
msgid "Return to UpdraftPlus Configuration"
|
605 |
+
msgstr "Volver a la configuración UpdraftPlus"
|
606 |
+
|
607 |
+
#: updraftplus.php:2677
|
608 |
+
msgid "Remove old directories"
|
609 |
+
msgstr "Remueva directorio viejo"
|
610 |
+
|
611 |
+
#: updraftplus.php:2683
|
612 |
+
msgid "Old directories successfully removed."
|
613 |
+
msgstr "Directorios viejos removidos exitosamente"
|
614 |
+
|
615 |
+
#: updraftplus.php:2686
|
616 |
+
msgid ""
|
617 |
+
"Old directory removal failed for some reason. You may want to do this "
|
618 |
+
"manually."
|
619 |
+
msgstr ""
|
620 |
+
"Directorios viejos no pudieron ser removidos. Si desea lo puede hacer "
|
621 |
+
"manualmente"
|
622 |
+
|
623 |
+
#: updraftplus.php:2701
|
624 |
+
msgid "Backup directory could not be created"
|
625 |
+
msgstr "Directorio de respaldo no se pudo crear"
|
626 |
+
|
627 |
+
#: updraftplus.php:2703
|
628 |
+
msgid "Backup directory successfully created."
|
629 |
+
msgstr "Directorio de respaldo fue creado exitosamente"
|
630 |
+
|
631 |
+
#: updraftplus.php:2710
|
632 |
+
msgid "Schedule backup"
|
633 |
+
msgstr "Horario de respaldos"
|
634 |
+
|
635 |
+
#: updraftplus.php:2713
|
636 |
+
msgid "Failed."
|
637 |
+
msgstr "Fallo"
|
638 |
+
|
639 |
+
#: updraftplus.php:2715
|
640 |
+
msgid ""
|
641 |
+
"OK. Now load any page from your site to make sure the schedule can trigger. "
|
642 |
+
"You should then see activity in the \"Last log message\" field below."
|
643 |
+
msgstr ""
|
644 |
+
"Ok ahora cargue cualquier página de su site para asegurarse que el horario "
|
645 |
+
"se inicie. Usted podrá ver la actividad en \"Ultimo mensaje del log\" el "
|
646 |
+
"campo abajo"
|
647 |
+
|
648 |
+
#: updraftplus.php:2715
|
649 |
+
msgid "Nothing happening? Follow this link for help."
|
650 |
+
msgstr "No sucede nada? Clic en este link para ayuda."
|
651 |
+
|
652 |
+
#: updraftplus.php:2728
|
653 |
+
msgid "Your settings have been wiped."
|
654 |
+
msgstr "Su configuración ha sido borrada"
|
655 |
+
|
656 |
+
#: updraftplus.php:2735
|
657 |
+
msgid "By UpdraftPlus.Com"
|
658 |
+
msgstr "Por UpdraftPlus.Com"
|
659 |
+
|
660 |
+
#: updraftplus.php:2735
|
661 |
+
msgid "Lead developer's homepage"
|
662 |
+
msgstr "Pagina del Desarrollador Principal"
|
663 |
+
|
664 |
+
#: updraftplus.php:2735
|
665 |
+
msgid "Donate"
|
666 |
+
msgstr "Donación"
|
667 |
+
|
668 |
+
#: updraftplus.php:2735
|
669 |
+
msgid "Other WordPress plugins"
|
670 |
+
msgstr "Otros plugins de WordPress"
|
671 |
+
|
672 |
+
#: updraftplus.php:2735
|
673 |
+
msgid "Version"
|
674 |
+
msgstr "Versión"
|
675 |
+
|
676 |
+
#: updraftplus.php:2739
|
677 |
+
msgid "Your backup has been restored."
|
678 |
+
msgstr "Su respaldo a sido restaurado"
|
679 |
+
|
680 |
+
#: updraftplus.php:2739
|
681 |
+
msgid ""
|
682 |
+
"Your old (themes, uploads, plugins, whatever) directories have been retained "
|
683 |
+
"with \"-old\" appended to their name. Remove them when you are satisfied "
|
684 |
+
"that the backup worked properly."
|
685 |
+
msgstr ""
|
686 |
+
"`Su directorio (temas, subidas de archivos, plugins, etc.) viejos han sido "
|
687 |
+
"retenidos con \"-old\"agregado a sus nombres. Removerlos una vez satisfecho "
|
688 |
+
"de que su respaldo se realizó sin problemas"
|
689 |
+
|
690 |
+
#: updraftplus.php:2739
|
691 |
+
msgid ""
|
692 |
+
"At this time UpdraftPlus does not automatically restore your database. You "
|
693 |
+
"will need to use an external tool like phpMyAdmin to perform that task."
|
694 |
+
msgstr ""
|
695 |
+
"En este momento UpdraftPlus no restaura su base de datos automáticamente. "
|
696 |
+
"Usted va a necesitar una herramienta externa como phpMyAdmin para esta tarea"
|
697 |
+
|
698 |
+
#: updraftplus.php:2745
|
699 |
+
msgid "Old directories successfully deleted."
|
700 |
+
msgstr "Directorios viejos fueron borrados con éxito"
|
701 |
+
|
702 |
+
#: updraftplus.php:2748
|
703 |
+
msgid ""
|
704 |
+
"Your PHP memory limit is quite low. UpdraftPlus attempted to raise it but "
|
705 |
+
"was unsuccessful. This plugin may not work properly with a memory limit of "
|
706 |
+
"less than 96 Mb (though on the other hand, it has been used successfully "
|
707 |
+
"with a 32Mb limit - your mileage may vary, but don't blame us!)."
|
708 |
+
msgstr ""
|
709 |
+
"Su limite de memoria PHP es muy baja. UpdraftPlus intento aumentarla sin "
|
710 |
+
"exito. Este plugin no trabajara correctamente con una memoria menor de 96 Mb "
|
711 |
+
"(por otra parte a habido veces que con un limite de 32 Mb a trabajado con "
|
712 |
+
"exito - su efectividad puede variar, no nos culpe!). "
|
713 |
+
|
714 |
+
#: updraftplus.php:2748
|
715 |
+
msgid "Current limit is:"
|
716 |
+
msgstr "Limite actual es:"
|
717 |
+
|
718 |
+
#: updraftplus.php:2752
|
719 |
+
msgid ""
|
720 |
+
"Your PHP max_execution_time is less than 60 seconds. This possibly means "
|
721 |
+
"you're running in safe_mode. Either disable safe_mode or modify your php.ini "
|
722 |
+
"to set max_execution_time to a higher number. If you do not, then longer "
|
723 |
+
"will be needed to complete a backup (but that is all). Present limit is:"
|
724 |
+
msgstr ""
|
725 |
+
"El PHP max_execution_time es menor de 60 segundos. Esto probablemente "
|
726 |
+
"significa que está corriendo en safe_mode (modo seguro). Deshabilite "
|
727 |
+
"safe_mode o modifique su php.ini y fije el max_execution_time a un número "
|
728 |
+
"mayor. Si no lo hace, completara el respaldo en un tiempo mayor. Límite "
|
729 |
+
"actual es de:"
|
730 |
+
|
731 |
+
#: updraftplus.php:2752
|
732 |
+
msgid "seconds"
|
733 |
+
msgstr "segundos"
|
734 |
+
|
735 |
+
#: updraftplus.php:2757
|
736 |
+
msgid ""
|
737 |
+
"You have old directories from a previous backup (technical information: "
|
738 |
+
"these are found in wp-content, and suffixed with -old). Use this button to "
|
739 |
+
"delete them (if you have verified that the restoration worked)."
|
740 |
+
msgstr ""
|
741 |
+
"Usted tiene directorios viejos de un respaldo anterior (información técnica: "
|
742 |
+
"estos se consiguen en wp-content y con la adición -old) Use este botón para "
|
743 |
+
"borrarlos (si usted previamente verifico que la restauración fue exitosa)."
|
744 |
+
|
745 |
+
#: updraftplus.php:2761
|
746 |
+
msgid "Delete Old Directories"
|
747 |
+
msgstr "Borre Directorios \"old\""
|
748 |
+
|
749 |
+
#: updraftplus.php:2761
|
750 |
+
msgid ""
|
751 |
+
"Are you sure you want to delete the old directories? This cannot be undone."
|
752 |
+
msgstr ""
|
753 |
+
"Está seguro que quiere borrar los directorios viejos (old)? Acción "
|
754 |
+
"irreversible."
|
755 |
+
|
756 |
+
#: updraftplus.php:2774
|
757 |
+
msgid "Existing Schedule And Backups"
|
758 |
+
msgstr "Horarios existentes de Respaldos"
|
759 |
+
|
760 |
+
#: updraftplus.php:2778
|
761 |
+
msgid "JavaScript warning"
|
762 |
+
msgstr "Advertencia de JavaScrip"
|
763 |
+
|
764 |
+
#: updraftplus.php:2779
|
765 |
+
msgid ""
|
766 |
+
"This admin interface uses JavaScript heavily. You either need to activate it "
|
767 |
+
"within your browser, or to use a JavaScript-capable browser."
|
768 |
+
msgstr ""
|
769 |
+
"Esta interface administrativa usa JavaScript frecuentemente. Usted necesita "
|
770 |
+
"activarlo en su navegador o utilice un navegador que contenga JavaScript"
|
771 |
+
|
772 |
+
#: updraftplus.php:2792 updraftplus.php:2805
|
773 |
+
msgid "Nothing currently scheduled"
|
774 |
+
msgstr "Nada programado actualmente"
|
775 |
+
|
776 |
+
#: updraftplus.php:2797
|
777 |
+
msgid "At the same time as the files backup"
|
778 |
+
msgstr "Al mismo tiempo que su archivo de respaldo"
|
779 |
+
|
780 |
+
#: updraftplus.php:2817
|
781 |
+
msgid "Next scheduled backups"
|
782 |
+
msgstr "Próximo horario de respaldos"
|
783 |
+
|
784 |
+
#: updraftplus.php:2819
|
785 |
+
msgid "Files"
|
786 |
+
msgstr "Archivos"
|
787 |
+
|
788 |
+
#: updraftplus.php:2821
|
789 |
+
msgid "Time now"
|
790 |
+
msgstr "Hora actual"
|
791 |
+
|
792 |
+
#: updraftplus.php:2825
|
793 |
+
msgid "Last finished backup run"
|
794 |
+
msgstr "Ultimo respaldo completado"
|
795 |
+
|
796 |
+
#: updraftplus.php:2845
|
797 |
+
msgid "Last log message"
|
798 |
+
msgstr "Ultimo mensaje del Log"
|
799 |
+
|
800 |
+
#: updraftplus.php:2846
|
801 |
+
msgid "(Nothing yet logged)"
|
802 |
+
msgstr "Aún sin registros"
|
803 |
+
|
804 |
+
#: updraftplus.php:2849
|
805 |
+
msgid "Backups, logs & restoring"
|
806 |
+
msgstr "Respaldos, registros & restauraciones"
|
807 |
+
|
808 |
+
#: updraftplus.php:2850
|
809 |
+
msgid "Press to see available backups"
|
810 |
+
msgstr "Apriete para ver respaldos disponibles"
|
811 |
+
|
812 |
+
#: updraftplus.php:2850
|
813 |
+
#, php-format
|
814 |
+
msgid "%d set(s) available"
|
815 |
+
msgstr "%d set(s) disponibles"
|
816 |
+
|
817 |
+
#: updraftplus.php:2855
|
818 |
+
msgid "Downloading"
|
819 |
+
msgstr "Bajando"
|
820 |
+
|
821 |
+
#: updraftplus.php:2855
|
822 |
+
msgid ""
|
823 |
+
"Pressing a button for Database/Plugins/Themes/Uploads/Others will make "
|
824 |
+
"UpdraftPlus try to bring the backup file back from the remote storage (if "
|
825 |
+
"any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then "
|
826 |
+
"you will be allowed to download it to your computer. If the fetch from the "
|
827 |
+
"remote storage stops progressing (wait 30 seconds to make sure), then press "
|
828 |
+
"again to resume. Remember that you can also visit the cloud storage vendor's "
|
829 |
+
"website directly."
|
830 |
+
msgstr ""
|
831 |
+
"Marcando algún botón como Base de Datos/Pluins/Temas/Subidas (uploads)/Otros "
|
832 |
+
"ara que UpdraftPlus trate de traer el archivo de respaldo desde el "
|
833 |
+
"almacenamiento externo (Amazon S3,Dropbox, Gooogle Drive, FTP) a su "
|
834 |
+
"servidor. En ese momento podrá bajarlo a su computadora. Si la traída desde "
|
835 |
+
"el almacenaje externo falla en el proceso (espere 30 segundo para estar "
|
836 |
+
"seguro), entonces apriete de nuevo para reiniciar. Recuerde que lo puede "
|
837 |
+
"bajar directamente desde el sitio de almacenaje directamente."
|
838 |
+
|
839 |
+
#: updraftplus.php:2856
|
840 |
+
msgid "Restoring"
|
841 |
+
msgstr "Restaurando"
|
842 |
+
|
843 |
+
#: updraftplus.php:2856
|
844 |
+
msgid ""
|
845 |
+
"Press the button for the backup you wish to restore. If your site is large "
|
846 |
+
"and you are using remote storage, then you should first click on each entity "
|
847 |
+
"in order to retrieve it back to the webserver. This will prevent time-outs "
|
848 |
+
"from occuring during the restore process itself."
|
849 |
+
msgstr ""
|
850 |
+
"Apriete el botón por el respaldo desea restaurar. Si su site es grande y "
|
851 |
+
"está escogiendo almacenamiento externo, entonces usted debe primero hacer "
|
852 |
+
"clic a cada entidad para que pueda traerlo otra vez a su servidor. Esto es "
|
853 |
+
"para prevenir problemas de tiempo durante el proceso mismo."
|
854 |
+
|
855 |
+
#: updraftplus.php:2856
|
856 |
+
msgid "More tasks:"
|
857 |
+
msgstr "Mas tareas:"
|
858 |
+
|
859 |
+
#: updraftplus.php:2856
|
860 |
+
msgid "upload backup files"
|
861 |
+
msgstr "Suba archivos de respaldo"
|
862 |
+
|
863 |
+
#: updraftplus.php:2856
|
864 |
+
msgid ""
|
865 |
+
"Press here to look inside your UpdraftPlus directory (in your web hosting "
|
866 |
+
"space) for any new backup sets that you have uploaded. The location of this "
|
867 |
+
"directory is set in the expert settings, below."
|
868 |
+
msgstr ""
|
869 |
+
"Apriete aquí para ver dentro del directorio de UpdraftPlus (en su sitio de "
|
870 |
+
"Alojamiento web- hosting) para cualquier set de respaldo que desea subir. La "
|
871 |
+
"ubicación de este directorio se fija en la configuración experta, abajo."
|
872 |
+
|
873 |
+
#: updraftplus.php:2856
|
874 |
+
msgid "rescan folder for new backup sets"
|
875 |
+
msgstr "re-escanee directorios por respaldos nuevos"
|
876 |
+
|
877 |
+
#: updraftplus.php:2857
|
878 |
+
msgid "Opera web browser"
|
879 |
+
msgstr "Navegador Opera"
|
880 |
+
|
881 |
+
#: updraftplus.php:2857
|
882 |
+
msgid "If you are using this, then turn Turbo/Road mode off."
|
883 |
+
msgstr "Si esta usando esto, estonces apague (off) modo Turbo/Road"
|
884 |
+
|
885 |
+
#: updraftplus.php:2858
|
886 |
+
msgid "This is a count of the contents of your Updraft directory"
|
887 |
+
msgstr "Esto es un conteo del contenido de su directorio Updraft"
|
888 |
+
|
889 |
+
#: updraftplus.php:2858
|
890 |
+
msgid "Web-server disk space in use by UpdraftPlus"
|
891 |
+
msgstr "Espacio de disco usado en su servidor de web"
|
892 |
+
|
893 |
+
#: updraftplus.php:2858
|
894 |
+
msgid "refresh"
|
895 |
+
msgstr "refrescar"
|
896 |
+
|
897 |
+
#: updraftplus.php:2860
|
898 |
+
msgid "UpdraftPlus - Upload backup files"
|
899 |
+
msgstr "UpdraftPlus - Subir (upload) archivos derespaldo"
|
900 |
+
|
901 |
+
#: updraftplus.php:2861
|
902 |
+
msgid ""
|
903 |
+
"Upload files into UpdraftPlus. Use this to import backups made on a "
|
904 |
+
"different WordPress installation."
|
905 |
+
msgstr ""
|
906 |
+
"Subir (upload) archivos dentro de UpdraftPlus. Use esto para importar "
|
907 |
+
"respaldos hechos en otras instalaciones de WordPress."
|
908 |
+
|
909 |
+
#: updraftplus.php:2865
|
910 |
+
msgid "Drop backup zips here"
|
911 |
+
msgstr "Poner el zip del respaldo aquí"
|
912 |
+
|
913 |
+
#: updraftplus.php:2879
|
914 |
+
msgid "calculating..."
|
915 |
+
msgstr "calculando..."
|
916 |
+
|
917 |
+
#: updraftplus.php:2948
|
918 |
+
msgid "Restore backup"
|
919 |
+
msgstr "Restaurar el respaldo"
|
920 |
+
|
921 |
+
#: updraftplus.php:2949
|
922 |
+
msgid "Restore backup from"
|
923 |
+
msgstr "Restaurar el respaldo desde"
|
924 |
+
|
925 |
+
#: updraftplus.php:2950
|
926 |
+
msgid ""
|
927 |
+
"Restoring will replace this site's themes, plugins, uploads and/or other "
|
928 |
+
"content directories (according to what is contained in the backup set, and "
|
929 |
+
"your selection"
|
930 |
+
msgstr ""
|
931 |
+
"La restauración va a reemplazar en este site el tema, plugin, subidas "
|
932 |
+
"(uploads) y/u otros contenidos de acuerdo al contenido del set de "
|
933 |
+
"restauración y su selección"
|
934 |
+
|
935 |
+
#: updraftplus.php:2950
|
936 |
+
msgid "Choose the components to restore"
|
937 |
+
msgstr "Seleccione el componente a restaurar"
|
938 |
+
|
939 |
+
#: updraftplus.php:2961
|
940 |
+
msgid ""
|
941 |
+
"Databases cannot yet be restored from here - you must download the database "
|
942 |
+
"file and take it to your web hosting company's control panel."
|
943 |
+
msgstr ""
|
944 |
+
"La base de datos no se ha podido restaurar desde aquí - debe de bajar el "
|
945 |
+
"archivo de la base de datos y llevarlo a su panel de control de su "
|
946 |
+
"alojamiento web"
|
947 |
+
|
948 |
+
#: updraftplus.php:2966
|
949 |
+
msgid "Perform a backup now"
|
950 |
+
msgstr "Realice el respaldo ahora"
|
951 |
+
|
952 |
+
#: updraftplus.php:2968
|
953 |
+
msgid ""
|
954 |
+
"This will schedule a one-time backup. To proceed, press 'Backup Now', then "
|
955 |
+
"wait 10 seconds, then visit any page on your site. WordPress should then "
|
956 |
+
"start the backup running in the background."
|
957 |
+
msgstr ""
|
958 |
+
"Esto va a programar un respaldo una sola vez. Para procede apriete 'Respalde "
|
959 |
+
"Ahora', luego espere 10 segundos, luego visite cualquier página en su site. "
|
960 |
+
"En este momento WordPress empezara a correr el respaldo"
|
961 |
+
|
962 |
+
#: updraftplus.php:2974
|
963 |
+
msgid "Does nothing happen when you schedule backups?"
|
964 |
+
msgstr "Nada pasa cuando programa un respaldo?"
|
965 |
+
|
966 |
+
#: updraftplus.php:2974
|
967 |
+
msgid "Go here for help."
|
968 |
+
msgstr "Visite aquí para ayuda."
|
969 |
+
|
970 |
+
#: updraftplus.php:2981
|
971 |
+
msgid "Multisite"
|
972 |
+
msgstr "Mulrisite"
|
973 |
+
|
974 |
+
#: updraftplus.php:2985
|
975 |
+
msgid "Do you need WordPress Multisite support?"
|
976 |
+
msgstr "Va a necesitar soporte de Multisite de WordPress?"
|
977 |
+
|
978 |
+
#: updraftplus.php:2985
|
979 |
+
msgid ""
|
980 |
+
"Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on."
|
981 |
+
msgstr "Por favor chequee UltradraftPlus Premium o el adicional para Multisite"
|
982 |
+
|
983 |
+
#: updraftplus.php:2990
|
984 |
+
msgid "Configure Backup Contents And Schedule"
|
985 |
+
msgstr "Configure el contenido del respaldo y su horario"
|
986 |
+
|
987 |
+
#: updraftplus.php:2996
|
988 |
+
msgid "Debug Information And Expert Options"
|
989 |
+
msgstr "información de depuración y opciones de expertos "
|
990 |
+
|
991 |
+
#: updraftplus.php:3001
|
992 |
+
msgid "Peak memory usage"
|
993 |
+
msgstr "Tope de uso de memoria"
|
994 |
+
|
995 |
+
#: updraftplus.php:3002
|
996 |
+
msgid "Current memory usage"
|
997 |
+
msgstr "Uso de memoria actual"
|
998 |
+
|
999 |
+
#: updraftplus.php:3003
|
1000 |
+
msgid "PHP memory limit"
|
1001 |
+
msgstr "limite de memoria PHP"
|
1002 |
+
|
1003 |
+
#: updraftplus.php:3006
|
1004 |
+
msgid ""
|
1005 |
+
"The buttons below will immediately execute a backup run, independently of "
|
1006 |
+
"WordPress's scheduler. If these work whilst your scheduled backups and the "
|
1007 |
+
"\"Backup Now\" button do absolutely nothing (i.e. not even produce a log "
|
1008 |
+
"file), then it means that your scheduler is broken. You should then disable "
|
1009 |
+
"all your other plugins, and try the \"Backup Now\" button. If that fails, "
|
1010 |
+
"then contact your web hosting company and ask them if they have disabled wp-"
|
1011 |
+
"cron. If it succeeds, then re-activate your other plugins one-by-one, and "
|
1012 |
+
"find the one that is the problem and report a bug to them."
|
1013 |
+
msgstr ""
|
1014 |
+
"El botón abajo inicia un respaldo inmediatamente, independiente del horario "
|
1015 |
+
"de WordPress. Si esto trabaja muestras trabaja el horario de respaldo y el "
|
1016 |
+
"botón \"Respaldar Ahora\" no hace nada (ni siquiera el archivo de log), "
|
1017 |
+
"entonces quiere decir que su programación se rompió. Usted debe en este "
|
1018 |
+
"momento de desactivar todos los demás plugins y probar de nuevo el botón "
|
1019 |
+
"\"Respaldar Ahora\". Si no tiene éxito contacte su sitio de alojamiento web "
|
1020 |
+
"(hosting) y solicite le desactiven el wp-cron. Si esto tiene éxito, entonces "
|
1021 |
+
"reactive sus otros plugins uno a uno, y consiga cuál de ellos tiene el "
|
1022 |
+
"problema y repórtelo a su autor."
|
1023 |
+
|
1024 |
+
#: updraftplus.php:3010
|
1025 |
+
msgid "Debug Full Backup"
|
1026 |
+
msgstr "Depurar Respaldo Completo"
|
1027 |
+
|
1028 |
+
#: updraftplus.php:3010
|
1029 |
+
msgid ""
|
1030 |
+
"This will cause an immediate backup. The page will stall loading until it "
|
1031 |
+
"finishes (ie, unscheduled)."
|
1032 |
+
msgstr ""
|
1033 |
+
"Esto causara un respaldo inmediato. La página se atacara cargando hasta que "
|
1034 |
+
"termine (no programado)."
|
1035 |
+
|
1036 |
+
#: updraftplus.php:3014
|
1037 |
+
msgid "Debug Database Backup"
|
1038 |
+
msgstr "Depuración de la base de datos del respaldo"
|
1039 |
+
|
1040 |
+
#: updraftplus.php:3014
|
1041 |
+
msgid ""
|
1042 |
+
"This will cause an immediate DB backup. The page will stall loading until it "
|
1043 |
+
"finishes (ie, unscheduled). The backup may well run out of time; really this "
|
1044 |
+
"button is only helpful for checking that the backup is able to get through "
|
1045 |
+
"the initial stages, or for small WordPress sites.."
|
1046 |
+
msgstr ""
|
1047 |
+
"Esto causara un respaldo inmediato de la base de datos (DB). La página se "
|
1048 |
+
"estancara hasta que termine. El respaldo podría correr fuera de tiempo, este "
|
1049 |
+
"botón realmente es útil para chequear que el respaldo pueda pasar por sus "
|
1050 |
+
"etapas iniciales o para Sitios Webs pequeños de WordPress"
|
1051 |
+
|
1052 |
+
#: updraftplus.php:3016
|
1053 |
+
msgid "Wipe Settings"
|
1054 |
+
msgstr "Borrar Configuración"
|
1055 |
+
|
1056 |
+
#: updraftplus.php:3017
|
1057 |
+
msgid ""
|
1058 |
+
"This button will delete all UpdraftPlus settings (but not any of your "
|
1059 |
+
"existing backups from your cloud storage). You will then need to enter all "
|
1060 |
+
"your settings again. You can also do this before deactivating/deinstalling "
|
1061 |
+
"UpdraftPlus if you wish."
|
1062 |
+
msgstr ""
|
1063 |
+
"Este botón borrara todas las configuraciones de UpdraftPlus (pero no borrara "
|
1064 |
+
"respaldo actuales realizados en su almacenamiento externo). Tendrá que "
|
1065 |
+
"configurar de nuevo todo. Podrá hacer antes de desactivar/desinstalar "
|
1066 |
+
"UpdraftPlus si desea."
|
1067 |
+
|
1068 |
+
#: updraftplus.php:3020
|
1069 |
+
msgid "Wipe All Settings"
|
1070 |
+
msgstr "Borrar todos los ajustes"
|
1071 |
+
|
1072 |
+
#: updraftplus.php:3020
|
1073 |
+
msgid ""
|
1074 |
+
"This will delete all your UpdraftPlus settings - are you sure you want to do "
|
1075 |
+
"this?"
|
1076 |
+
msgstr ""
|
1077 |
+
"Esto borrara todos los ajustes de UpdraftPlus. Está seguro de realizar esta "
|
1078 |
+
"operación?"
|
1079 |
+
|
1080 |
+
#: updraftplus.php:3089
|
1081 |
+
msgid "Press here to download"
|
1082 |
+
msgstr "Haga clic aqui para bajar"
|
1083 |
+
|
1084 |
+
#: updraftplus.php:3091
|
1085 |
+
#, php-format
|
1086 |
+
msgid "(No %s)"
|
1087 |
+
msgstr "(No %s)"
|
1088 |
+
|
1089 |
+
#: updraftplus.php:3101
|
1090 |
+
msgid "Backup Log"
|
1091 |
+
msgstr "Log de respaldo"
|
1092 |
+
|
1093 |
+
#: updraftplus.php:3109
|
1094 |
+
msgid ""
|
1095 |
+
"After pressing this button, you will be given the option to choose which "
|
1096 |
+
"components you wish to restore"
|
1097 |
+
msgstr ""
|
1098 |
+
"Luego de marcar este botón, tendra la opción de seleccionar cuales "
|
1099 |
+
"componentes desea restaurar"
|
1100 |
+
|
1101 |
+
#: updraftplus.php:3134 updraftplus.php:3138
|
1102 |
+
msgid "Warning"
|
1103 |
+
msgstr "Cuidado"
|
1104 |
+
|
1105 |
+
#: updraftplus.php:3134
|
1106 |
+
#, php-format
|
1107 |
+
msgid ""
|
1108 |
+
"You have less than %s of free disk space on the disk which UpdraftPlus is "
|
1109 |
+
"configured to use to create backups. UpdraftPlus could well run out of "
|
1110 |
+
"space. Contact your the operator of your server (e.g. your web hosting "
|
1111 |
+
"company) to resolve this issue."
|
1112 |
+
msgstr ""
|
1113 |
+
"Usted tiene menos de %s de disco disponible, donde UpdraftPlus guarda los "
|
1114 |
+
"respaldos creados. UpdraftPlus podria en cualquier momento de quedarse sin "
|
1115 |
+
"espacio. Contacte su sitio de alojamiento (hosting) para resolver este "
|
1116 |
+
"problema."
|
1117 |
+
|
1118 |
+
#: updraftplus.php:3138
|
1119 |
+
#, php-format
|
1120 |
+
msgid ""
|
1121 |
+
"UpdraftPlus does not officially support versions of WordPress before %s. It "
|
1122 |
+
"may work for you, but if it does not, then please be aware that no support "
|
1123 |
+
"is available until you upgrade WordPress."
|
1124 |
+
msgstr ""
|
1125 |
+
"UpdraftPlus no soporta oficialmente las versiones de WordPress anteriores a "
|
1126 |
+
"%s. Podría funcionar, pero si no funciona, tenga en cuenta que no tendrá "
|
1127 |
+
"soporte disponible hasta que actualice el WordPress."
|
1128 |
+
|
1129 |
+
#: updraftplus.php:3142 updraftplus.php:3146 updraftplus.php:3150
|
1130 |
+
msgid "UpdraftPlus notice:"
|
1131 |
+
msgstr "Aviso de UpdraftPlus "
|
1132 |
+
|
1133 |
+
#: updraftplus.php:3142
|
1134 |
+
msgid "The log file could not be read."
|
1135 |
+
msgstr "El archivo de registro (log) no se pudo leer"
|
1136 |
+
|
1137 |
+
#: updraftplus.php:3146 updraftplus.php:3150
|
1138 |
+
#, php-format
|
1139 |
+
msgid ""
|
1140 |
+
"Click here to authenticate your %s account (you will not be able to back up "
|
1141 |
+
"to %s without it)."
|
1142 |
+
msgstr ""
|
1143 |
+
"Haga clic aquí para autenticar su cuenta de %s (no podrá respaldar a %s sin "
|
1144 |
+
"la autentificación"
|
1145 |
+
|
1146 |
+
#: updraftplus.php:3323
|
1147 |
+
msgid "Infinite recursion: consult your log for more information"
|
1148 |
+
msgstr "Recursión infinita; consulte su registro (log) para mas información"
|
1149 |
+
|
1150 |
+
#: includes/updraft-restorer.php:5
|
1151 |
+
msgid "Backup file not available."
|
1152 |
+
msgstr "Archivo de respaldo no disponible"
|
1153 |
+
|
1154 |
+
#: includes/updraft-restorer.php:6
|
1155 |
+
msgid "Unpacking backup..."
|
1156 |
+
msgstr "Descomprimiendo el respaldo..."
|
1157 |
+
|
1158 |
+
#: includes/updraft-restorer.php:7
|
1159 |
+
msgid "Moving old directory out of the way..."
|
1160 |
+
msgstr "Moviendo directorio viejo..."
|
1161 |
+
|
1162 |
+
#: includes/updraft-restorer.php:8
|
1163 |
+
msgid "Moving unpacked backup in place..."
|
1164 |
+
msgstr "Moviendo respaldo descomprimido en sitio..."
|
1165 |
+
|
1166 |
+
#: includes/updraft-restorer.php:9
|
1167 |
+
msgid "Cleaning up rubbish..."
|
1168 |
+
msgstr "Limpiando basura..."
|
1169 |
+
|
1170 |
+
#: includes/updraft-restorer.php:10
|
1171 |
+
msgid ""
|
1172 |
+
"Could not move old directory out of the way. Perhaps you already have -old "
|
1173 |
+
"directories that need deleting first?"
|
1174 |
+
msgstr ""
|
1175 |
+
"No se pudo mover el directorio viejo. A lo mejor ya lo hiso - directorios "
|
1176 |
+
"viejos que necesitan borrar primero?"
|
1177 |
+
|
1178 |
+
#: includes/updraft-restorer.php:11
|
1179 |
+
msgid ""
|
1180 |
+
"Could not move new directory into place. Check your wp-content/upgrade "
|
1181 |
+
"folder."
|
1182 |
+
msgstr ""
|
1183 |
+
"No se pudo mover el nuevo directorio a su sitio. Chequee su wp-content/"
|
1184 |
+
"upgrade folder"
|
1185 |
+
|
1186 |
+
#: includes/updraft-restorer.php:12
|
1187 |
+
msgid "Failed to delete working directory after restoring."
|
1188 |
+
msgstr "No se borró el directorio de trabajo después de restaurar."
|
1189 |
+
|
1190 |
+
#: includes/updraft-restorer.php:34
|
1191 |
+
msgid ""
|
1192 |
+
"Will not delete the archive after unpacking it, because there was no cloud "
|
1193 |
+
"storage for this backup"
|
1194 |
+
msgstr ""
|
1195 |
+
"No borrara el archivo luego de descomprimir, porque no hay un almacenaje en "
|
1196 |
+
"la nube para este respaldo"
|
1197 |
+
|
1198 |
+
#: methods/webdav.php:13 methods/webdav.php:34 methods/webdav.php:50
|
1199 |
+
#: methods/sftp.php:13 methods/sftp.php:34 methods/sftp.php:50
|
1200 |
+
#, php-format
|
1201 |
+
msgid "You do not have the UpdraftPlus %s add-on installed - get it from %s"
|
1202 |
+
msgstr ""
|
1203 |
+
"Usted no tiene la adición (add-on) %s de UpdraftPlus instalado - consígalo "
|
1204 |
+
"de %s"
|
1205 |
+
|
1206 |
+
#: methods/webdav.php:63 methods/sftp.php:63
|
1207 |
+
#, php-format
|
1208 |
+
msgid "%s support is available as an add-on"
|
1209 |
+
msgstr "Soporte de %s esta disponible como una adición (add-on) "
|
1210 |
+
|
1211 |
+
#: methods/webdav.php:63 methods/sftp.php:63
|
1212 |
+
msgid "follow this link to get it"
|
1213 |
+
msgstr "Siga este enlace para obtenerlo"
|
1214 |
+
|
1215 |
+
#: methods/googledrive.php:94 methods/s3.php:326 methods/dropbox.php:293
|
1216 |
+
#: addons/webdav.php:292
|
1217 |
+
msgid "Success"
|
1218 |
+
msgstr "Con éxito"
|
1219 |
+
|
1220 |
+
#: methods/googledrive.php:94 methods/dropbox.php:293
|
1221 |
+
#, php-format
|
1222 |
+
msgid "you have authenticated your %s account"
|
1223 |
+
msgstr "Usted ha autenticado su cuenta de %s"
|
1224 |
+
|
1225 |
+
#: methods/googledrive.php:94 methods/googledrive.php:325
|
1226 |
+
#: methods/googledrive.php:327 methods/googledrive.php:345
|
1227 |
+
#: methods/googledrive.php:349 methods/googledrive.php:353
|
1228 |
+
msgid "Google Drive"
|
1229 |
+
msgstr "Google Drive"
|
1230 |
+
|
1231 |
+
#: methods/googledrive.php:98
|
1232 |
+
msgid ""
|
1233 |
+
"No refresh token was received from Google. This often means that you entered "
|
1234 |
+
"your client secret wrongly, or that you have not yet re-authenticated "
|
1235 |
+
"(below) since correcting it. Re-check it, then follow the link to "
|
1236 |
+
"authenticate again. Finally, if that does not work, then use expert mode to "
|
1237 |
+
"wipe all your settings, create a new Google client ID/secret, and start "
|
1238 |
+
"again."
|
1239 |
+
msgstr ""
|
1240 |
+
"No se ha recibido un \"refresh token\" de Google. Frecuentemente esto quiere "
|
1241 |
+
"decir que ingreso erróneamente su clave (client secret) de cliente, o que no "
|
1242 |
+
"ha re-autenticado todavía desde que lo corrigió. Re-chequee y vaya al enlace "
|
1243 |
+
"para autenticar de nuevo. Finalmente si esto no funciona, use modo de "
|
1244 |
+
"experto para borrar todas las configuraciones, crea de nuevo un ID/secret de "
|
1245 |
+
"cliente y empiece de nuevo."
|
1246 |
+
|
1247 |
+
#: methods/googledrive.php:103
|
1248 |
+
msgid "Authorization failed"
|
1249 |
+
msgstr "Autorización no exitosa"
|
1250 |
+
|
1251 |
+
#: methods/googledrive.php:117
|
1252 |
+
msgid ""
|
1253 |
+
"Have not yet obtained an access token from Google - you need to authorise or "
|
1254 |
+
"re-authorise your connection to Google Drive."
|
1255 |
+
msgstr ""
|
1256 |
+
"“Todavía no ha obtenido un token de acceso de Google - usted debe de "
|
1257 |
+
"autorizar o re-autorizar su conexión a Google Drive."
|
1258 |
+
|
1259 |
+
#: methods/googledrive.php:118 methods/googledrive.php:254
|
1260 |
+
msgid ""
|
1261 |
+
"Have not yet obtained an access token from Google (has the user authorised?)"
|
1262 |
+
msgstr ""
|
1263 |
+
"No ha obtenido un \"access token\" de Google (el usuario a autorizado?)"
|
1264 |
+
|
1265 |
+
#: methods/googledrive.php:135 addons/webdav.php:57
|
1266 |
+
#, php-format
|
1267 |
+
msgid "Failed to upload to %s"
|
1268 |
+
msgstr "Subida no exitosa a %s"
|
1269 |
+
|
1270 |
+
#: methods/googledrive.php:189 addons/webdav.php:57
|
1271 |
+
msgid "Error"
|
1272 |
+
msgstr "Error"
|
1273 |
+
|
1274 |
+
#: methods/googledrive.php:225
|
1275 |
+
msgid "An error occurred during GoogleDrive upload (see log for more details)"
|
1276 |
+
msgstr ""
|
1277 |
+
"Ha ocurrido un error durante la subida a Google Drive (ver el registro (log) "
|
1278 |
+
"para mas detalles)"
|
1279 |
+
|
1280 |
+
#: methods/googledrive.php:266
|
1281 |
+
#, php-format
|
1282 |
+
msgid ""
|
1283 |
+
"Google Drive error: %d: could not download: could not find a record of the "
|
1284 |
+
"Google Drive file ID for this file"
|
1285 |
+
msgstr ""
|
1286 |
+
"Error de Google Drive: %d: no pudo bajar: No se pudo encontrar ningún record "
|
1287 |
+
"en el file ID de Google Drive de este archivo"
|
1288 |
+
|
1289 |
+
#: methods/googledrive.php:271
|
1290 |
+
#, php-format
|
1291 |
+
msgid "Could not find %s in order to download it"
|
1292 |
+
msgstr "No se pudo conseguir %s para bajarlo"
|
1293 |
+
|
1294 |
+
#: methods/googledrive.php:283
|
1295 |
+
msgid "Google Drive "
|
1296 |
+
msgstr "Google Drive"
|
1297 |
+
|
1298 |
+
#: methods/googledrive.php:283
|
1299 |
+
msgid "error: zero-size file was downloaded"
|
1300 |
+
msgstr "error: archivo de tamaño cero bajado"
|
1301 |
+
|
1302 |
+
#: methods/googledrive.php:301
|
1303 |
+
msgid "Account is not authorized."
|
1304 |
+
msgstr "Cuenta no autorizada"
|
1305 |
+
|
1306 |
+
#: methods/googledrive.php:328 methods/s3.php:246 methods/dropbox.php:217
|
1307 |
+
#: methods/ftp.php:109 addons/webdav.php:231
|
1308 |
+
#, php-format
|
1309 |
+
msgid ""
|
1310 |
+
"%s is a great choice, because UpdraftPlus supports chunked uploads - no "
|
1311 |
+
"matter how big your blog is, UpdraftPlus can upload it a little at a time, "
|
1312 |
+
"and not get thwarted by timeouts."
|
1313 |
+
msgstr ""
|
1314 |
+
"%s es una buena selección, porque UpdraftPlus soporta subidas en trozos\" - "
|
1315 |
+
"no importa que tan grande sea su blog, UpdraftPlus puede subir por partes y "
|
1316 |
+
"no tener errores de tiempo vencido"
|
1317 |
+
|
1318 |
+
#: methods/googledrive.php:334
|
1319 |
+
msgid ""
|
1320 |
+
"For longer help, including screenshots, follow this link. The description "
|
1321 |
+
"below is sufficient for more expert users."
|
1322 |
+
msgstr ""
|
1323 |
+
"Para ayudas largas, incluyendo captura de pantallas, siga este enlace. La "
|
1324 |
+
"descripción abajo es para usuarios más expertos."
|
1325 |
+
|
1326 |
+
#: methods/googledrive.php:335
|
1327 |
+
msgid ""
|
1328 |
+
"Follow this link to your Google API Console, and there create a Client ID in "
|
1329 |
+
"the API Access section."
|
1330 |
+
msgstr ""
|
1331 |
+
"Siga este enlace hacia su consola de Google API, ahí puede crear un Client "
|
1332 |
+
"ID en la sección de accesos API"
|
1333 |
+
|
1334 |
+
#: methods/googledrive.php:335
|
1335 |
+
msgid "Select 'Web Application' as the application type."
|
1336 |
+
msgstr "Seleccione 'Aplicación de Web' como el tipo de aplicación"
|
1337 |
+
|
1338 |
+
#: methods/googledrive.php:335
|
1339 |
+
msgid ""
|
1340 |
+
"You must add the following as the authorised redirect URI (under \"More "
|
1341 |
+
"Options\") when asked"
|
1342 |
+
msgstr ""
|
1343 |
+
"Debe agregar el siguiente re-direccionamiento autorizado de URI (debajo de "
|
1344 |
+
"\"Más Opciones\") cuando lo solicite"
|
1345 |
+
|
1346 |
+
#: methods/googledrive.php:335
|
1347 |
+
msgid ""
|
1348 |
+
"N.B. If you install UpdraftPlus on several WordPress sites, then you cannot "
|
1349 |
+
"re-use your client ID; you must create a new one from your Google API "
|
1350 |
+
"console for each blog."
|
1351 |
+
msgstr ""
|
1352 |
+
"N.B. Si usted instala UpdraftPlus en varios sitios de WordPress, no puede "
|
1353 |
+
"reusar su client ID; debe de crear uno nuevo por cada blog en su consola de "
|
1354 |
+
"Google API."
|
1355 |
+
|
1356 |
+
#: methods/googledrive.php:338
|
1357 |
+
msgid ""
|
1358 |
+
"You do not have the SimpleXMLElement installed. Google Drive backups will "
|
1359 |
+
"<b>not</b> work until you do."
|
1360 |
+
msgstr ""
|
1361 |
+
"No tiene instalado SimpleXMLElement. Respaldos en Google Drive <b>no</b> "
|
1362 |
+
"funcionaran hasta instalarlo."
|
1363 |
+
|
1364 |
+
#: methods/googledrive.php:345
|
1365 |
+
msgid "Client ID"
|
1366 |
+
msgstr "Client ID"
|
1367 |
+
|
1368 |
+
#: methods/googledrive.php:346
|
1369 |
+
msgid ""
|
1370 |
+
"If Google later shows you the message \"invalid_client\", then you did not "
|
1371 |
+
"enter a valid client ID here."
|
1372 |
+
msgstr ""
|
1373 |
+
"Si posteriormente en Google sale este mensaje \"invalid_client\", quiere "
|
1374 |
+
"decir que no introdujo un Client ID valido."
|
1375 |
+
|
1376 |
+
#: methods/googledrive.php:349
|
1377 |
+
msgid "Client Secret"
|
1378 |
+
msgstr "Client Secret (clave secreta de cliente)"
|
1379 |
+
|
1380 |
+
#: methods/googledrive.php:353
|
1381 |
+
msgid "Folder ID"
|
1382 |
+
msgstr "ID de carpeta"
|
1383 |
+
|
1384 |
+
#: methods/googledrive.php:354
|
1385 |
+
msgid ""
|
1386 |
+
"<strong>This is NOT a folder name</strong>. To get a folder's ID navigate to "
|
1387 |
+
"that folder in Google Drive in your web browser and copy the ID from your "
|
1388 |
+
"browser's address bar. It is the part that comes after <kbd>#folders/.</kbd> "
|
1389 |
+
"Leave empty to use your root folder)"
|
1390 |
+
msgstr ""
|
1391 |
+
"<strong>Este no es un nombre de carpeta</strong>. Para obtener un ID de "
|
1392 |
+
"carpeta (folder ID) navegue a esa carpeta en Google Drive y copie el ID "
|
1393 |
+
"desde la dirección de URL de su navegador. Es una parte que va despues "
|
1394 |
+
"<kbd>#folders/.</kbd>Déjela vacía para usar como su carpeta principal o raíz"
|
1395 |
+
|
1396 |
+
#: methods/googledrive.php:357
|
1397 |
+
msgid "Authenticate with Google"
|
1398 |
+
msgstr "Autenticando con Google"
|
1399 |
+
|
1400 |
+
#: methods/googledrive.php:358
|
1401 |
+
msgid ""
|
1402 |
+
"<strong>After</strong> you have saved your settings (by clicking 'Save "
|
1403 |
+
"Changes' below), then come back here once and click this link to complete "
|
1404 |
+
"authentication with Google."
|
1405 |
+
msgstr ""
|
1406 |
+
"<strong>Después</strong>de guardar su configuración (dele clic a Guardar "
|
1407 |
+
"Cambios abajo).luego regrese aquí y apriete el enlace para completar la "
|
1408 |
+
"autenticación con Google."
|
1409 |
+
|
1410 |
+
#: methods/email.php:15
|
1411 |
+
msgid "WordPress Backup"
|
1412 |
+
msgstr "Respaldo de Wordpress"
|
1413 |
+
|
1414 |
+
#: methods/email.php:15
|
1415 |
+
msgid "Backup is of:"
|
1416 |
+
msgstr "El respaldo es de:"
|
1417 |
+
|
1418 |
+
#: methods/email.php:15
|
1419 |
+
msgid ""
|
1420 |
+
"Be wary; email backups may fail because of file size limitations on mail "
|
1421 |
+
"servers."
|
1422 |
+
msgstr ""
|
1423 |
+
"Tenga en cuenta; respaldos vía emails pueden tener limitaciones de tamaño en "
|
1424 |
+
"los servidores de correo"
|
1425 |
+
|
1426 |
+
#: methods/email.php:24
|
1427 |
+
msgid "Note:"
|
1428 |
+
msgstr "Nota:"
|
1429 |
+
|
1430 |
+
#: methods/email.php:25
|
1431 |
+
msgid ""
|
1432 |
+
"The email address entered above will be used. If choosing \"E-Mail\", then "
|
1433 |
+
"<strong>be aware</strong> that mail servers tend to have size limits; "
|
1434 |
+
"typically around 10-20Mb; backups larger than any limits will not arrive. If "
|
1435 |
+
"you really need a large backup via email, then you could fund a new feature "
|
1436 |
+
"(to break the backup set into configurable-size pieces) - but the demand has "
|
1437 |
+
"not yet existed for such a feature."
|
1438 |
+
msgstr ""
|
1439 |
+
"La dirección de email introducida arriba será la usada. Si selecciona \"E-"
|
1440 |
+
"Mail\", <strong>tenga en cuenta</strong>que los servidores de correo tienen "
|
1441 |
+
"límites de tamaño; en promedio de 10-20Mb; mayores al límite no llegaran. Si "
|
1442 |
+
"realmente necesita enviar un respaldo grande vía email, entonces debe "
|
1443 |
+
"conseguir otra forma (partir el respaldo en varias partes) - La demanda "
|
1444 |
+
"actual no exige tener esta función actualmente"
|
1445 |
+
|
1446 |
+
#: methods/s3.php:77
|
1447 |
+
#, php-format
|
1448 |
+
msgid "%s Error: Failed to upload"
|
1449 |
+
msgstr "%s Error: Fallo la subida"
|
1450 |
+
|
1451 |
+
#: methods/s3.php:98
|
1452 |
+
msgid ""
|
1453 |
+
"S3 upload: getting uploadID for multipart upload failed - see log file for "
|
1454 |
+
"more details"
|
1455 |
+
msgstr ""
|
1456 |
+
"Subidas en S3: obteniendo uploadID para subidas en partes fallo - ver "
|
1457 |
+
"archivo para mas detalles"
|
1458 |
+
|
1459 |
+
#: methods/s3.php:130
|
1460 |
+
#, php-format
|
1461 |
+
msgid "S3 chunk %s: upload failed"
|
1462 |
+
msgstr "S3 pedaso %s no pudo subir"
|
1463 |
+
|
1464 |
+
#: methods/s3.php:144
|
1465 |
+
#, php-format
|
1466 |
+
msgid "S3 upload (%s): re-assembly failed (see log for more details)"
|
1467 |
+
msgstr ""
|
1468 |
+
"S3 subida (%s): reconstruccion fallo (ver registro (log) para detalles)"
|
1469 |
+
|
1470 |
+
#: methods/s3.php:148
|
1471 |
+
#, php-format
|
1472 |
+
msgid "S3 re-assembly error (%s): (see log file for more)"
|
1473 |
+
msgstr "S3 error de reconstrucción (%s): (ver registro (log))"
|
1474 |
+
|
1475 |
+
#: methods/s3.php:160
|
1476 |
+
#, php-format
|
1477 |
+
msgid ""
|
1478 |
+
"S3 Error: Failed to create bucket %s. Check your permissions and credentials."
|
1479 |
+
msgstr ""
|
1480 |
+
"S3 Error: Fallo creación de bucket %s. Chequee sus credenciales y permisos."
|
1481 |
+
|
1482 |
+
#: methods/s3.php:213
|
1483 |
+
#, php-format
|
1484 |
+
msgid ""
|
1485 |
+
"S3 Error: Failed to download %s. Check your permissions and credentials."
|
1486 |
+
msgstr "S3 Error. No se pudo bajar %s. Chequee sus credenciales y permisos."
|
1487 |
+
|
1488 |
+
#: methods/s3.php:217
|
1489 |
+
#, php-format
|
1490 |
+
msgid ""
|
1491 |
+
"S3 Error: Failed to access bucket %s. Check your permissions and credentials."
|
1492 |
+
msgstr ""
|
1493 |
+
"S3 Error: No hay acceso al bucket %s. Chequee sus credenciales y permisos"
|
1494 |
+
|
1495 |
+
#: methods/s3.php:251
|
1496 |
+
msgid ""
|
1497 |
+
"Get your access key and secret key <a href=\"http://aws.amazon.com/console/"
|
1498 |
+
"\">from your AWS console</a>, then pick a (globally unique - all Amazon S3 "
|
1499 |
+
"users) bucket name (letters and numbers) (and optionally a path) to use for "
|
1500 |
+
"storage. This bucket will be created for you if it does not already exist."
|
1501 |
+
msgstr ""
|
1502 |
+
"Obtenga su 'access key' y 'secret key' <a href=\"http://aws.amazon.com/"
|
1503 |
+
"console/\">desde su consola de AWS</a>, luego escoja un (globalmente unico - "
|
1504 |
+
"usuarios de Amazon S3) bucket name (letras y número y opcionalmente un path) "
|
1505 |
+
"para el almacenamiento. Este bucket va a ser creado por usted si aún no lo "
|
1506 |
+
"tiene."
|
1507 |
+
|
1508 |
+
#: methods/s3.php:254
|
1509 |
+
msgid "S3 access key"
|
1510 |
+
msgstr "S3 access key"
|
1511 |
+
|
1512 |
+
#: methods/s3.php:258
|
1513 |
+
msgid "S3 secret key"
|
1514 |
+
msgstr "S3 secret key"
|
1515 |
+
|
1516 |
+
#: methods/s3.php:262
|
1517 |
+
msgid "S3 location"
|
1518 |
+
msgstr "S3 Ubicación"
|
1519 |
+
|
1520 |
+
#: methods/s3.php:267 methods/ftp.php:135 addons/webdav.php:244
|
1521 |
+
#, php-format
|
1522 |
+
msgid "Test %s Settings"
|
1523 |
+
msgstr "Pruebe configuración de %s"
|
1524 |
+
|
1525 |
+
#: methods/s3.php:275 methods/s3.php:279 methods/ftp.php:152
|
1526 |
+
#: methods/ftp.php:156 addons/webdav.php:272
|
1527 |
+
#, php-format
|
1528 |
+
msgid "Failure: No %s was given."
|
1529 |
+
msgstr "Falla: no se obtubo %s"
|
1530 |
+
|
1531 |
+
#: methods/s3.php:275
|
1532 |
+
msgid "API key"
|
1533 |
+
msgstr "API Key"
|
1534 |
+
|
1535 |
+
#: methods/s3.php:279
|
1536 |
+
msgid "API secret"
|
1537 |
+
msgstr "API secret"
|
1538 |
+
|
1539 |
+
#: methods/s3.php:296
|
1540 |
+
msgid "Failure: No bucket details were given."
|
1541 |
+
msgstr "Falla: No se ha obtenido detalles del bucket"
|
1542 |
+
|
1543 |
+
#: methods/s3.php:306
|
1544 |
+
msgid "Amazon region"
|
1545 |
+
msgstr "Amazon region"
|
1546 |
+
|
1547 |
+
#: methods/s3.php:316
|
1548 |
+
msgid ""
|
1549 |
+
"Failure: We could not successfully access or create such a bucket. Please "
|
1550 |
+
"check your access credentials, and if those are correct then try another "
|
1551 |
+
"bucket name (as another S3 user may already have taken your name)."
|
1552 |
+
msgstr ""
|
1553 |
+
"Falla: No pudimos accesar o crear este bucket. Por favor chequee sus "
|
1554 |
+
"credenciales, si son correctas entonces trate con otro nombre de bucket "
|
1555 |
+
"(otro usuario S3 probablemente tenga ese nombre)."
|
1556 |
+
|
1557 |
+
#: methods/s3.php:324
|
1558 |
+
msgid "Failure"
|
1559 |
+
msgstr "Falla"
|
1560 |
+
|
1561 |
+
#: methods/s3.php:324
|
1562 |
+
msgid ""
|
1563 |
+
"We successfully accessed the bucket, but the attempt to create a file in it "
|
1564 |
+
"failed."
|
1565 |
+
msgstr "Hemos entrado correctamente al bucket, pero no se pudo crear archivos."
|
1566 |
+
|
1567 |
+
#: methods/s3.php:326
|
1568 |
+
msgid "We accessed the bucket, and were able to create files within it."
|
1569 |
+
msgstr "hubo acceso correcto al bucket y pudimos crear los archivos."
|
1570 |
+
|
1571 |
+
#: methods/dropbox.php:35 methods/dropbox.php:167
|
1572 |
+
msgid "You do not appear to be authenticated with Dropbox"
|
1573 |
+
msgstr "Usted no parece estar autenticado en Dropbox"
|
1574 |
+
|
1575 |
+
#: methods/dropbox.php:46
|
1576 |
+
#, php-format
|
1577 |
+
msgid "error: %s (see log file for more)"
|
1578 |
+
msgstr "error: %s (ver registro (log) para mas info)"
|
1579 |
+
|
1580 |
+
#: methods/dropbox.php:98 methods/dropbox.php:103
|
1581 |
+
#, php-format
|
1582 |
+
msgid "error: failed to upload file to %s (see log file for more)"
|
1583 |
+
msgstr "error: fallo la subida de archivos a %s (ver registro (log))"
|
1584 |
+
|
1585 |
+
#: methods/dropbox.php:223
|
1586 |
+
msgid "Need to use sub-folders?"
|
1587 |
+
msgstr "Necesita usar sub-carpetas?"
|
1588 |
+
|
1589 |
+
#: methods/dropbox.php:223
|
1590 |
+
msgid "Backups are saved in"
|
1591 |
+
msgstr "Los respaldos fueron guardados en"
|
1592 |
+
|
1593 |
+
#: methods/dropbox.php:223
|
1594 |
+
msgid ""
|
1595 |
+
"If you back up several sites into the same Dropbox and want to organise with "
|
1596 |
+
"sub-folders, then "
|
1597 |
+
msgstr ""
|
1598 |
+
"Si respalda varios sitios web dentro de Dropbox y desea organizarlos en sub-"
|
1599 |
+
"carpetas, entonces"
|
1600 |
+
|
1601 |
+
#: methods/dropbox.php:223
|
1602 |
+
msgid "there's an add-on for that."
|
1603 |
+
msgstr "hay una adición (add-on) para eso"
|
1604 |
+
|
1605 |
+
#: methods/dropbox.php:228
|
1606 |
+
msgid "Authenticate with Dropbox"
|
1607 |
+
msgstr "Autentique con Dropbox"
|
1608 |
+
|
1609 |
+
#: methods/dropbox.php:229
|
1610 |
+
msgid ""
|
1611 |
+
"<strong>After</strong> you have saved your settings (by clicking 'Save "
|
1612 |
+
"Changes' below), then come back here once and click this link to complete "
|
1613 |
+
"authentication with Dropbox."
|
1614 |
+
msgstr ""
|
1615 |
+
"<strong>Luego</strong> de haber guardado su configuración (usando 'Guardar "
|
1616 |
+
"Cambios' abajo). Regrese aquí una vez y haga clic a este enlace para "
|
1617 |
+
"completar autenticación con Dropbox."
|
1618 |
+
|
1619 |
+
#: methods/dropbox.php:240
|
1620 |
+
msgid ""
|
1621 |
+
"Your web server's PHP installation does not included a required module "
|
1622 |
+
"(MCrypt). Please contact your web hosting provider's support. UpdraftPlus's "
|
1623 |
+
"Dropbox module <strong>requires</strong> MCrypt. Please do not file any "
|
1624 |
+
"support requests; there is no alternative."
|
1625 |
+
msgstr ""
|
1626 |
+
"Su servidor de web PHP no incluye la instalación del módulo requerido "
|
1627 |
+
"(MCrypt). Por favor contacte el soporte de su alojamiento de web (hosting). "
|
1628 |
+
"El módulo de Dropbox en UpdraftPlus <strong>requiere</strong> MCrypt. No "
|
1629 |
+
"contacte nuestro soporte; no hay alternativas."
|
1630 |
+
|
1631 |
+
#: methods/dropbox.php:243
|
1632 |
+
msgid ""
|
1633 |
+
"Your web server's PHP installation does not included a required module "
|
1634 |
+
"(Curl). Please contact your web hosting provider's support. UpdraftPlus's "
|
1635 |
+
"Dropbox module <strong>requires</strong> Curl. Your only options to get this "
|
1636 |
+
"working are 1) Install/enable curl or 2) Hire us or someone else to code "
|
1637 |
+
"additional support options into UpdraftPlus. 3) Wait, possibly forever, for "
|
1638 |
+
"someone else to do this."
|
1639 |
+
msgstr ""
|
1640 |
+
"Su servidor de web PHP no incluye la instalación del módulo requerido "
|
1641 |
+
"(Curl). Por favor contacte el soporte de su alojamiento de web (hosting). El "
|
1642 |
+
"módulo de Dropbox en UpdraftPlus <strong>requiere</strong> Curl. Su única "
|
1643 |
+
"opción adicional para realizar esto es 1) Instalar Curl o 2) Nos contrata a "
|
1644 |
+
"nosotros o alguien como nosotros. 3) Esperar que otra persona lo realice."
|
1645 |
+
|
1646 |
+
#: methods/dropbox.php:296
|
1647 |
+
msgid ""
|
1648 |
+
"though part of the returned information was not as expected - your mileage "
|
1649 |
+
"may vary"
|
1650 |
+
msgstr ""
|
1651 |
+
"aunque parte de la información recibida no fue como se esperaba - su "
|
1652 |
+
"kilometraje puede variar"
|
1653 |
+
|
1654 |
+
#: methods/dropbox.php:299
|
1655 |
+
#, php-format
|
1656 |
+
msgid "Your %s account name"
|
1657 |
+
msgstr "Nombre de cuenta de %s "
|
1658 |
+
|
1659 |
+
#: methods/ftp.php:19 methods/ftp.php:66
|
1660 |
+
msgid "FTP login failure"
|
1661 |
+
msgstr "FTP falla de ingreso (login)"
|
1662 |
+
|
1663 |
+
#: methods/ftp.php:38
|
1664 |
+
msgid "FTP upload failed"
|
1665 |
+
msgstr "FTP no se pudo subir"
|
1666 |
+
|
1667 |
+
#: methods/ftp.php:98
|
1668 |
+
msgid "Settings test result"
|
1669 |
+
msgstr "Resultado del test de configuracón"
|
1670 |
+
|
1671 |
+
#: methods/ftp.php:114
|
1672 |
+
msgid "Only non-encrypted FTP is supported by regular UpdraftPlus."
|
1673 |
+
msgstr "Solo FTP no-cifrado funciona con UpdraftPlus."
|
1674 |
+
|
1675 |
+
#: methods/ftp.php:114
|
1676 |
+
msgid ""
|
1677 |
+
"If you want encryption (e.g. you are storing sensitive business data), then "
|
1678 |
+
"an add-on is available."
|
1679 |
+
msgstr ""
|
1680 |
+
"Si desea cifrar (e.g. material sensible), nosotros tenemos una adición (add-"
|
1681 |
+
"on) disponible para ello."
|
1682 |
+
|
1683 |
+
#: methods/ftp.php:118
|
1684 |
+
msgid "FTP Server"
|
1685 |
+
msgstr "Servidor FTP"
|
1686 |
+
|
1687 |
+
#: methods/ftp.php:122
|
1688 |
+
msgid "FTP Login"
|
1689 |
+
msgstr "Registro FTD (login)"
|
1690 |
+
|
1691 |
+
#: methods/ftp.php:126
|
1692 |
+
msgid "FTP Password"
|
1693 |
+
msgstr "FTP Clave"
|
1694 |
+
|
1695 |
+
#: methods/ftp.php:130
|
1696 |
+
msgid "Remote Path"
|
1697 |
+
msgstr "Dirección remota"
|
1698 |
+
|
1699 |
+
#: methods/ftp.php:131
|
1700 |
+
msgid "Needs to already exist"
|
1701 |
+
msgstr "Necesidades que ya existen"
|
1702 |
+
|
1703 |
+
#: methods/ftp.php:148
|
1704 |
+
msgid "Failure: No server details were given."
|
1705 |
+
msgstr "Falla: No se dieron detalles del servidor."
|
1706 |
+
|
1707 |
+
#: methods/ftp.php:167
|
1708 |
+
msgid "Failure: we did not successfully log in with those credentials."
|
1709 |
+
msgstr "Falla: No pudimos ingresar con esas credenciales."
|
1710 |
+
|
1711 |
+
#: methods/ftp.php:175
|
1712 |
+
msgid ""
|
1713 |
+
"Failure: an unexpected internal UpdraftPlus error occurred when testing the "
|
1714 |
+
"credentials - please contact the developer"
|
1715 |
+
msgstr ""
|
1716 |
+
"Falla: Un error inesperado de UpdraftPlus ocurrió cuando se probaban las "
|
1717 |
+
"credenciales - por favor contacte el desarrollador"
|
1718 |
+
|
1719 |
+
#: methods/ftp.php:179
|
1720 |
+
msgid ""
|
1721 |
+
"Success: we successfully logged in, and confirmed our ability to create a "
|
1722 |
+
"file in the given directory (login type:"
|
1723 |
+
msgstr ""
|
1724 |
+
"Exitoso: Nos registramos con éxito y confirmamos nuestra habilidad de crear "
|
1725 |
+
"archivos en el directorio dado (tipo de registro (login):"
|
1726 |
+
|
1727 |
+
#: methods/ftp.php:182
|
1728 |
+
msgid ""
|
1729 |
+
"Failure: we successfully logged in, but were not able to create a file in "
|
1730 |
+
"the given directory."
|
1731 |
+
msgstr ""
|
1732 |
+
"Falla: Nos registramos con éxito pero no pudimos crear archivos en el "
|
1733 |
+
"directorio dado."
|
1734 |
+
|
1735 |
+
#: addons/webdav.php:40 addons/webdav.php:170
|
1736 |
+
#, php-format
|
1737 |
+
msgid "No %s settings were found"
|
1738 |
+
msgstr "Falto configuración %s"
|
1739 |
+
|
1740 |
+
#: addons/webdav.php:116 addons/webdav.php:120
|
1741 |
+
#, php-format
|
1742 |
+
msgid "Chunk %s: A %s error occurred"
|
1743 |
+
msgstr "Ocurrió error de pedazo %s: A %s"
|
1744 |
+
|
1745 |
+
#: addons/webdav.php:182 addons/webdav.php:188 addons/webdav.php:200
|
1746 |
+
msgid "WebDAV Error"
|
1747 |
+
msgstr "Error de WebDAV"
|
1748 |
+
|
1749 |
+
#: addons/webdav.php:182
|
1750 |
+
msgid "Error opening local file: Failed to download"
|
1751 |
+
msgstr "Error abriendo archivo local: No se pudo bajar"
|
1752 |
+
|
1753 |
+
#: addons/webdav.php:188
|
1754 |
+
msgid "Error opening remote file: Failed to download"
|
1755 |
+
msgstr "Error abriendo archivo remoto: No se pudo bajar"
|
1756 |
+
|
1757 |
+
#: addons/webdav.php:200
|
1758 |
+
msgid "Local write failed: Failed to download"
|
1759 |
+
msgstr "Escritura local fallo: No se pudo bajar"
|
1760 |
+
|
1761 |
+
#: addons/webdav.php:234
|
1762 |
+
msgid "WebDAV URL"
|
1763 |
+
msgstr "URL de WebDAV"
|
1764 |
+
|
1765 |
+
#: addons/webdav.php:238
|
1766 |
+
#, php-format
|
1767 |
+
msgid ""
|
1768 |
+
"Enter a complete URL, beginning with webdav:// or webdavs:// and including "
|
1769 |
+
"path, username, password and port as required - e.g.%s"
|
1770 |
+
msgstr ""
|
1771 |
+
"Ponga un URL completo, empezado con webdav:// o webdavs:// e incluyendo la "
|
1772 |
+
"ruta, usuario, clave y puertos requeridos - e.g. %s"
|
1773 |
+
|
1774 |
+
#: addons/webdav.php:281
|
1775 |
+
msgid "Failed"
|
1776 |
+
msgstr "Fallo"
|
1777 |
+
|
1778 |
+
#: addons/webdav.php:295
|
1779 |
+
msgid ""
|
1780 |
+
"Failed: We were not able to place a file in that directory - please check "
|
1781 |
+
"your credentials."
|
1782 |
+
msgstr ""
|
1783 |
+
"Fallo: No pudimos poner un archivo en ese directorio - Por favor chequee sus "
|
1784 |
+
"credenciales."
|
1785 |
+
|
1786 |
+
#: addons/sftp.php:23
|
1787 |
+
msgid ""
|
1788 |
+
"Encrypted FTP is available, and will be automatically tried first (before "
|
1789 |
+
"falling back to non-encrypted if it is not successful). The 'Test FTP Login' "
|
1790 |
+
"button will tell you what type of connection is in use."
|
1791 |
+
msgstr ""
|
1792 |
+
"FTP cifrado está disponible y será intentado siempre inicialmente (luego se "
|
1793 |
+
"intentara no-cifrado si no fue exitoso). El botón 'Pruebe Registro FTP' le "
|
1794 |
+
"dirá que tipo de conexión está en uso."
|
1795 |
+
|
1796 |
+
#: addons/sftp.php:30 addons/sftp.php:31 addons/sftp.php:32
|
1797 |
+
#, php-format
|
1798 |
+
msgid "No %s found"
|
1799 |
+
msgstr "No %s encontrados"
|
1800 |
+
|
1801 |
+
#: addons/sftp.php:30
|
1802 |
+
msgid "SFTP host setting"
|
1803 |
+
msgstr "SFTP Configuración del servidor"
|
1804 |
+
|
1805 |
+
#: addons/sftp.php:31
|
1806 |
+
msgid "SFTP user setting"
|
1807 |
+
msgstr "SFTP Configuración de usuario"
|
1808 |
+
|
1809 |
+
#: addons/sftp.php:32
|
1810 |
+
msgid "SFTP passwrd"
|
1811 |
+
msgstr "SFTP Clave"
|
1812 |
+
|
1813 |
+
#: addons/sftp.php:50 addons/sftp.php:293
|
1814 |
+
msgid "Check your file permissions: Could not successfully create and enter:"
|
1815 |
+
msgstr "Chequee permisos de archivos: No se pudo crear con exito e ingrese:"
|
1816 |
+
|
1817 |
+
#: addons/sftp.php:128
|
1818 |
+
#, php-format
|
1819 |
+
msgid "%s Error: Failed to download"
|
1820 |
+
msgstr "Error %s: No se pudo bajar"
|
1821 |
+
|
1822 |
+
#: addons/sftp.php:172
|
1823 |
+
msgid ""
|
1824 |
+
"Resuming partial uploads is not supported, so you will need to ensure that "
|
1825 |
+
"your webserver allows PHP processes to run long enough to upload your "
|
1826 |
+
"largest backup file."
|
1827 |
+
msgstr ""
|
1828 |
+
"Retomar subidas parciales no son aceptadas, o sea que debe de asegurarse que "
|
1829 |
+
"su servidor de web, permite procesos PHP, correr el tiempo suficiente para "
|
1830 |
+
"subir sus archivos grandes."
|
1831 |
+
|
1832 |
+
#: addons/sftp.php:177
|
1833 |
+
msgid "Host"
|
1834 |
+
msgstr "Host (servidor)"
|
1835 |
+
|
1836 |
+
#: addons/sftp.php:184
|
1837 |
+
msgid "Port"
|
1838 |
+
msgstr "Puerto"
|
1839 |
+
|
1840 |
+
#: addons/sftp.php:191
|
1841 |
+
msgid "Username"
|
1842 |
+
msgstr "Usuario"
|
1843 |
+
|
1844 |
+
#: addons/sftp.php:198
|
1845 |
+
msgid "Password"
|
1846 |
+
msgstr "Clave"
|
1847 |
+
|
1848 |
+
#: addons/sftp.php:214
|
1849 |
+
msgid "Directory path"
|
1850 |
+
msgstr "Ruta del directorio"
|
1851 |
+
|
1852 |
+
#: addons/sftp.php:216
|
1853 |
+
msgid ""
|
1854 |
+
"Where to change directory to after logging in - often this is relative to "
|
1855 |
+
"your home directory."
|
1856 |
+
msgstr ""
|
1857 |
+
"Donde cambiar el directorio luego de registrarse - frecuentemente esta "
|
1858 |
+
"relativo a su directorio principal"
|
1859 |
+
|
1860 |
+
#: addons/sftp.php:254
|
1861 |
+
msgid "host name"
|
1862 |
+
msgstr "Nombre del servidor (host)"
|
1863 |
+
|
1864 |
+
#: addons/sftp.php:258
|
1865 |
+
msgid "username"
|
1866 |
+
msgstr "usuario"
|
1867 |
+
|
1868 |
+
#: addons/sftp.php:262
|
1869 |
+
msgid "password"
|
1870 |
+
msgstr "clave"
|
1871 |
+
|
1872 |
+
#: addons/sftp.php:267
|
1873 |
+
msgid "Failure: Port must be an integer."
|
1874 |
+
msgstr "Falla: El puerto debe de ser un numero entero"
|
1875 |
+
|
1876 |
+
#: addons/sftp.php:307
|
1877 |
+
msgid ""
|
1878 |
+
"Failed: We were able to log in and move to the indicated directory, but "
|
1879 |
+
"failed to successfully created a file in that location."
|
1880 |
+
msgstr ""
|
1881 |
+
"Falla: Pudimos registrarnos y mover el directorio indicado, pero fallamos "
|
1882 |
+
"creando un archivo en esta locación."
|
1883 |
+
|
1884 |
+
#: addons/fixtime.php:77 addons/fixtime.php:87
|
1885 |
+
msgid "starting from next time it is"
|
1886 |
+
msgstr "empezando desde la próxima hora son las"
|
1887 |
+
|
1888 |
+
#: addons/fixtime.php:77 addons/fixtime.php:87
|
1889 |
+
msgid "Enter in format HH:MM (e.g. 14:22)"
|
1890 |
+
msgstr "Ingrese formato HH:MM (Ej. 14:22)"
|
1891 |
+
|
1892 |
+
#: addons/multisite.php:103
|
1893 |
+
msgid "Multisite Install"
|
1894 |
+
msgstr "Instalaciones multisites"
|
1895 |
+
|
1896 |
+
#: addons/multisite.php:109
|
1897 |
+
msgid "You do not have sufficient permissions to access this page."
|
1898 |
+
msgstr "No tiene suficiente permiso accesar esta página"
|
1899 |
+
|
1900 |
+
#: addons/multisite.php:128
|
1901 |
+
msgid "You do not have permission to access this page."
|
1902 |
+
msgstr "No tiene permiso para entrar a esta página"
|
1903 |
+
|
1904 |
+
#: addons/multisite.php:180
|
1905 |
+
msgid "Must-use plugins"
|
1906 |
+
msgstr "Plugins Multi-uso"
|
1907 |
+
|
1908 |
+
#: addons/multisite.php:181
|
1909 |
+
msgid "Blog uploads"
|
1910 |
+
msgstr "Subir blogs"
|
1911 |
+
|
1912 |
+
#: addons/dropbox-folders.php:21
|
1913 |
+
msgid "Store at"
|
1914 |
+
msgstr "Almacenado en"
|
languages/updraftplus-hu_HU.po
CHANGED
@@ -452,16 +452,14 @@ msgid ""
|
|
452 |
"<em>will</em> be useless.</strong> Presently, only the database file is "
|
453 |
"encrypted. This is also the key used to decrypt backups from this admin "
|
454 |
"interface (so if you change it, then automatic decryption will not work "
|
455 |
-
"until you change it back).
|
456 |
-
"from inside the UpdraftPlus plugin directory to decrypt manually."
|
457 |
msgstr ""
|
458 |
"Ha ide beír karaktereket, titkosítva lesz a mentés (Rijndael). <strong>Kérem "
|
459 |
"külön jegyezze fel ezt, különben az <em>összes</em> mentése hasztalan lesz.</"
|
460 |
"strong> Jelenleg csak az adatbázis mentések kerülnek titkosításra. Ezzel a "
|
461 |
"kulccsal kerül kinyitásra minden mentés erről a felületről (szóval, ha "
|
462 |
"módosítja, akkor a titkosítás automatikus kinyitása nem fog működni, amíg "
|
463 |
-
"vissza nem változtatja).
|
464 |
-
"php program fájlt az UpdraftPlus bővítmény könyvtárban."
|
465 |
|
466 |
#: updraftplus.php:2403
|
467 |
msgid "Copying Your Backup To Remote Storage"
|
452 |
"<em>will</em> be useless.</strong> Presently, only the database file is "
|
453 |
"encrypted. This is also the key used to decrypt backups from this admin "
|
454 |
"interface (so if you change it, then automatic decryption will not work "
|
455 |
+
"until you change it back)."
|
|
|
456 |
msgstr ""
|
457 |
"Ha ide beír karaktereket, titkosítva lesz a mentés (Rijndael). <strong>Kérem "
|
458 |
"külön jegyezze fel ezt, különben az <em>összes</em> mentése hasztalan lesz.</"
|
459 |
"strong> Jelenleg csak az adatbázis mentések kerülnek titkosításra. Ezzel a "
|
460 |
"kulccsal kerül kinyitásra minden mentés erről a felületről (szóval, ha "
|
461 |
"módosítja, akkor a titkosítás automatikus kinyitása nem fog működni, amíg "
|
462 |
+
"vissza nem változtatja)."
|
|
|
463 |
|
464 |
#: updraftplus.php:2403
|
465 |
msgid "Copying Your Backup To Remote Storage"
|
languages/updraftplus.pot
CHANGED
@@ -2,15 +2,15 @@ msgid ""
|
|
2 |
msgstr ""
|
3 |
"Project-Id-Version: UpdraftPlus\n"
|
4 |
"Report-Msgid-Bugs-To: \n"
|
5 |
-
"POT-Creation-Date: 2013-
|
6 |
-
"PO-Revision-Date: 2013-
|
7 |
"Last-Translator: David Anderson <contact@updraftplus.com>\n"
|
8 |
"Language-Team: <contact@updraftplus.com>\n"
|
9 |
"Language: \n"
|
10 |
"MIME-Version: 1.0\n"
|
11 |
"Content-Type: text/plain; charset=UTF-8\n"
|
12 |
"Content-Transfer-Encoding: 8bit\n"
|
13 |
-
"X-Poedit-KeywordsList: _;gettext;gettext_noop;__;
|
14 |
"X-Poedit-Basepath: /home/david/MissionaryHosting/UpdraftPlus/svn/trunk\n"
|
15 |
"X-Poedit-SearchPath-0: .\n"
|
16 |
|
@@ -18,897 +18,1100 @@ msgstr ""
|
|
18 |
msgid "UpdraftPlus Backups"
|
19 |
msgstr ""
|
20 |
|
21 |
-
#: updraftplus.php:
|
22 |
-
|
|
|
|
|
|
|
|
|
23 |
msgstr ""
|
24 |
|
25 |
-
#: updraftplus.php:
|
26 |
-
msgid "
|
27 |
msgstr ""
|
28 |
|
29 |
-
#: updraftplus.php:
|
30 |
-
msgid "
|
31 |
msgstr ""
|
32 |
|
33 |
-
#: updraftplus.php:
|
34 |
-
msgid "
|
35 |
msgstr ""
|
36 |
|
37 |
-
#: updraftplus.php:
|
38 |
msgid "Plugins"
|
39 |
msgstr ""
|
40 |
|
41 |
-
#: updraftplus.php:
|
42 |
msgid "Themes"
|
43 |
msgstr ""
|
44 |
|
45 |
-
#: updraftplus.php:
|
46 |
msgid "Uploads"
|
47 |
msgstr ""
|
48 |
|
49 |
-
#: updraftplus.php:
|
50 |
msgid "Others"
|
51 |
msgstr ""
|
52 |
|
53 |
-
#: updraftplus.php:
|
54 |
msgid "Could not create files in the backup directory. Backup aborted - check your UpdraftPlus settings."
|
55 |
msgstr ""
|
56 |
|
57 |
-
#: updraftplus.php:
|
58 |
msgid "Encryption error occurred when encrypting database. Encryption aborted."
|
59 |
msgstr ""
|
60 |
|
61 |
-
#: updraftplus.php:
|
62 |
msgid "The backup apparently succeeded and is now complete"
|
63 |
msgstr ""
|
64 |
|
65 |
-
#: updraftplus.php:
|
66 |
msgid "The backup attempt has finished, apparently unsuccessfully"
|
67 |
msgstr ""
|
68 |
|
69 |
-
#: updraftplus.php:
|
70 |
msgid "The backup has not finished; a resumption is scheduled within 5 minutes"
|
71 |
msgstr ""
|
72 |
|
73 |
-
#: updraftplus.php:
|
74 |
msgid "Backed up"
|
75 |
msgstr ""
|
76 |
|
77 |
-
#: updraftplus.php:
|
78 |
msgid "WordPress backup is complete"
|
79 |
msgstr ""
|
80 |
|
81 |
-
#: updraftplus.php:
|
82 |
msgid "Backup contains"
|
83 |
msgstr ""
|
84 |
|
85 |
-
#: updraftplus.php:
|
86 |
msgid "Latest status"
|
87 |
msgstr ""
|
88 |
|
89 |
-
#: updraftplus.php:
|
90 |
-
#, php-format
|
91 |
-
msgid "Could not create %s zip. Consult the log file for more information."
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
#: updraftplus.php:1158
|
95 |
#, php-format
|
96 |
msgid "Backup directory (%s) is not writable, or does not exist."
|
97 |
msgstr ""
|
98 |
|
99 |
-
#: updraftplus.php:
|
100 |
-
msgid "Could not read the
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: updraftplus.php:
|
104 |
msgid "Could not save backup history because we have no backup array. Backup probably failed."
|
105 |
msgstr ""
|
106 |
|
107 |
-
#: updraftplus.php:
|
108 |
msgid "Could not open the backup file for writing"
|
109 |
msgstr ""
|
110 |
|
111 |
-
#: updraftplus.php:
|
112 |
#, php-format
|
113 |
msgid "Generated: %s"
|
114 |
msgstr ""
|
115 |
|
116 |
-
#: updraftplus.php:
|
117 |
#, php-format
|
118 |
msgid "Hostname: %s"
|
119 |
msgstr ""
|
120 |
|
121 |
-
#: updraftplus.php:
|
122 |
#, php-format
|
123 |
msgid "Database: %s"
|
124 |
msgstr ""
|
125 |
|
126 |
-
#: updraftplus.php:
|
127 |
msgid "The backup directory is not writable."
|
128 |
msgstr ""
|
129 |
|
130 |
-
#: updraftplus.php:
|
131 |
#, php-format
|
132 |
msgid "Table: %s"
|
133 |
msgstr ""
|
134 |
|
135 |
-
#: updraftplus.php:
|
136 |
#, php-format
|
137 |
msgid "Skipping non-WP table: %s"
|
138 |
msgstr ""
|
139 |
|
140 |
-
#: updraftplus.php:
|
141 |
#, php-format
|
142 |
msgid "Delete any existing table %s"
|
143 |
msgstr ""
|
144 |
|
145 |
-
#: updraftplus.php:
|
146 |
#, php-format
|
147 |
msgid "Table structure of table %s"
|
148 |
msgstr ""
|
149 |
|
150 |
-
#: updraftplus.php:
|
151 |
#, php-format
|
152 |
msgid "Error with SHOW CREATE TABLE for %s."
|
153 |
msgstr ""
|
154 |
|
155 |
-
#: updraftplus.php:
|
156 |
#, php-format
|
157 |
-
msgid "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
msgstr ""
|
159 |
|
160 |
-
#: updraftplus.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
#, php-format
|
162 |
-
msgid "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
msgstr ""
|
164 |
|
165 |
-
#:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
#, php-format
|
167 |
-
msgid "
|
168 |
msgstr ""
|
169 |
|
170 |
-
#:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
msgid "Nothing yet logged"
|
172 |
msgstr ""
|
173 |
|
174 |
-
#:
|
175 |
-
msgid "
|
176 |
msgstr ""
|
177 |
|
178 |
-
#:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
msgid "No local copy present."
|
180 |
msgstr ""
|
181 |
|
182 |
-
#:
|
183 |
-
msgid "
|
184 |
msgstr ""
|
185 |
|
186 |
-
#:
|
187 |
-
|
188 |
-
msgid "The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder"
|
189 |
msgstr ""
|
190 |
|
191 |
-
#:
|
192 |
-
msgid "
|
193 |
msgstr ""
|
194 |
|
195 |
-
#:
|
196 |
-
|
|
|
|
|
197 |
msgstr ""
|
198 |
|
199 |
-
#:
|
200 |
-
|
|
|
|
|
|
|
201 |
msgstr ""
|
202 |
|
203 |
-
#:
|
204 |
-
|
205 |
-
#: updraftplus.php:3072
|
206 |
-
msgid "Database"
|
207 |
msgstr ""
|
208 |
|
209 |
-
#:
|
210 |
-
msgid "
|
211 |
msgstr ""
|
212 |
|
213 |
-
#:
|
214 |
-
msgid "
|
215 |
msgstr ""
|
216 |
|
217 |
-
#:
|
218 |
-
msgid "
|
219 |
msgstr ""
|
220 |
|
221 |
-
#:
|
222 |
-
msgid "
|
223 |
msgstr ""
|
224 |
|
225 |
-
#:
|
226 |
-
msgid "
|
227 |
msgstr ""
|
228 |
|
229 |
-
#:
|
230 |
-
msgid "
|
231 |
msgstr ""
|
232 |
|
233 |
-
#:
|
234 |
-
|
235 |
-
msgid "Could not find one of the files for restoration"
|
236 |
msgstr ""
|
237 |
|
238 |
-
#:
|
239 |
-
msgid "
|
240 |
msgstr ""
|
241 |
|
242 |
-
#:
|
243 |
-
msgid "
|
244 |
msgstr ""
|
245 |
|
246 |
-
#:
|
247 |
-
msgid "
|
248 |
msgstr ""
|
249 |
|
250 |
-
#:
|
251 |
-
msgid "
|
252 |
msgstr ""
|
253 |
|
254 |
-
#:
|
255 |
-
msgid "
|
256 |
msgstr ""
|
257 |
|
258 |
-
#:
|
259 |
-
msgid "
|
260 |
msgstr ""
|
261 |
|
262 |
-
#:
|
263 |
-
msgid "
|
264 |
msgstr ""
|
265 |
|
266 |
-
#:
|
267 |
-
msgid "
|
268 |
msgstr ""
|
269 |
|
270 |
-
#:
|
271 |
-
msgid "
|
272 |
msgstr ""
|
273 |
|
274 |
-
#:
|
275 |
-
msgid "
|
276 |
msgstr ""
|
277 |
|
278 |
-
#:
|
279 |
-
msgid "
|
280 |
msgstr ""
|
281 |
|
282 |
-
#:
|
283 |
-
msgid "
|
284 |
msgstr ""
|
285 |
|
286 |
-
#:
|
287 |
-
msgid "
|
288 |
msgstr ""
|
289 |
|
290 |
-
#:
|
291 |
-
msgid "
|
292 |
msgstr ""
|
293 |
|
294 |
-
#:
|
295 |
-
msgid "
|
296 |
msgstr ""
|
297 |
|
298 |
-
#:
|
299 |
-
msgid "
|
300 |
msgstr ""
|
301 |
|
302 |
-
#:
|
303 |
-
msgid "
|
304 |
msgstr ""
|
305 |
|
306 |
-
#:
|
307 |
-
msgid "
|
308 |
msgstr ""
|
309 |
|
310 |
-
#:
|
311 |
-
msgid "
|
312 |
msgstr ""
|
313 |
|
314 |
-
#:
|
315 |
-
msgid "
|
316 |
msgstr ""
|
317 |
|
318 |
-
#:
|
319 |
-
#:
|
320 |
-
msgid "
|
321 |
msgstr ""
|
322 |
|
323 |
-
#:
|
324 |
-
msgid "
|
325 |
msgstr ""
|
326 |
|
327 |
-
#:
|
328 |
-
msgid "
|
329 |
msgstr ""
|
330 |
|
331 |
-
#:
|
332 |
-
msgid "
|
333 |
msgstr ""
|
334 |
|
335 |
-
#:
|
336 |
-
|
|
|
|
|
|
|
|
|
337 |
msgstr ""
|
338 |
|
339 |
-
#:
|
340 |
-
msgid "
|
341 |
msgstr ""
|
342 |
|
343 |
-
#:
|
344 |
-
msgid "
|
345 |
msgstr ""
|
346 |
|
347 |
-
#:
|
348 |
-
|
|
|
349 |
msgstr ""
|
350 |
|
351 |
-
#:
|
352 |
-
|
|
|
|
|
353 |
msgstr ""
|
354 |
|
355 |
-
#:
|
356 |
-
msgid "
|
357 |
msgstr ""
|
358 |
|
359 |
-
#:
|
360 |
-
msgid "
|
361 |
msgstr ""
|
362 |
|
363 |
-
#:
|
364 |
-
msgid "
|
365 |
msgstr ""
|
366 |
|
367 |
-
#:
|
368 |
-
msgid "
|
369 |
msgstr ""
|
370 |
|
371 |
-
#:
|
372 |
-
msgid "
|
373 |
msgstr ""
|
374 |
|
375 |
-
#:
|
376 |
-
|
|
|
377 |
msgstr ""
|
378 |
|
379 |
-
#:
|
380 |
-
msgid "
|
381 |
msgstr ""
|
382 |
|
383 |
-
#:
|
384 |
-
|
385 |
-
#: updraftplus.php:3109
|
386 |
-
msgid "Restore"
|
387 |
msgstr ""
|
388 |
|
389 |
-
#:
|
390 |
-
|
391 |
-
msgid "Cancel"
|
392 |
msgstr ""
|
393 |
|
394 |
-
#:
|
395 |
-
|
396 |
-
msgid "Backup Now"
|
397 |
msgstr ""
|
398 |
|
399 |
-
#:
|
400 |
-
msgid "
|
401 |
msgstr ""
|
402 |
|
403 |
-
#:
|
404 |
-
msgid "
|
405 |
msgstr ""
|
406 |
|
407 |
-
#:
|
408 |
-
msgid "
|
409 |
msgstr ""
|
410 |
|
411 |
-
#:
|
412 |
-
msgid "
|
413 |
msgstr ""
|
414 |
|
415 |
-
#:
|
416 |
-
msgid "
|
417 |
msgstr ""
|
418 |
|
419 |
-
#:
|
420 |
-
msgid "
|
421 |
msgstr ""
|
422 |
|
423 |
-
#:
|
424 |
-
msgid "
|
425 |
msgstr ""
|
426 |
|
427 |
-
#:
|
428 |
-
msgid "
|
429 |
msgstr ""
|
430 |
|
431 |
-
#:
|
432 |
-
msgid "
|
433 |
msgstr ""
|
434 |
|
435 |
-
#:
|
436 |
-
msgid "
|
437 |
msgstr ""
|
438 |
|
439 |
-
#:
|
440 |
-
msgid "
|
441 |
msgstr ""
|
442 |
|
443 |
-
#:
|
444 |
-
msgid "
|
445 |
msgstr ""
|
446 |
|
447 |
-
#:
|
448 |
-
|
|
|
449 |
msgstr ""
|
450 |
|
451 |
-
#:
|
452 |
-
msgid "
|
453 |
msgstr ""
|
454 |
|
455 |
-
#:
|
456 |
-
|
|
|
457 |
msgstr ""
|
458 |
|
459 |
-
#:
|
460 |
-
msgid "
|
461 |
msgstr ""
|
462 |
|
463 |
-
#:
|
464 |
-
msgid "
|
465 |
msgstr ""
|
466 |
|
467 |
-
#:
|
468 |
-
msgid "Download
|
469 |
msgstr ""
|
470 |
|
471 |
-
#:
|
472 |
-
msgid "
|
473 |
msgstr ""
|
474 |
|
475 |
-
#:
|
476 |
-
msgid "Restore
|
477 |
msgstr ""
|
478 |
|
479 |
-
#:
|
480 |
-
|
481 |
-
#: updraftplus.php:2704
|
482 |
-
msgid "Actions"
|
483 |
msgstr ""
|
484 |
|
485 |
-
#:
|
486 |
-
|
487 |
-
#: updraftplus.php:2688
|
488 |
-
#: updraftplus.php:2704
|
489 |
-
msgid "Return to UpdraftPlus Configuration"
|
490 |
msgstr ""
|
491 |
|
492 |
-
#:
|
493 |
-
msgid "
|
494 |
msgstr ""
|
495 |
|
496 |
-
#:
|
497 |
-
msgid "
|
498 |
msgstr ""
|
499 |
|
500 |
-
#:
|
501 |
-
msgid "
|
502 |
msgstr ""
|
503 |
|
504 |
-
#:
|
505 |
-
msgid "Backup
|
506 |
msgstr ""
|
507 |
|
508 |
-
#:
|
509 |
-
msgid "
|
510 |
msgstr ""
|
511 |
|
512 |
-
#:
|
513 |
-
msgid "
|
514 |
msgstr ""
|
515 |
|
516 |
-
#:
|
517 |
-
msgid "
|
518 |
msgstr ""
|
519 |
|
520 |
-
#:
|
521 |
-
msgid "
|
522 |
msgstr ""
|
523 |
|
524 |
-
#:
|
525 |
-
msgid "
|
526 |
msgstr ""
|
527 |
|
528 |
-
#:
|
529 |
-
msgid "
|
530 |
msgstr ""
|
531 |
|
532 |
-
#:
|
533 |
-
msgid "
|
534 |
msgstr ""
|
535 |
|
536 |
-
#:
|
537 |
-
msgid "
|
538 |
msgstr ""
|
539 |
|
540 |
-
#:
|
541 |
-
msgid "
|
542 |
msgstr ""
|
543 |
|
544 |
-
#:
|
545 |
-
msgid "
|
546 |
msgstr ""
|
547 |
|
548 |
-
#:
|
549 |
-
msgid "
|
550 |
msgstr ""
|
551 |
|
552 |
-
#:
|
553 |
-
msgid "
|
554 |
msgstr ""
|
555 |
|
556 |
-
#:
|
557 |
-
msgid "
|
558 |
msgstr ""
|
559 |
|
560 |
-
#:
|
561 |
-
msgid "
|
562 |
msgstr ""
|
563 |
|
564 |
-
#:
|
565 |
-
msgid "
|
566 |
msgstr ""
|
567 |
|
568 |
-
#:
|
569 |
-
msgid "
|
570 |
msgstr ""
|
571 |
|
572 |
-
#:
|
573 |
-
msgid "
|
574 |
msgstr ""
|
575 |
|
576 |
-
#:
|
577 |
-
msgid "
|
578 |
msgstr ""
|
579 |
|
580 |
-
#:
|
581 |
-
msgid "
|
582 |
msgstr ""
|
583 |
|
584 |
-
#:
|
585 |
-
msgid "
|
586 |
msgstr ""
|
587 |
|
588 |
-
#:
|
589 |
-
msgid "
|
590 |
msgstr ""
|
591 |
|
592 |
-
#:
|
593 |
-
msgid "
|
594 |
msgstr ""
|
595 |
|
596 |
-
#:
|
597 |
-
msgid "
|
598 |
msgstr ""
|
599 |
|
600 |
-
#:
|
601 |
-
msgid "
|
602 |
msgstr ""
|
603 |
|
604 |
-
#:
|
605 |
-
msgid "
|
606 |
msgstr ""
|
607 |
|
608 |
-
#:
|
609 |
-
|
610 |
-
msgid "Nothing currently scheduled"
|
611 |
msgstr ""
|
612 |
|
613 |
-
#:
|
614 |
-
msgid "
|
615 |
msgstr ""
|
616 |
|
617 |
-
#:
|
618 |
-
msgid "
|
619 |
msgstr ""
|
620 |
|
621 |
-
#:
|
622 |
-
msgid "
|
623 |
msgstr ""
|
624 |
|
625 |
-
#:
|
626 |
-
msgid "
|
627 |
msgstr ""
|
628 |
|
629 |
-
#:
|
630 |
-
msgid "
|
631 |
msgstr ""
|
632 |
|
633 |
-
#:
|
634 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
635 |
msgstr ""
|
636 |
|
637 |
-
#:
|
638 |
-
msgid "
|
639 |
msgstr ""
|
640 |
|
641 |
-
#:
|
642 |
-
msgid "
|
643 |
msgstr ""
|
644 |
|
645 |
-
#:
|
646 |
-
msgid "
|
647 |
msgstr ""
|
648 |
|
649 |
-
#:
|
650 |
-
|
651 |
-
msgid "%d set(s) available"
|
652 |
msgstr ""
|
653 |
|
654 |
-
#:
|
655 |
-
msgid "
|
656 |
msgstr ""
|
657 |
|
658 |
-
#:
|
659 |
-
msgid "
|
660 |
msgstr ""
|
661 |
|
662 |
-
#:
|
663 |
-
msgid "
|
664 |
msgstr ""
|
665 |
|
666 |
-
#:
|
667 |
-
msgid "
|
668 |
msgstr ""
|
669 |
|
670 |
-
#:
|
671 |
-
msgid "
|
672 |
msgstr ""
|
673 |
|
674 |
-
#:
|
675 |
-
msgid "
|
676 |
msgstr ""
|
677 |
|
678 |
-
#:
|
679 |
-
msgid "
|
680 |
msgstr ""
|
681 |
|
682 |
-
#:
|
683 |
-
msgid "
|
684 |
msgstr ""
|
685 |
|
686 |
-
#:
|
687 |
-
msgid "
|
688 |
msgstr ""
|
689 |
|
690 |
-
#:
|
691 |
-
msgid "
|
692 |
msgstr ""
|
693 |
|
694 |
-
#:
|
695 |
-
msgid "
|
696 |
msgstr ""
|
697 |
|
698 |
-
#:
|
699 |
-
msgid "
|
700 |
msgstr ""
|
701 |
|
702 |
-
#:
|
703 |
-
msgid "
|
704 |
msgstr ""
|
705 |
|
706 |
-
#:
|
707 |
-
msgid "UpdraftPlus
|
708 |
msgstr ""
|
709 |
|
710 |
-
#:
|
711 |
-
msgid "
|
712 |
msgstr ""
|
713 |
|
714 |
-
#:
|
715 |
-
msgid "
|
716 |
msgstr ""
|
717 |
|
718 |
-
#:
|
719 |
-
msgid "
|
720 |
msgstr ""
|
721 |
|
722 |
-
#:
|
723 |
-
msgid "
|
724 |
msgstr ""
|
725 |
|
726 |
-
#:
|
727 |
-
|
|
|
728 |
msgstr ""
|
729 |
|
730 |
-
#:
|
731 |
-
|
|
|
732 |
msgstr ""
|
733 |
|
734 |
-
#:
|
735 |
-
|
|
|
736 |
msgstr ""
|
737 |
|
738 |
-
#:
|
739 |
-
|
|
|
740 |
msgstr ""
|
741 |
|
742 |
-
#:
|
743 |
-
|
|
|
744 |
msgstr ""
|
745 |
|
746 |
-
#:
|
747 |
-
msgid "
|
748 |
msgstr ""
|
749 |
|
750 |
-
#:
|
751 |
-
|
|
|
752 |
msgstr ""
|
753 |
|
754 |
-
#:
|
755 |
-
msgid "
|
756 |
msgstr ""
|
757 |
|
758 |
-
#:
|
759 |
-
msgid "
|
760 |
msgstr ""
|
761 |
|
762 |
-
#:
|
763 |
-
msgid "
|
764 |
msgstr ""
|
765 |
|
766 |
-
#:
|
767 |
-
msgid "
|
768 |
msgstr ""
|
769 |
|
770 |
-
#:
|
771 |
-
msgid "
|
772 |
msgstr ""
|
773 |
|
774 |
-
#:
|
775 |
-
msgid "
|
776 |
msgstr ""
|
777 |
|
778 |
-
#:
|
779 |
-
msgid "
|
780 |
msgstr ""
|
781 |
|
782 |
-
#:
|
783 |
-
msgid "
|
784 |
msgstr ""
|
785 |
|
786 |
-
#:
|
787 |
-
msgid "
|
788 |
msgstr ""
|
789 |
|
790 |
-
#:
|
791 |
-
msgid "The
|
792 |
msgstr ""
|
793 |
|
794 |
-
#:
|
795 |
-
msgid "
|
796 |
msgstr ""
|
797 |
|
798 |
-
#:
|
799 |
-
|
|
|
800 |
msgstr ""
|
801 |
|
802 |
-
#:
|
803 |
-
msgid "
|
804 |
msgstr ""
|
805 |
|
806 |
-
#:
|
807 |
-
msgid "
|
808 |
msgstr ""
|
809 |
|
810 |
-
#:
|
811 |
-
msgid "
|
812 |
msgstr ""
|
813 |
|
814 |
-
#:
|
815 |
-
msgid "
|
816 |
msgstr ""
|
817 |
|
818 |
-
#:
|
819 |
-
msgid "
|
820 |
msgstr ""
|
821 |
|
822 |
-
#:
|
823 |
-
msgid "
|
824 |
msgstr ""
|
825 |
|
826 |
-
#:
|
827 |
-
msgid "
|
828 |
msgstr ""
|
829 |
|
830 |
-
#:
|
831 |
-
|
832 |
-
msgid "(No %s)"
|
833 |
msgstr ""
|
834 |
|
835 |
-
#:
|
836 |
-
msgid "
|
837 |
msgstr ""
|
838 |
|
839 |
-
#:
|
840 |
-
msgid "
|
841 |
msgstr ""
|
842 |
|
843 |
-
#:
|
844 |
-
|
845 |
-
msgid "Warning"
|
846 |
msgstr ""
|
847 |
|
848 |
-
#:
|
849 |
-
|
850 |
-
msgid "You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue."
|
851 |
msgstr ""
|
852 |
|
853 |
-
#:
|
854 |
-
|
855 |
-
msgid "UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress."
|
856 |
msgstr ""
|
857 |
|
858 |
-
#:
|
859 |
-
|
860 |
-
#: updraftplus.php:3150
|
861 |
-
msgid "UpdraftPlus notice:"
|
862 |
msgstr ""
|
863 |
|
864 |
-
#:
|
865 |
-
msgid "
|
866 |
msgstr ""
|
867 |
|
868 |
-
#:
|
869 |
-
|
870 |
-
#, php-format
|
871 |
-
msgid "Click here to authenticate your %s account (you will not be able to back up to %s without it)."
|
872 |
msgstr ""
|
873 |
|
874 |
-
#:
|
875 |
-
msgid "
|
876 |
msgstr ""
|
877 |
|
878 |
-
#: includes/updraft-restorer.php:
|
879 |
-
msgid "
|
880 |
msgstr ""
|
881 |
|
882 |
-
#: includes/updraft-restorer.php:
|
883 |
-
msgid "
|
884 |
msgstr ""
|
885 |
|
886 |
-
#: includes/updraft-restorer.php:
|
887 |
-
msgid "
|
888 |
msgstr ""
|
889 |
|
890 |
-
#: includes/updraft-restorer.php:
|
891 |
-
msgid "
|
892 |
msgstr ""
|
893 |
|
894 |
-
#: includes/updraft-restorer.php:
|
895 |
-
|
|
|
896 |
msgstr ""
|
897 |
|
898 |
-
#: includes/updraft-restorer.php:
|
899 |
-
msgid "
|
900 |
msgstr ""
|
901 |
|
902 |
-
#: includes/updraft-restorer.php:
|
903 |
-
msgid "
|
904 |
msgstr ""
|
905 |
|
906 |
-
#: includes/updraft-restorer.php:
|
907 |
-
|
|
|
908 |
msgstr ""
|
909 |
|
910 |
-
#: includes/updraft-restorer.php:
|
911 |
-
|
|
|
912 |
msgstr ""
|
913 |
|
914 |
#: methods/webdav.php:13
|
@@ -932,143 +1135,261 @@ msgstr ""
|
|
932 |
msgid "follow this link to get it"
|
933 |
msgstr ""
|
934 |
|
935 |
-
#: methods/googledrive.php:
|
936 |
-
#: methods/
|
937 |
-
#: methods/dropbox.php:293
|
938 |
-
#: addons/webdav.php:292
|
939 |
msgid "Success"
|
940 |
msgstr ""
|
941 |
|
942 |
-
#: methods/googledrive.php:
|
943 |
-
#: methods/dropbox.php:293
|
944 |
#, php-format
|
945 |
msgid "you have authenticated your %s account"
|
946 |
msgstr ""
|
947 |
|
948 |
-
#: methods/googledrive.php:
|
949 |
-
#: methods/googledrive.php:
|
950 |
-
#: methods/googledrive.php:
|
951 |
-
#: methods/googledrive.php:
|
952 |
-
#: methods/googledrive.php:
|
953 |
-
#: methods/googledrive.php:
|
954 |
msgid "Google Drive"
|
955 |
msgstr ""
|
956 |
|
957 |
-
#: methods/googledrive.php:
|
958 |
msgid "No refresh token was received from Google. This often means that you entered your client secret wrongly, or that you have not yet re-authenticated (below) since correcting it. Re-check it, then follow the link to authenticate again. Finally, if that does not work, then use expert mode to wipe all your settings, create a new Google client ID/secret, and start again."
|
959 |
msgstr ""
|
960 |
|
961 |
-
#: methods/googledrive.php:
|
962 |
msgid "Authorization failed"
|
963 |
msgstr ""
|
964 |
|
965 |
-
#: methods/googledrive.php:
|
966 |
msgid "Have not yet obtained an access token from Google - you need to authorise or re-authorise your connection to Google Drive."
|
967 |
msgstr ""
|
968 |
|
969 |
-
#: methods/googledrive.php:
|
970 |
-
#: methods/googledrive.php:
|
971 |
msgid "Have not yet obtained an access token from Google (has the user authorised?)"
|
972 |
msgstr ""
|
973 |
|
974 |
-
#: methods/googledrive.php:
|
975 |
-
#: addons/webdav.php:57
|
976 |
#, php-format
|
977 |
msgid "Failed to upload to %s"
|
978 |
msgstr ""
|
979 |
|
980 |
-
#: methods/googledrive.php:
|
981 |
-
#: addons/webdav.php:57
|
982 |
msgid "Error"
|
983 |
msgstr ""
|
984 |
|
985 |
-
#: methods/googledrive.php:
|
986 |
msgid "An error occurred during GoogleDrive upload (see log for more details)"
|
987 |
msgstr ""
|
988 |
|
989 |
-
#: methods/googledrive.php:
|
990 |
#, php-format
|
991 |
msgid "Google Drive error: %d: could not download: could not find a record of the Google Drive file ID for this file"
|
992 |
msgstr ""
|
993 |
|
994 |
-
#: methods/googledrive.php:
|
995 |
#, php-format
|
996 |
msgid "Could not find %s in order to download it"
|
997 |
msgstr ""
|
998 |
|
999 |
-
#: methods/googledrive.php:
|
1000 |
msgid "Google Drive "
|
1001 |
msgstr ""
|
1002 |
|
1003 |
-
#: methods/googledrive.php:
|
1004 |
msgid "error: zero-size file was downloaded"
|
1005 |
msgstr ""
|
1006 |
|
1007 |
-
#: methods/googledrive.php:
|
1008 |
msgid "Account is not authorized."
|
1009 |
msgstr ""
|
1010 |
|
1011 |
-
#: methods/googledrive.php:
|
1012 |
-
#: methods/
|
1013 |
-
#: methods/dropbox.php:217
|
1014 |
-
#: methods/ftp.php:109
|
1015 |
-
#: addons/webdav.php:231
|
1016 |
#, php-format
|
1017 |
msgid "%s is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your blog is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts."
|
1018 |
msgstr ""
|
1019 |
|
1020 |
-
#: methods/googledrive.php:
|
1021 |
msgid "For longer help, including screenshots, follow this link. The description below is sufficient for more expert users."
|
1022 |
msgstr ""
|
1023 |
|
1024 |
-
#: methods/googledrive.php:
|
1025 |
msgid "Follow this link to your Google API Console, and there create a Client ID in the API Access section."
|
1026 |
msgstr ""
|
1027 |
|
1028 |
-
#: methods/googledrive.php:
|
1029 |
msgid "Select 'Web Application' as the application type."
|
1030 |
msgstr ""
|
1031 |
|
1032 |
-
#: methods/googledrive.php:
|
1033 |
msgid "You must add the following as the authorised redirect URI (under \"More Options\") when asked"
|
1034 |
msgstr ""
|
1035 |
|
1036 |
-
#: methods/googledrive.php:
|
1037 |
msgid "N.B. If you install UpdraftPlus on several WordPress sites, then you cannot re-use your client ID; you must create a new one from your Google API console for each blog."
|
1038 |
msgstr ""
|
1039 |
|
1040 |
-
#: methods/googledrive.php:
|
1041 |
msgid "You do not have the SimpleXMLElement installed. Google Drive backups will <b>not</b> work until you do."
|
1042 |
msgstr ""
|
1043 |
|
1044 |
-
#: methods/googledrive.php:
|
1045 |
msgid "Client ID"
|
1046 |
msgstr ""
|
1047 |
|
1048 |
-
#: methods/googledrive.php:
|
1049 |
msgid "If Google later shows you the message \"invalid_client\", then you did not enter a valid client ID here."
|
1050 |
msgstr ""
|
1051 |
|
1052 |
-
#: methods/googledrive.php:
|
1053 |
msgid "Client Secret"
|
1054 |
msgstr ""
|
1055 |
|
1056 |
-
#: methods/googledrive.php:
|
1057 |
msgid "Folder ID"
|
1058 |
msgstr ""
|
1059 |
|
1060 |
-
#: methods/googledrive.php:
|
1061 |
msgid "<strong>This is NOT a folder name</strong>. To get a folder's ID navigate to that folder in Google Drive in your web browser and copy the ID from your browser's address bar. It is the part that comes after <kbd>#folders/.</kbd> Leave empty to use your root folder)"
|
1062 |
msgstr ""
|
1063 |
|
1064 |
-
#: methods/googledrive.php:
|
1065 |
msgid "Authenticate with Google"
|
1066 |
msgstr ""
|
1067 |
|
1068 |
-
#: methods/googledrive.php:
|
1069 |
msgid "<strong>After</strong> you have saved your settings (by clicking 'Save Changes' below), then come back here once and click this link to complete authentication with Google."
|
1070 |
msgstr ""
|
1071 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1072 |
#: methods/email.php:15
|
1073 |
msgid "WordPress Backup"
|
1074 |
msgstr ""
|
@@ -1089,109 +1410,100 @@ msgstr ""
|
|
1089 |
msgid "The email address entered above will be used. If choosing \"E-Mail\", then <strong>be aware</strong> that mail servers tend to have size limits; typically around 10-20Mb; backups larger than any limits will not arrive. If you really need a large backup via email, then you could fund a new feature (to break the backup set into configurable-size pieces) - but the demand has not yet existed for such a feature."
|
1090 |
msgstr ""
|
1091 |
|
1092 |
-
#: methods/s3.php:
|
1093 |
-
#, php-format
|
1094 |
-
msgid "%s Error: Failed to upload"
|
1095 |
-
msgstr ""
|
1096 |
-
|
1097 |
-
#: methods/s3.php:98
|
1098 |
msgid "S3 upload: getting uploadID for multipart upload failed - see log file for more details"
|
1099 |
msgstr ""
|
1100 |
|
1101 |
-
#: methods/s3.php:
|
1102 |
#, php-format
|
1103 |
msgid "S3 chunk %s: upload failed"
|
1104 |
msgstr ""
|
1105 |
|
1106 |
-
#: methods/s3.php:
|
1107 |
#, php-format
|
1108 |
msgid "S3 upload (%s): re-assembly failed (see log for more details)"
|
1109 |
msgstr ""
|
1110 |
|
1111 |
-
#: methods/s3.php:
|
1112 |
#, php-format
|
1113 |
msgid "S3 re-assembly error (%s): (see log file for more)"
|
1114 |
msgstr ""
|
1115 |
|
1116 |
-
#: methods/s3.php:
|
1117 |
#, php-format
|
1118 |
msgid "S3 Error: Failed to create bucket %s. Check your permissions and credentials."
|
1119 |
msgstr ""
|
1120 |
|
1121 |
-
#: methods/s3.php:
|
1122 |
#, php-format
|
1123 |
msgid "S3 Error: Failed to download %s. Check your permissions and credentials."
|
1124 |
msgstr ""
|
1125 |
|
1126 |
-
#: methods/s3.php:
|
1127 |
#, php-format
|
1128 |
msgid "S3 Error: Failed to access bucket %s. Check your permissions and credentials."
|
1129 |
msgstr ""
|
1130 |
|
1131 |
-
#: methods/s3.php:
|
1132 |
msgid "Get your access key and secret key <a href=\"http://aws.amazon.com/console/\">from your AWS console</a>, then pick a (globally unique - all Amazon S3 users) bucket name (letters and numbers) (and optionally a path) to use for storage. This bucket will be created for you if it does not already exist."
|
1133 |
msgstr ""
|
1134 |
|
1135 |
-
#: methods/s3.php:
|
|
|
|
|
|
|
|
|
1136 |
msgid "S3 access key"
|
1137 |
msgstr ""
|
1138 |
|
1139 |
-
#: methods/s3.php:
|
1140 |
msgid "S3 secret key"
|
1141 |
msgstr ""
|
1142 |
|
1143 |
-
#: methods/s3.php:
|
1144 |
msgid "S3 location"
|
1145 |
msgstr ""
|
1146 |
|
1147 |
-
#: methods/s3.php:
|
1148 |
-
#: methods/ftp.php:135
|
1149 |
-
#: addons/webdav.php:244
|
1150 |
-
#, php-format
|
1151 |
-
msgid "Test %s Settings"
|
1152 |
-
msgstr ""
|
1153 |
-
|
1154 |
-
#: methods/s3.php:275
|
1155 |
-
#: methods/s3.php:279
|
1156 |
-
#: methods/ftp.php:152
|
1157 |
-
#: methods/ftp.php:156
|
1158 |
-
#: addons/webdav.php:272
|
1159 |
-
#, php-format
|
1160 |
-
msgid "Failure: No %s was given."
|
1161 |
-
msgstr ""
|
1162 |
-
|
1163 |
-
#: methods/s3.php:275
|
1164 |
-
msgid "API key"
|
1165 |
-
msgstr ""
|
1166 |
-
|
1167 |
-
#: methods/s3.php:279
|
1168 |
msgid "API secret"
|
1169 |
msgstr ""
|
1170 |
|
1171 |
-
#: methods/s3.php:
|
1172 |
msgid "Failure: No bucket details were given."
|
1173 |
msgstr ""
|
1174 |
|
1175 |
-
#: methods/s3.php:
|
1176 |
msgid "Amazon region"
|
1177 |
msgstr ""
|
1178 |
|
1179 |
-
#: methods/s3.php:
|
1180 |
msgid "Failure: We could not successfully access or create such a bucket. Please check your access credentials, and if those are correct then try another bucket name (as another S3 user may already have taken your name)."
|
1181 |
msgstr ""
|
1182 |
|
1183 |
-
#: methods/s3.php:
|
|
|
1184 |
msgid "Failure"
|
1185 |
msgstr ""
|
1186 |
|
1187 |
-
#: methods/s3.php:
|
|
|
1188 |
msgid "We successfully accessed the bucket, but the attempt to create a file in it failed."
|
1189 |
msgstr ""
|
1190 |
|
1191 |
-
#: methods/s3.php:
|
1192 |
msgid "We accessed the bucket, and were able to create files within it."
|
1193 |
msgstr ""
|
1194 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1195 |
#: methods/dropbox.php:35
|
1196 |
#: methods/dropbox.php:167
|
1197 |
msgid "You do not appear to be authenticated with Dropbox"
|
@@ -1232,86 +1544,79 @@ msgstr ""
|
|
1232 |
msgid "<strong>After</strong> you have saved your settings (by clicking 'Save Changes' below), then come back here once and click this link to complete authentication with Dropbox."
|
1233 |
msgstr ""
|
1234 |
|
1235 |
-
#: methods/dropbox.php:
|
1236 |
-
msgid "Your web server's PHP installation does not included a required module (MCrypt). Please contact your web hosting provider's support. UpdraftPlus's Dropbox module <strong>requires</strong> MCrypt. Please do not file any support requests; there is no alternative."
|
1237 |
-
msgstr ""
|
1238 |
-
|
1239 |
-
#: methods/dropbox.php:243
|
1240 |
-
msgid "Your web server's PHP installation does not included a required module (Curl). Please contact your web hosting provider's support. UpdraftPlus's Dropbox module <strong>requires</strong> Curl. Your only options to get this working are 1) Install/enable curl or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this."
|
1241 |
-
msgstr ""
|
1242 |
-
|
1243 |
-
#: methods/dropbox.php:296
|
1244 |
msgid "though part of the returned information was not as expected - your mileage may vary"
|
1245 |
msgstr ""
|
1246 |
|
1247 |
-
#: methods/dropbox.php:
|
1248 |
#, php-format
|
1249 |
msgid "Your %s account name"
|
1250 |
msgstr ""
|
1251 |
|
1252 |
-
#: methods/ftp.php:
|
1253 |
-
#: methods/ftp.php:
|
1254 |
msgid "FTP login failure"
|
1255 |
msgstr ""
|
1256 |
|
1257 |
-
#: methods/ftp.php:
|
1258 |
msgid "FTP upload failed"
|
1259 |
msgstr ""
|
1260 |
|
1261 |
-
#: methods/ftp.php:
|
1262 |
msgid "Settings test result"
|
1263 |
msgstr ""
|
1264 |
|
1265 |
-
#: methods/ftp.php:
|
1266 |
msgid "Only non-encrypted FTP is supported by regular UpdraftPlus."
|
1267 |
msgstr ""
|
1268 |
|
1269 |
-
#: methods/ftp.php:
|
1270 |
msgid "If you want encryption (e.g. you are storing sensitive business data), then an add-on is available."
|
1271 |
msgstr ""
|
1272 |
|
1273 |
-
#: methods/ftp.php:
|
1274 |
msgid "FTP Server"
|
1275 |
msgstr ""
|
1276 |
|
1277 |
-
#: methods/ftp.php:
|
1278 |
msgid "FTP Login"
|
1279 |
msgstr ""
|
1280 |
|
1281 |
-
#: methods/ftp.php:
|
1282 |
msgid "FTP Password"
|
1283 |
msgstr ""
|
1284 |
|
1285 |
-
#: methods/ftp.php:
|
1286 |
msgid "Remote Path"
|
1287 |
msgstr ""
|
1288 |
|
1289 |
-
#: methods/ftp.php:
|
1290 |
msgid "Needs to already exist"
|
1291 |
msgstr ""
|
1292 |
|
1293 |
-
#: methods/ftp.php:
|
1294 |
msgid "Failure: No server details were given."
|
1295 |
msgstr ""
|
1296 |
|
1297 |
-
#: methods/ftp.php:
|
1298 |
msgid "Failure: we did not successfully log in with those credentials."
|
1299 |
msgstr ""
|
1300 |
|
1301 |
-
#: methods/ftp.php:
|
1302 |
msgid "Failure: an unexpected internal UpdraftPlus error occurred when testing the credentials - please contact the developer"
|
1303 |
msgstr ""
|
1304 |
|
1305 |
-
#: methods/ftp.php:
|
1306 |
msgid "Success: we successfully logged in, and confirmed our ability to create a file in the given directory (login type:"
|
1307 |
msgstr ""
|
1308 |
|
1309 |
-
#: methods/ftp.php:
|
1310 |
msgid "Failure: we successfully logged in, but were not able to create a file in the given directory."
|
1311 |
msgstr ""
|
1312 |
|
1313 |
#: addons/webdav.php:40
|
1314 |
#: addons/webdav.php:170
|
|
|
1315 |
#, php-format
|
1316 |
msgid "No %s settings were found"
|
1317 |
msgstr ""
|
@@ -1328,10 +1633,6 @@ msgstr ""
|
|
1328 |
msgid "WebDAV Error"
|
1329 |
msgstr ""
|
1330 |
|
1331 |
-
#: addons/webdav.php:182
|
1332 |
-
msgid "Error opening local file: Failed to download"
|
1333 |
-
msgstr ""
|
1334 |
-
|
1335 |
#: addons/webdav.php:188
|
1336 |
msgid "Error opening remote file: Failed to download"
|
1337 |
msgstr ""
|
@@ -1350,6 +1651,7 @@ msgid "Enter a complete URL, beginning with webdav:// or webdavs:// and includin
|
|
1350 |
msgstr ""
|
1351 |
|
1352 |
#: addons/webdav.php:281
|
|
|
1353 |
msgid "Failed"
|
1354 |
msgstr ""
|
1355 |
|
@@ -1357,8 +1659,29 @@ msgstr ""
|
|
1357 |
msgid "Failed: We were not able to place a file in that directory - please check your credentials."
|
1358 |
msgstr ""
|
1359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1360 |
#: addons/sftp.php:23
|
1361 |
-
msgid "
|
1362 |
msgstr ""
|
1363 |
|
1364 |
#: addons/sftp.php:30
|
@@ -1377,7 +1700,7 @@ msgid "SFTP user setting"
|
|
1377 |
msgstr ""
|
1378 |
|
1379 |
#: addons/sftp.php:32
|
1380 |
-
msgid "SFTP
|
1381 |
msgstr ""
|
1382 |
|
1383 |
#: addons/sftp.php:50
|
@@ -1402,10 +1725,6 @@ msgstr ""
|
|
1402 |
msgid "Port"
|
1403 |
msgstr ""
|
1404 |
|
1405 |
-
#: addons/sftp.php:191
|
1406 |
-
msgid "Username"
|
1407 |
-
msgstr ""
|
1408 |
-
|
1409 |
#: addons/sftp.php:198
|
1410 |
msgid "Password"
|
1411 |
msgstr ""
|
@@ -1448,23 +1767,23 @@ msgstr ""
|
|
1448 |
msgid "Enter in format HH:MM (e.g. 14:22)"
|
1449 |
msgstr ""
|
1450 |
|
1451 |
-
#: addons/multisite.php:
|
1452 |
msgid "Multisite Install"
|
1453 |
msgstr ""
|
1454 |
|
1455 |
-
#: addons/multisite.php:
|
1456 |
msgid "You do not have sufficient permissions to access this page."
|
1457 |
msgstr ""
|
1458 |
|
1459 |
-
#: addons/multisite.php:
|
1460 |
msgid "You do not have permission to access this page."
|
1461 |
msgstr ""
|
1462 |
|
1463 |
-
#: addons/multisite.php:
|
1464 |
msgid "Must-use plugins"
|
1465 |
msgstr ""
|
1466 |
|
1467 |
-
#: addons/multisite.php:
|
1468 |
msgid "Blog uploads"
|
1469 |
msgstr ""
|
1470 |
|
2 |
msgstr ""
|
3 |
"Project-Id-Version: UpdraftPlus\n"
|
4 |
"Report-Msgid-Bugs-To: \n"
|
5 |
+
"POT-Creation-Date: 2013-04-12 00:39+0100\n"
|
6 |
+
"PO-Revision-Date: 2013-04-12 00:39+0100\n"
|
7 |
"Last-Translator: David Anderson <contact@updraftplus.com>\n"
|
8 |
"Language-Team: <contact@updraftplus.com>\n"
|
9 |
"Language: \n"
|
10 |
"MIME-Version: 1.0\n"
|
11 |
"Content-Type: text/plain; charset=UTF-8\n"
|
12 |
"Content-Transfer-Encoding: 8bit\n"
|
13 |
+
"X-Poedit-KeywordsList: _;gettext;gettext_noop;_x;__;_e;_ex\n"
|
14 |
"X-Poedit-Basepath: /home/david/MissionaryHosting/UpdraftPlus/svn/trunk\n"
|
15 |
"X-Poedit-SearchPath-0: .\n"
|
16 |
|
18 |
msgid "UpdraftPlus Backups"
|
19 |
msgstr ""
|
20 |
|
21 |
+
#: updraftplus.php:270
|
22 |
+
#: updraftplus.php:275
|
23 |
+
#: updraftplus.php:280
|
24 |
+
#: admin.php:167
|
25 |
+
#: admin.php:171
|
26 |
+
msgid "UpdraftPlus notice:"
|
27 |
msgstr ""
|
28 |
|
29 |
+
#: updraftplus.php:270
|
30 |
+
msgid "The log file could not be read."
|
31 |
msgstr ""
|
32 |
|
33 |
+
#: updraftplus.php:275
|
34 |
+
msgid "No log files were found."
|
35 |
msgstr ""
|
36 |
|
37 |
+
#: updraftplus.php:280
|
38 |
+
msgid "The given file could not be read."
|
39 |
msgstr ""
|
40 |
|
41 |
+
#: updraftplus.php:404
|
42 |
msgid "Plugins"
|
43 |
msgstr ""
|
44 |
|
45 |
+
#: updraftplus.php:405
|
46 |
msgid "Themes"
|
47 |
msgstr ""
|
48 |
|
49 |
+
#: updraftplus.php:406
|
50 |
msgid "Uploads"
|
51 |
msgstr ""
|
52 |
|
53 |
+
#: updraftplus.php:421
|
54 |
msgid "Others"
|
55 |
msgstr ""
|
56 |
|
57 |
+
#: updraftplus.php:689
|
58 |
msgid "Could not create files in the backup directory. Backup aborted - check your UpdraftPlus settings."
|
59 |
msgstr ""
|
60 |
|
61 |
+
#: updraftplus.php:758
|
62 |
msgid "Encryption error occurred when encrypting database. Encryption aborted."
|
63 |
msgstr ""
|
64 |
|
65 |
+
#: updraftplus.php:792
|
66 |
msgid "The backup apparently succeeded and is now complete"
|
67 |
msgstr ""
|
68 |
|
69 |
+
#: updraftplus.php:795
|
70 |
msgid "The backup attempt has finished, apparently unsuccessfully"
|
71 |
msgstr ""
|
72 |
|
73 |
+
#: updraftplus.php:798
|
74 |
msgid "The backup has not finished; a resumption is scheduled within 5 minutes"
|
75 |
msgstr ""
|
76 |
|
77 |
+
#: updraftplus.php:849
|
78 |
msgid "Backed up"
|
79 |
msgstr ""
|
80 |
|
81 |
+
#: updraftplus.php:849
|
82 |
msgid "WordPress backup is complete"
|
83 |
msgstr ""
|
84 |
|
85 |
+
#: updraftplus.php:849
|
86 |
msgid "Backup contains"
|
87 |
msgstr ""
|
88 |
|
89 |
+
#: updraftplus.php:849
|
90 |
msgid "Latest status"
|
91 |
msgstr ""
|
92 |
|
93 |
+
#: updraftplus.php:1093
|
|
|
|
|
|
|
|
|
|
|
94 |
#, php-format
|
95 |
msgid "Backup directory (%s) is not writable, or does not exist."
|
96 |
msgstr ""
|
97 |
|
98 |
+
#: updraftplus.php:1218
|
99 |
+
msgid "Could not read the directory"
|
100 |
msgstr ""
|
101 |
|
102 |
+
#: updraftplus.php:1235
|
103 |
msgid "Could not save backup history because we have no backup array. Backup probably failed."
|
104 |
msgstr ""
|
105 |
|
106 |
+
#: updraftplus.php:1264
|
107 |
msgid "Could not open the backup file for writing"
|
108 |
msgstr ""
|
109 |
|
110 |
+
#: updraftplus.php:1274
|
111 |
#, php-format
|
112 |
msgid "Generated: %s"
|
113 |
msgstr ""
|
114 |
|
115 |
+
#: updraftplus.php:1275
|
116 |
#, php-format
|
117 |
msgid "Hostname: %s"
|
118 |
msgstr ""
|
119 |
|
120 |
+
#: updraftplus.php:1276
|
121 |
#, php-format
|
122 |
msgid "Database: %s"
|
123 |
msgstr ""
|
124 |
|
125 |
+
#: updraftplus.php:1320
|
126 |
msgid "The backup directory is not writable."
|
127 |
msgstr ""
|
128 |
|
129 |
+
#: updraftplus.php:1341
|
130 |
#, php-format
|
131 |
msgid "Table: %s"
|
132 |
msgstr ""
|
133 |
|
134 |
+
#: updraftplus.php:1346
|
135 |
#, php-format
|
136 |
msgid "Skipping non-WP table: %s"
|
137 |
msgstr ""
|
138 |
|
139 |
+
#: updraftplus.php:1441
|
140 |
#, php-format
|
141 |
msgid "Delete any existing table %s"
|
142 |
msgstr ""
|
143 |
|
144 |
+
#: updraftplus.php:1450
|
145 |
#, php-format
|
146 |
msgid "Table structure of table %s"
|
147 |
msgstr ""
|
148 |
|
149 |
+
#: updraftplus.php:1456
|
150 |
#, php-format
|
151 |
msgid "Error with SHOW CREATE TABLE for %s."
|
152 |
msgstr ""
|
153 |
|
154 |
+
#: updraftplus.php:1534
|
155 |
#, php-format
|
156 |
+
msgid "End of data contents of table %s"
|
157 |
+
msgstr ""
|
158 |
+
|
159 |
+
#: updraftplus.php:1706
|
160 |
+
#: includes/updraft-restorer.php:55
|
161 |
+
msgid "Decryption failed. The database file is encrypted, but you have no encryption key entered."
|
162 |
+
msgstr ""
|
163 |
+
|
164 |
+
#: updraftplus.php:1719
|
165 |
+
#: includes/updraft-restorer.php:70
|
166 |
+
msgid "Decryption failed. The most likely cause is that you used the wrong key."
|
167 |
+
msgstr ""
|
168 |
+
|
169 |
+
#: updraftplus.php:1719
|
170 |
+
msgid "The decryption key used:"
|
171 |
+
msgstr ""
|
172 |
+
|
173 |
+
#: updraftplus.php:1734
|
174 |
+
msgid "File not found"
|
175 |
+
msgstr ""
|
176 |
+
|
177 |
+
#: updraftplus.php:1784
|
178 |
+
msgid "Can you translate? Want to improve UpdraftPlus for speakers of your language?"
|
179 |
msgstr ""
|
180 |
|
181 |
+
#: updraftplus.php:1786
|
182 |
+
msgid "Find UpdraftPlus useful?"
|
183 |
+
msgstr ""
|
184 |
+
|
185 |
+
#: updraftplus.php:1786
|
186 |
+
msgid "Please make a donation"
|
187 |
+
msgstr ""
|
188 |
+
|
189 |
+
#: updraftplus.php:1791
|
190 |
+
msgid "Like UpdraftPlus and can spare one minute?"
|
191 |
+
msgstr ""
|
192 |
+
|
193 |
+
#: updraftplus.php:1791
|
194 |
+
msgid "Please help UpdraftPlus by giving a positive review at wordpress.org"
|
195 |
+
msgstr ""
|
196 |
+
|
197 |
+
#: updraftplus.php:1798
|
198 |
+
msgid "Need even more features and support? Check out UpdraftPlus Premium"
|
199 |
+
msgstr ""
|
200 |
+
|
201 |
+
#: updraftplus.php:1807
|
202 |
+
msgid "Check out UpdraftPlus.Com for help, add-ons and support"
|
203 |
+
msgstr ""
|
204 |
+
|
205 |
+
#: updraftplus.php:1810
|
206 |
+
msgid "Want to say thank-you for UpdraftPlus?"
|
207 |
+
msgstr ""
|
208 |
+
|
209 |
+
#: updraftplus.php:1810
|
210 |
+
msgid "Please buy our very cheap 'no adverts' add-on."
|
211 |
+
msgstr ""
|
212 |
+
|
213 |
+
#: backup.php:33
|
214 |
+
msgid "Infinite recursion: consult your log for more information"
|
215 |
+
msgstr ""
|
216 |
+
|
217 |
+
#: backup.php:300
|
218 |
#, php-format
|
219 |
+
msgid "Could not create %s zip. Consult the log file for more information."
|
220 |
+
msgstr ""
|
221 |
+
|
222 |
+
#: admin.php:76
|
223 |
+
#: admin.php:93
|
224 |
+
msgid "Allowed Files"
|
225 |
+
msgstr ""
|
226 |
+
|
227 |
+
#: admin.php:143
|
228 |
+
msgid "Settings"
|
229 |
+
msgstr ""
|
230 |
+
|
231 |
+
#: admin.php:147
|
232 |
+
msgid "Add-Ons / Pro Support"
|
233 |
msgstr ""
|
234 |
|
235 |
+
#: admin.php:159
|
236 |
+
#: admin.php:163
|
237 |
+
#: admin.php:1459
|
238 |
+
#: admin.php:1465
|
239 |
+
#: admin.php:1467
|
240 |
+
msgid "Warning"
|
241 |
+
msgstr ""
|
242 |
+
|
243 |
+
#: admin.php:159
|
244 |
#, php-format
|
245 |
+
msgid "You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue."
|
246 |
msgstr ""
|
247 |
|
248 |
+
#: admin.php:163
|
249 |
+
#, php-format
|
250 |
+
msgid "UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress."
|
251 |
+
msgstr ""
|
252 |
+
|
253 |
+
#: admin.php:167
|
254 |
+
#: admin.php:171
|
255 |
+
#, php-format
|
256 |
+
msgid "Click here to authenticate your %s account (you will not be able to back up to %s without it)."
|
257 |
+
msgstr ""
|
258 |
+
|
259 |
+
#: admin.php:322
|
260 |
+
#, php-format
|
261 |
+
msgid "The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder"
|
262 |
+
msgstr ""
|
263 |
+
|
264 |
+
#: admin.php:337
|
265 |
msgid "Nothing yet logged"
|
266 |
msgstr ""
|
267 |
|
268 |
+
#: admin.php:354
|
269 |
+
msgid "Download failed"
|
270 |
msgstr ""
|
271 |
|
272 |
+
#: admin.php:368
|
273 |
+
#: admin.php:890
|
274 |
+
msgid "File ready."
|
275 |
+
msgstr ""
|
276 |
+
|
277 |
+
#: admin.php:376
|
278 |
+
msgid "Download in progress"
|
279 |
+
msgstr ""
|
280 |
+
|
281 |
+
#: admin.php:379
|
282 |
msgid "No local copy present."
|
283 |
msgstr ""
|
284 |
|
285 |
+
#: admin.php:487
|
286 |
+
msgid "Bad filename format - this does not look like a file created by UpdraftPlus"
|
287 |
msgstr ""
|
288 |
|
289 |
+
#: admin.php:566
|
290 |
+
msgid "Bad filename format - this does not look like an encrypted database file created by UpdraftPlus"
|
|
|
291 |
msgstr ""
|
292 |
|
293 |
+
#: admin.php:593
|
294 |
+
msgid "Restore successful!"
|
295 |
msgstr ""
|
296 |
|
297 |
+
#: admin.php:594
|
298 |
+
#: admin.php:629
|
299 |
+
#: admin.php:641
|
300 |
+
msgid "Actions"
|
301 |
msgstr ""
|
302 |
|
303 |
+
#: admin.php:594
|
304 |
+
#: admin.php:609
|
305 |
+
#: admin.php:629
|
306 |
+
#: admin.php:641
|
307 |
+
msgid "Return to UpdraftPlus Configuration"
|
308 |
msgstr ""
|
309 |
|
310 |
+
#: admin.php:618
|
311 |
+
msgid "Remove old directories"
|
|
|
|
|
312 |
msgstr ""
|
313 |
|
314 |
+
#: admin.php:624
|
315 |
+
msgid "Old directories successfully removed."
|
316 |
msgstr ""
|
317 |
|
318 |
+
#: admin.php:627
|
319 |
+
msgid "Old directory removal failed for some reason. You may want to do this manually."
|
320 |
msgstr ""
|
321 |
|
322 |
+
#: admin.php:638
|
323 |
+
msgid "Backup directory could not be created"
|
324 |
msgstr ""
|
325 |
|
326 |
+
#: admin.php:640
|
327 |
+
msgid "Backup directory successfully created."
|
328 |
msgstr ""
|
329 |
|
330 |
+
#: admin.php:647
|
331 |
+
msgid "Schedule backup"
|
332 |
msgstr ""
|
333 |
|
334 |
+
#: admin.php:650
|
335 |
+
msgid "Failed."
|
336 |
msgstr ""
|
337 |
|
338 |
+
#: admin.php:652
|
339 |
+
msgid "OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the \"Last log message\" field below."
|
|
|
340 |
msgstr ""
|
341 |
|
342 |
+
#: admin.php:652
|
343 |
+
msgid "Nothing happening? Follow this link for help."
|
344 |
msgstr ""
|
345 |
|
346 |
+
#: admin.php:666
|
347 |
+
msgid "Your settings have been wiped."
|
348 |
msgstr ""
|
349 |
|
350 |
+
#: admin.php:673
|
351 |
+
msgid "By UpdraftPlus.Com"
|
352 |
msgstr ""
|
353 |
|
354 |
+
#: admin.php:673
|
355 |
+
msgid "Lead developer's homepage"
|
356 |
msgstr ""
|
357 |
|
358 |
+
#: admin.php:673
|
359 |
+
msgid "Donate"
|
360 |
msgstr ""
|
361 |
|
362 |
+
#: admin.php:673
|
363 |
+
msgid "Other WordPress plugins"
|
364 |
msgstr ""
|
365 |
|
366 |
+
#: admin.php:673
|
367 |
+
msgid "Version"
|
368 |
msgstr ""
|
369 |
|
370 |
+
#: admin.php:679
|
371 |
+
msgid "Your backup has been restored."
|
372 |
msgstr ""
|
373 |
|
374 |
+
#: admin.php:679
|
375 |
+
msgid "Your old (themes, uploads, plugins, whatever) directories have been retained with \"-old\" appended to their name. Remove them when you are satisfied that the backup worked properly."
|
376 |
msgstr ""
|
377 |
|
378 |
+
#: admin.php:685
|
379 |
+
msgid "Old directories successfully deleted."
|
380 |
msgstr ""
|
381 |
|
382 |
+
#: admin.php:688
|
383 |
+
msgid "Your PHP memory limit (set by your web hosting company) is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will bhe successful with a 32Mb limit - your experience may vary)."
|
384 |
msgstr ""
|
385 |
|
386 |
+
#: admin.php:688
|
387 |
+
msgid "Current limit is:"
|
388 |
msgstr ""
|
389 |
|
390 |
+
#: admin.php:692
|
391 |
+
msgid "Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:"
|
392 |
msgstr ""
|
393 |
|
394 |
+
#: admin.php:692
|
395 |
+
msgid "seconds"
|
396 |
msgstr ""
|
397 |
|
398 |
+
#: admin.php:697
|
399 |
+
msgid "You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked)."
|
400 |
msgstr ""
|
401 |
|
402 |
+
#: admin.php:701
|
403 |
+
msgid "Delete Old Directories"
|
404 |
msgstr ""
|
405 |
|
406 |
+
#: admin.php:701
|
407 |
+
msgid "Are you sure you want to delete the old directories? This cannot be undone."
|
408 |
msgstr ""
|
409 |
|
410 |
+
#: admin.php:714
|
411 |
+
msgid "Existing Schedule And Backups"
|
412 |
msgstr ""
|
413 |
|
414 |
+
#: admin.php:718
|
415 |
+
msgid "JavaScript warning"
|
416 |
msgstr ""
|
417 |
|
418 |
+
#: admin.php:719
|
419 |
+
msgid "This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser."
|
420 |
msgstr ""
|
421 |
|
422 |
+
#: admin.php:732
|
423 |
+
#: admin.php:745
|
424 |
+
msgid "Nothing currently scheduled"
|
425 |
msgstr ""
|
426 |
|
427 |
+
#: admin.php:737
|
428 |
+
msgid "At the same time as the files backup"
|
429 |
msgstr ""
|
430 |
|
431 |
+
#: admin.php:757
|
432 |
+
msgid "Next scheduled backups"
|
433 |
msgstr ""
|
434 |
|
435 |
+
#: admin.php:759
|
436 |
+
msgid "Files"
|
437 |
msgstr ""
|
438 |
|
439 |
+
#: admin.php:760
|
440 |
+
#: admin.php:936
|
441 |
+
#: admin.php:1531
|
442 |
+
#: admin.php:1538
|
443 |
+
#: admin.php:1692
|
444 |
+
msgid "Database"
|
445 |
msgstr ""
|
446 |
|
447 |
+
#: admin.php:761
|
448 |
+
msgid "Time now"
|
449 |
msgstr ""
|
450 |
|
451 |
+
#: admin.php:765
|
452 |
+
msgid "Last finished backup run"
|
453 |
msgstr ""
|
454 |
|
455 |
+
#: admin.php:770
|
456 |
+
#: admin.php:1349
|
457 |
+
msgid "Backup Now"
|
458 |
msgstr ""
|
459 |
|
460 |
+
#: admin.php:778
|
461 |
+
#: admin.php:1328
|
462 |
+
#: admin.php:1575
|
463 |
+
msgid "Restore"
|
464 |
msgstr ""
|
465 |
|
466 |
+
#: admin.php:785
|
467 |
+
msgid "Last log message"
|
468 |
msgstr ""
|
469 |
|
470 |
+
#: admin.php:787
|
471 |
+
msgid "(Nothing yet logged)"
|
472 |
msgstr ""
|
473 |
|
474 |
+
#: admin.php:788
|
475 |
+
msgid "Download most recently modified log file"
|
476 |
msgstr ""
|
477 |
|
478 |
+
#: admin.php:792
|
479 |
+
msgid "Backups, logs & restoring"
|
480 |
msgstr ""
|
481 |
|
482 |
+
#: admin.php:793
|
483 |
+
msgid "Press to see available backups"
|
484 |
msgstr ""
|
485 |
|
486 |
+
#: admin.php:793
|
487 |
+
#, php-format
|
488 |
+
msgid "%d set(s) available"
|
489 |
msgstr ""
|
490 |
|
491 |
+
#: admin.php:798
|
492 |
+
msgid "Downloading"
|
493 |
msgstr ""
|
494 |
|
495 |
+
#: admin.php:798
|
496 |
+
msgid "Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly."
|
|
|
|
|
497 |
msgstr ""
|
498 |
|
499 |
+
#: admin.php:799
|
500 |
+
msgid "Restoring"
|
|
|
501 |
msgstr ""
|
502 |
|
503 |
+
#: admin.php:799
|
504 |
+
msgid "Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself."
|
|
|
505 |
msgstr ""
|
506 |
|
507 |
+
#: admin.php:799
|
508 |
+
msgid "More tasks:"
|
509 |
msgstr ""
|
510 |
|
511 |
+
#: admin.php:799
|
512 |
+
msgid "upload backup files"
|
513 |
msgstr ""
|
514 |
|
515 |
+
#: admin.php:799
|
516 |
+
msgid "Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below."
|
517 |
msgstr ""
|
518 |
|
519 |
+
#: admin.php:799
|
520 |
+
msgid "rescan folder for new backup sets"
|
521 |
msgstr ""
|
522 |
|
523 |
+
#: admin.php:800
|
524 |
+
msgid "Opera web browser"
|
525 |
msgstr ""
|
526 |
|
527 |
+
#: admin.php:800
|
528 |
+
msgid "If you are using this, then turn Turbo/Road mode off."
|
529 |
msgstr ""
|
530 |
|
531 |
+
#: admin.php:801
|
532 |
+
msgid "This is a count of the contents of your Updraft directory"
|
533 |
msgstr ""
|
534 |
|
535 |
+
#: admin.php:801
|
536 |
+
msgid "Web-server disk space in use by UpdraftPlus"
|
537 |
msgstr ""
|
538 |
|
539 |
+
#: admin.php:801
|
540 |
+
msgid "refresh"
|
541 |
msgstr ""
|
542 |
|
543 |
+
#: admin.php:803
|
544 |
+
msgid "UpdraftPlus - Upload backup files"
|
545 |
msgstr ""
|
546 |
|
547 |
+
#: admin.php:804
|
548 |
+
msgid "Upload files into UpdraftPlus. Use this to import backups made on a different WordPress installation."
|
549 |
msgstr ""
|
550 |
|
551 |
+
#: admin.php:808
|
552 |
+
msgid "Drop backup zips here"
|
553 |
msgstr ""
|
554 |
|
555 |
+
#: admin.php:809
|
556 |
+
#: admin.php:1205
|
557 |
+
msgid "or"
|
558 |
msgstr ""
|
559 |
|
560 |
+
#: admin.php:822
|
561 |
+
msgid "calculating..."
|
562 |
msgstr ""
|
563 |
|
564 |
+
#: admin.php:880
|
565 |
+
#: admin.php:902
|
566 |
+
msgid "Error:"
|
567 |
msgstr ""
|
568 |
|
569 |
+
#: admin.php:890
|
570 |
+
msgid "You should:"
|
571 |
msgstr ""
|
572 |
|
573 |
+
#: admin.php:897
|
574 |
+
msgid "Download error: the server sent us a response (JSON) which we did not understand"
|
575 |
msgstr ""
|
576 |
|
577 |
+
#: admin.php:902
|
578 |
+
msgid "Download error: the server sent us a response which we did not understand."
|
579 |
msgstr ""
|
580 |
|
581 |
+
#: admin.php:917
|
582 |
+
msgid "Restore backup"
|
583 |
msgstr ""
|
584 |
|
585 |
+
#: admin.php:918
|
586 |
+
msgid "Restore backup from"
|
587 |
msgstr ""
|
588 |
|
589 |
+
#: admin.php:919
|
590 |
+
msgid "Restoring will replace this site's themes, plugins, uploads, database and/or other content directories (according to what is contained in the backup set, and your selection"
|
|
|
|
|
591 |
msgstr ""
|
592 |
|
593 |
+
#: admin.php:919
|
594 |
+
msgid "Choose the components to restore"
|
|
|
|
|
|
|
595 |
msgstr ""
|
596 |
|
597 |
+
#: admin.php:928
|
598 |
+
msgid "Your web server has PHP's so-called safe_mode active."
|
599 |
msgstr ""
|
600 |
|
601 |
+
#: admin.php:928
|
602 |
+
msgid "This makes time-outs much more likely. You are recommended to turn safe_mode off, or to restore only one entity at a time, <a href=\"http://updraftplus.com/faqs/i-want-to-restore-but-have-either-cannot-or-have-failed-to-do-so-from-the-wp-admin-console/\">or to restore manually</a>."
|
603 |
msgstr ""
|
604 |
|
605 |
+
#: admin.php:941
|
606 |
+
msgid "Perform a backup now"
|
607 |
msgstr ""
|
608 |
|
609 |
+
#: admin.php:942
|
610 |
+
msgid "This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background."
|
611 |
msgstr ""
|
612 |
|
613 |
+
#: admin.php:948
|
614 |
+
msgid "Does nothing happen when you schedule backups?"
|
615 |
msgstr ""
|
616 |
|
617 |
+
#: admin.php:948
|
618 |
+
msgid "Go here for help."
|
619 |
msgstr ""
|
620 |
|
621 |
+
#: admin.php:954
|
622 |
+
msgid "Multisite"
|
623 |
msgstr ""
|
624 |
|
625 |
+
#: admin.php:958
|
626 |
+
msgid "Do you need WordPress Multisite support?"
|
627 |
msgstr ""
|
628 |
|
629 |
+
#: admin.php:958
|
630 |
+
msgid "Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on."
|
631 |
msgstr ""
|
632 |
|
633 |
+
#: admin.php:963
|
634 |
+
msgid "Configure Backup Contents And Schedule"
|
635 |
msgstr ""
|
636 |
|
637 |
+
#: admin.php:969
|
638 |
+
msgid "Debug Information And Expert Options"
|
639 |
msgstr ""
|
640 |
|
641 |
+
#: admin.php:974
|
642 |
+
msgid "Peak memory usage"
|
643 |
msgstr ""
|
644 |
|
645 |
+
#: admin.php:975
|
646 |
+
msgid "Current memory usage"
|
647 |
msgstr ""
|
648 |
|
649 |
+
#: admin.php:976
|
650 |
+
msgid "PHP memory limit"
|
651 |
msgstr ""
|
652 |
|
653 |
+
#: admin.php:979
|
654 |
+
msgid "The buttons below will immediately execute a backup run, independently of WordPress's scheduler. If these work whilst your scheduled backups and the \"Backup Now\" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the \"Backup Now\" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them."
|
655 |
msgstr ""
|
656 |
|
657 |
+
#: admin.php:983
|
658 |
+
msgid "Debug Full Backup"
|
659 |
msgstr ""
|
660 |
|
661 |
+
#: admin.php:983
|
662 |
+
msgid "This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled)."
|
663 |
msgstr ""
|
664 |
|
665 |
+
#: admin.php:987
|
666 |
+
msgid "Debug Database Backup"
|
667 |
msgstr ""
|
668 |
|
669 |
+
#: admin.php:987
|
670 |
+
msgid "This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites.."
|
671 |
msgstr ""
|
672 |
|
673 |
+
#: admin.php:989
|
674 |
+
msgid "Wipe Settings"
|
675 |
msgstr ""
|
676 |
|
677 |
+
#: admin.php:990
|
678 |
+
msgid "This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish."
|
679 |
msgstr ""
|
680 |
|
681 |
+
#: admin.php:993
|
682 |
+
msgid "Wipe All Settings"
|
683 |
msgstr ""
|
684 |
|
685 |
+
#: admin.php:993
|
686 |
+
msgid "This will delete all your UpdraftPlus settings - are you sure you want to do this?"
|
687 |
msgstr ""
|
688 |
|
689 |
+
#: admin.php:1036
|
690 |
+
msgid "Delete"
|
691 |
msgstr ""
|
692 |
|
693 |
+
#: admin.php:1100
|
694 |
+
msgid "Download log file"
|
695 |
msgstr ""
|
696 |
|
697 |
+
#: admin.php:1106
|
698 |
+
msgid "No backup has been completed."
|
699 |
msgstr ""
|
700 |
|
701 |
+
#: admin.php:1123
|
702 |
+
msgid "File backup intervals"
|
703 |
msgstr ""
|
704 |
|
705 |
+
#: admin.php:1126
|
706 |
+
msgid "Manual"
|
707 |
msgstr ""
|
708 |
|
709 |
+
#: admin.php:1126
|
710 |
+
msgid "Every 4 hours"
|
711 |
msgstr ""
|
712 |
|
713 |
+
#: admin.php:1126
|
714 |
+
msgid "Every 8 hours"
|
|
|
715 |
msgstr ""
|
716 |
|
717 |
+
#: admin.php:1126
|
718 |
+
msgid "Every 12 hours"
|
719 |
msgstr ""
|
720 |
|
721 |
+
#: admin.php:1126
|
722 |
+
msgid "Daily"
|
723 |
msgstr ""
|
724 |
|
725 |
+
#: admin.php:1126
|
726 |
+
msgid "Weekly"
|
727 |
msgstr ""
|
728 |
|
729 |
+
#: admin.php:1126
|
730 |
+
msgid "Fortnightly"
|
731 |
msgstr ""
|
732 |
|
733 |
+
#: admin.php:1126
|
734 |
+
msgid "Monthly"
|
735 |
msgstr ""
|
736 |
|
737 |
+
#: admin.php:1135
|
738 |
+
#: admin.php:1153
|
739 |
+
msgid "and retain this many backups"
|
740 |
+
msgstr ""
|
741 |
+
|
742 |
+
#: admin.php:1142
|
743 |
+
msgid "Database backup intervals"
|
744 |
+
msgstr ""
|
745 |
+
|
746 |
+
#: admin.php:1160
|
747 |
+
msgid "If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose \"manual\" then you must click the \"Backup Now\" button whenever you wish a backup to occur."
|
748 |
+
msgstr ""
|
749 |
+
|
750 |
+
#: admin.php:1161
|
751 |
+
msgid "To fix the time at which a backup should take place,"
|
752 |
+
msgstr ""
|
753 |
+
|
754 |
+
#: admin.php:1161
|
755 |
+
msgid "e.g. if your server is busy at day and you want to run overnight"
|
756 |
+
msgstr ""
|
757 |
+
|
758 |
+
#: admin.php:1161
|
759 |
+
msgid "use the \"Fix Time\" add-on"
|
760 |
+
msgstr ""
|
761 |
+
|
762 |
+
#: admin.php:1165
|
763 |
+
msgid "Include in files backup"
|
764 |
+
msgstr ""
|
765 |
+
|
766 |
+
#: admin.php:1175
|
767 |
+
msgid "Any other directories found inside wp-content but exclude these directories:"
|
768 |
+
msgstr ""
|
769 |
+
|
770 |
+
#: admin.php:1181
|
771 |
+
msgid "The above directories are everything, except for WordPress core itself which you can download afresh from WordPress.org."
|
772 |
+
msgstr ""
|
773 |
+
|
774 |
+
#: admin.php:1181
|
775 |
+
msgid "Or, get the \"More Files\" add-on from our shop."
|
776 |
+
msgstr ""
|
777 |
+
|
778 |
+
#: admin.php:1181
|
779 |
+
msgid "Use WordShell for automatic backup, version control and patching"
|
780 |
+
msgstr ""
|
781 |
+
|
782 |
+
#: admin.php:1185
|
783 |
+
msgid "Email"
|
784 |
+
msgstr ""
|
785 |
+
|
786 |
+
#: admin.php:1186
|
787 |
+
msgid "Enter an address here to have a report sent (and the whole backup, if you choose) to it."
|
788 |
+
msgstr ""
|
789 |
+
|
790 |
+
#: admin.php:1190
|
791 |
+
msgid "Database encryption phrase"
|
792 |
+
msgstr ""
|
793 |
+
|
794 |
+
#: admin.php:1197
|
795 |
+
msgid "If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back)."
|
796 |
+
msgstr ""
|
797 |
+
|
798 |
+
#: admin.php:1197
|
799 |
+
msgid "You can also decrypt a database manually here."
|
800 |
+
msgstr ""
|
801 |
+
|
802 |
+
#: admin.php:1200
|
803 |
+
msgid "Manually decrypt a database backup file"
|
804 |
+
msgstr ""
|
805 |
+
|
806 |
+
#: admin.php:1204
|
807 |
+
msgid "Drop encrypted database files (db.crypt.gz files) here to upload them for decryption"
|
808 |
+
msgstr ""
|
809 |
+
|
810 |
+
#: admin.php:1207
|
811 |
+
msgid "Use decryption key"
|
812 |
+
msgstr ""
|
813 |
+
|
814 |
+
#: admin.php:1221
|
815 |
+
msgid "Copying Your Backup To Remote Storage"
|
816 |
+
msgstr ""
|
817 |
+
|
818 |
+
#: admin.php:1225
|
819 |
+
msgid "Choose your remote storage"
|
820 |
+
msgstr ""
|
821 |
+
|
822 |
+
#: admin.php:1237
|
823 |
+
msgid "None"
|
824 |
+
msgstr ""
|
825 |
+
|
826 |
+
#: admin.php:1342
|
827 |
+
#: admin.php:1352
|
828 |
+
msgid "Cancel"
|
829 |
+
msgstr ""
|
830 |
+
|
831 |
+
#: admin.php:1376
|
832 |
+
msgid "Advanced / Debugging Settings"
|
833 |
+
msgstr ""
|
834 |
+
|
835 |
+
#: admin.php:1379
|
836 |
+
msgid "Debug mode"
|
837 |
msgstr ""
|
838 |
|
839 |
+
#: admin.php:1380
|
840 |
+
msgid "Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report."
|
841 |
msgstr ""
|
842 |
|
843 |
+
#: admin.php:1383
|
844 |
+
msgid "Expert settings"
|
845 |
msgstr ""
|
846 |
|
847 |
+
#: admin.php:1384
|
848 |
+
msgid "Show expert settings"
|
849 |
msgstr ""
|
850 |
|
851 |
+
#: admin.php:1384
|
852 |
+
msgid "click this to show some further options; don't bother with this unless you have a problem or are curious."
|
|
|
853 |
msgstr ""
|
854 |
|
855 |
+
#: admin.php:1391
|
856 |
+
msgid "Delete local backup"
|
857 |
msgstr ""
|
858 |
|
859 |
+
#: admin.php:1392
|
860 |
+
msgid "Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits)."
|
861 |
msgstr ""
|
862 |
|
863 |
+
#: admin.php:1397
|
864 |
+
msgid "Backup directory"
|
865 |
msgstr ""
|
866 |
|
867 |
+
#: admin.php:1405
|
868 |
+
msgid "Backup directory specified is writable, which is good."
|
869 |
msgstr ""
|
870 |
|
871 |
+
#: admin.php:1407
|
872 |
+
msgid "Backup directory specified is <b>not</b> writable, or does not exist."
|
873 |
msgstr ""
|
874 |
|
875 |
+
#: admin.php:1407
|
876 |
+
msgid "Click here to attempt to create the directory and set the permissions"
|
877 |
msgstr ""
|
878 |
|
879 |
+
#: admin.php:1407
|
880 |
+
msgid "or, to reset this option"
|
881 |
msgstr ""
|
882 |
|
883 |
+
#: admin.php:1407
|
884 |
+
msgid "click here"
|
885 |
msgstr ""
|
886 |
|
887 |
+
#: admin.php:1407
|
888 |
+
msgid "If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process."
|
889 |
msgstr ""
|
890 |
|
891 |
+
#: admin.php:1410
|
892 |
+
msgid "This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...)."
|
893 |
msgstr ""
|
894 |
|
895 |
+
#: admin.php:1414
|
896 |
+
msgid "Use the server's SSL certificates"
|
897 |
msgstr ""
|
898 |
|
899 |
+
#: admin.php:1415
|
900 |
+
msgid "By default UpdraftPlus its own store of SSL certificates to verify the identity of remote sites (i.e. to make sure it is talking to the real Dropbox, Amazon S3, etc., and not an attacker). We keep these up to date. However, if you get an SSL error, then choosing this option (which causes UpdraftPlus to use your web server's collection instead) may help."
|
901 |
msgstr ""
|
902 |
|
903 |
+
#: admin.php:1419
|
904 |
+
msgid "Do not verify SSL certificates"
|
905 |
msgstr ""
|
906 |
|
907 |
+
#: admin.php:1420
|
908 |
+
msgid "Choosing this option lowers your security by stopping UpdraftPlus from verifying the identity of encrypted sites that it connects to (e.g. Dropbox, Google Drive). It means that UpdraftPlus will be using SSL only for encryption of traffic, and not for authentication."
|
909 |
msgstr ""
|
910 |
|
911 |
+
#: admin.php:1420
|
912 |
+
msgid "Note that not all cloud backup methods are necessarily using SSL authentication."
|
913 |
msgstr ""
|
914 |
|
915 |
+
#: admin.php:1424
|
916 |
+
msgid "Disable SSL entirely where possible"
|
917 |
msgstr ""
|
918 |
|
919 |
+
#: admin.php:1425
|
920 |
+
msgid "Choosing this option lowers your security by stopping UpdraftPlus from using SSL for authentication and encrypted transport at all, where possible. Note that some cloud storage providers do not allow this (e.g. Dropbox), so with those providers this setting will have no effect."
|
921 |
msgstr ""
|
922 |
|
923 |
+
#: admin.php:1449
|
924 |
+
msgid "Save Changes"
|
925 |
msgstr ""
|
926 |
|
927 |
+
#: admin.php:1459
|
928 |
+
#, php-format
|
929 |
+
msgid "Your web server's PHP installation does not included a required module (%s). Please contact your web hosting provider's support."
|
930 |
msgstr ""
|
931 |
|
932 |
+
#: admin.php:1459
|
933 |
+
#, php-format
|
934 |
+
msgid "UpdraftPlus's %s module <strong>requires</strong> Curl. Your only options to get this working are 1) Install/enable curl or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this."
|
935 |
msgstr ""
|
936 |
|
937 |
+
#: admin.php:1465
|
938 |
+
#, php-format
|
939 |
+
msgid "Your web server's PHP/Curl installation does not support https access. Communications with %s will be unencrypted. ask your web host to install Curl/SSL in order to gain the ability for encryption (via an add-on)."
|
940 |
msgstr ""
|
941 |
|
942 |
+
#: admin.php:1467
|
943 |
+
#, php-format
|
944 |
+
msgid "Your web server's PHP/Curl installation does not support https access. We cannot access %s without this support. Please contact your web hosting provider's support. %s <strong>requires</strong> Curl+https. Please do not file any support requests; there is no alternative."
|
945 |
msgstr ""
|
946 |
|
947 |
+
#: admin.php:1470
|
948 |
+
#, php-format
|
949 |
+
msgid "Good news: Your site's communications with %s can be encrypted. If you see any errors to do with encryption, then look in the 'Expert Settings' for more help."
|
950 |
msgstr ""
|
951 |
|
952 |
+
#: admin.php:1555
|
953 |
+
msgid "Press here to download"
|
954 |
msgstr ""
|
955 |
|
956 |
+
#: admin.php:1557
|
957 |
+
#, php-format
|
958 |
+
msgid "(No %s)"
|
959 |
msgstr ""
|
960 |
|
961 |
+
#: admin.php:1567
|
962 |
+
msgid "Backup Log"
|
963 |
msgstr ""
|
964 |
|
965 |
+
#: admin.php:1575
|
966 |
+
msgid "After pressing this button, you will be given the option to choose which components you wish to restore"
|
967 |
msgstr ""
|
968 |
|
969 |
+
#: admin.php:1658
|
970 |
+
msgid "This backup does not exist in the backup history - restoration aborted. Timestamp:"
|
971 |
msgstr ""
|
972 |
|
973 |
+
#: admin.php:1671
|
974 |
+
msgid "UpdraftPlus Restoration: Progress"
|
975 |
msgstr ""
|
976 |
|
977 |
+
#: admin.php:1678
|
978 |
+
msgid "ABORT: Could not find the information on which entities to restore."
|
979 |
msgstr ""
|
980 |
|
981 |
+
#: admin.php:1698
|
982 |
+
msgid "This component was not selected for restoration - skipping."
|
983 |
msgstr ""
|
984 |
|
985 |
+
#: admin.php:1706
|
986 |
+
msgid "File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)"
|
987 |
msgstr ""
|
988 |
|
989 |
+
#: admin.php:1712
|
990 |
+
msgid "Archive is expected to be size:"
|
991 |
msgstr ""
|
992 |
|
993 |
+
#: admin.php:1717
|
994 |
+
msgid "ERROR"
|
995 |
msgstr ""
|
996 |
|
997 |
+
#: admin.php:1720
|
998 |
+
msgid "The backup records do not contain information about the proper size of this file."
|
999 |
msgstr ""
|
1000 |
|
1001 |
+
#: admin.php:1732
|
1002 |
+
msgid "Error message"
|
1003 |
msgstr ""
|
1004 |
|
1005 |
+
#: admin.php:1738
|
1006 |
+
#: admin.php:1739
|
1007 |
+
msgid "Could not find one of the files for restoration"
|
1008 |
msgstr ""
|
1009 |
|
1010 |
+
#: includes/updraft-restorer.php:5
|
1011 |
+
msgid "UpdraftPlus is not able to directly restore this kind of entity. It must be restored manually."
|
1012 |
msgstr ""
|
1013 |
|
1014 |
+
#: includes/updraft-restorer.php:6
|
1015 |
+
msgid "Backup file not available."
|
1016 |
msgstr ""
|
1017 |
|
1018 |
+
#: includes/updraft-restorer.php:7
|
1019 |
+
msgid "Unpacking backup..."
|
1020 |
msgstr ""
|
1021 |
|
1022 |
+
#: includes/updraft-restorer.php:8
|
1023 |
+
msgid "Decrypting database (can take a while)..."
|
1024 |
msgstr ""
|
1025 |
|
1026 |
+
#: includes/updraft-restorer.php:9
|
1027 |
+
msgid "Database successfully decrypted."
|
1028 |
msgstr ""
|
1029 |
|
1030 |
+
#: includes/updraft-restorer.php:10
|
1031 |
+
msgid "Moving old directory out of the way..."
|
1032 |
msgstr ""
|
1033 |
|
1034 |
+
#: includes/updraft-restorer.php:11
|
1035 |
+
msgid "Moving unpacked backup in place..."
|
1036 |
msgstr ""
|
1037 |
|
1038 |
+
#: includes/updraft-restorer.php:12
|
1039 |
+
msgid "Restoring the database (on a large site this can take a long time - if it times out (which can happen if your web hosting company has configured your hosting to limit resources) then you should use a different method, such as phpMyAdmin)..."
|
|
|
1040 |
msgstr ""
|
1041 |
|
1042 |
+
#: includes/updraft-restorer.php:13
|
1043 |
+
msgid "Cleaning up rubbish..."
|
1044 |
msgstr ""
|
1045 |
|
1046 |
+
#: includes/updraft-restorer.php:14
|
1047 |
+
msgid "Could not move old directory out of the way. Perhaps you already have -old directories that need deleting first?"
|
1048 |
msgstr ""
|
1049 |
|
1050 |
+
#: includes/updraft-restorer.php:15
|
1051 |
+
msgid "Could not delete old directory."
|
|
|
1052 |
msgstr ""
|
1053 |
|
1054 |
+
#: includes/updraft-restorer.php:16
|
1055 |
+
msgid "Could not move new directory into place. Check your wp-content/upgrade folder."
|
|
|
1056 |
msgstr ""
|
1057 |
|
1058 |
+
#: includes/updraft-restorer.php:17
|
1059 |
+
msgid "Failed to delete working directory after restoring."
|
|
|
1060 |
msgstr ""
|
1061 |
|
1062 |
+
#: includes/updraft-restorer.php:49
|
1063 |
+
msgid "Failed to create a temporary directory"
|
|
|
|
|
1064 |
msgstr ""
|
1065 |
|
1066 |
+
#: includes/updraft-restorer.php:67
|
1067 |
+
msgid "Failed to write out the decrypted database to the filesystem"
|
1068 |
msgstr ""
|
1069 |
|
1070 |
+
#: includes/updraft-restorer.php:158
|
1071 |
+
msgid "Will not delete the archive after unpacking it, because there was no cloud storage for this backup"
|
|
|
|
|
1072 |
msgstr ""
|
1073 |
|
1074 |
+
#: includes/updraft-restorer.php:179
|
1075 |
+
msgid "Warning: PHP safe_mode is active on your server. Timeouts are much more likely. If these happen, then you will need to manually restore the file via phpMyAdmin or another method."
|
1076 |
msgstr ""
|
1077 |
|
1078 |
+
#: includes/updraft-restorer.php:186
|
1079 |
+
msgid "Failed to find database file"
|
1080 |
msgstr ""
|
1081 |
|
1082 |
+
#: includes/updraft-restorer.php:192
|
1083 |
+
msgid "Failed to open database file"
|
1084 |
msgstr ""
|
1085 |
|
1086 |
+
#: includes/updraft-restorer.php:212
|
1087 |
+
msgid "Database access: Direct MySQL access is not available, so we are falling back to wpdb (this will be considerably slower)"
|
1088 |
msgstr ""
|
1089 |
|
1090 |
+
#: includes/updraft-restorer.php:238
|
1091 |
+
msgid "Restoring table"
|
1092 |
msgstr ""
|
1093 |
|
1094 |
+
#: includes/updraft-restorer.php:250
|
1095 |
+
#, php-format
|
1096 |
+
msgid "An error (%s) occured:"
|
1097 |
msgstr ""
|
1098 |
|
1099 |
+
#: includes/updraft-restorer.php:250
|
1100 |
+
msgid "the database query being run was: "
|
1101 |
msgstr ""
|
1102 |
|
1103 |
+
#: includes/updraft-restorer.php:253
|
1104 |
+
msgid "Too many database errors have occurred - aborting restoration (you will need to restore manually)"
|
1105 |
msgstr ""
|
1106 |
|
1107 |
+
#: includes/updraft-restorer.php:260
|
1108 |
+
#, php-format
|
1109 |
+
msgid "Database lines processed: %d in %.2f seconds"
|
1110 |
msgstr ""
|
1111 |
|
1112 |
+
#: includes/updraft-restorer.php:269
|
1113 |
+
#, php-format
|
1114 |
+
msgid "Finished: lines processed: %d in %.2f seconds"
|
1115 |
msgstr ""
|
1116 |
|
1117 |
#: methods/webdav.php:13
|
1135 |
msgid "follow this link to get it"
|
1136 |
msgstr ""
|
1137 |
|
1138 |
+
#: methods/googledrive.php:95
|
1139 |
+
#: methods/cloudfiles.php:449
|
|
|
|
|
1140 |
msgid "Success"
|
1141 |
msgstr ""
|
1142 |
|
1143 |
+
#: methods/googledrive.php:95
|
|
|
1144 |
#, php-format
|
1145 |
msgid "you have authenticated your %s account"
|
1146 |
msgstr ""
|
1147 |
|
1148 |
+
#: methods/googledrive.php:95
|
1149 |
+
#: methods/googledrive.php:331
|
1150 |
+
#: methods/googledrive.php:333
|
1151 |
+
#: methods/googledrive.php:351
|
1152 |
+
#: methods/googledrive.php:355
|
1153 |
+
#: methods/googledrive.php:359
|
1154 |
msgid "Google Drive"
|
1155 |
msgstr ""
|
1156 |
|
1157 |
+
#: methods/googledrive.php:99
|
1158 |
msgid "No refresh token was received from Google. This often means that you entered your client secret wrongly, or that you have not yet re-authenticated (below) since correcting it. Re-check it, then follow the link to authenticate again. Finally, if that does not work, then use expert mode to wipe all your settings, create a new Google client ID/secret, and start again."
|
1159 |
msgstr ""
|
1160 |
|
1161 |
+
#: methods/googledrive.php:104
|
1162 |
msgid "Authorization failed"
|
1163 |
msgstr ""
|
1164 |
|
1165 |
+
#: methods/googledrive.php:118
|
1166 |
msgid "Have not yet obtained an access token from Google - you need to authorise or re-authorise your connection to Google Drive."
|
1167 |
msgstr ""
|
1168 |
|
1169 |
+
#: methods/googledrive.php:119
|
1170 |
+
#: methods/googledrive.php:255
|
1171 |
msgid "Have not yet obtained an access token from Google (has the user authorised?)"
|
1172 |
msgstr ""
|
1173 |
|
1174 |
+
#: methods/googledrive.php:136
|
|
|
1175 |
#, php-format
|
1176 |
msgid "Failed to upload to %s"
|
1177 |
msgstr ""
|
1178 |
|
1179 |
+
#: methods/googledrive.php:190
|
|
|
1180 |
msgid "Error"
|
1181 |
msgstr ""
|
1182 |
|
1183 |
+
#: methods/googledrive.php:226
|
1184 |
msgid "An error occurred during GoogleDrive upload (see log for more details)"
|
1185 |
msgstr ""
|
1186 |
|
1187 |
+
#: methods/googledrive.php:267
|
1188 |
#, php-format
|
1189 |
msgid "Google Drive error: %d: could not download: could not find a record of the Google Drive file ID for this file"
|
1190 |
msgstr ""
|
1191 |
|
1192 |
+
#: methods/googledrive.php:272
|
1193 |
#, php-format
|
1194 |
msgid "Could not find %s in order to download it"
|
1195 |
msgstr ""
|
1196 |
|
1197 |
+
#: methods/googledrive.php:284
|
1198 |
msgid "Google Drive "
|
1199 |
msgstr ""
|
1200 |
|
1201 |
+
#: methods/googledrive.php:284
|
1202 |
msgid "error: zero-size file was downloaded"
|
1203 |
msgstr ""
|
1204 |
|
1205 |
+
#: methods/googledrive.php:302
|
1206 |
msgid "Account is not authorized."
|
1207 |
msgstr ""
|
1208 |
|
1209 |
+
#: methods/googledrive.php:334
|
1210 |
+
#: methods/cloudfiles.php:335
|
|
|
|
|
|
|
1211 |
#, php-format
|
1212 |
msgid "%s is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your blog is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts."
|
1213 |
msgstr ""
|
1214 |
|
1215 |
+
#: methods/googledrive.php:340
|
1216 |
msgid "For longer help, including screenshots, follow this link. The description below is sufficient for more expert users."
|
1217 |
msgstr ""
|
1218 |
|
1219 |
+
#: methods/googledrive.php:341
|
1220 |
msgid "Follow this link to your Google API Console, and there create a Client ID in the API Access section."
|
1221 |
msgstr ""
|
1222 |
|
1223 |
+
#: methods/googledrive.php:341
|
1224 |
msgid "Select 'Web Application' as the application type."
|
1225 |
msgstr ""
|
1226 |
|
1227 |
+
#: methods/googledrive.php:341
|
1228 |
msgid "You must add the following as the authorised redirect URI (under \"More Options\") when asked"
|
1229 |
msgstr ""
|
1230 |
|
1231 |
+
#: methods/googledrive.php:341
|
1232 |
msgid "N.B. If you install UpdraftPlus on several WordPress sites, then you cannot re-use your client ID; you must create a new one from your Google API console for each blog."
|
1233 |
msgstr ""
|
1234 |
|
1235 |
+
#: methods/googledrive.php:344
|
1236 |
msgid "You do not have the SimpleXMLElement installed. Google Drive backups will <b>not</b> work until you do."
|
1237 |
msgstr ""
|
1238 |
|
1239 |
+
#: methods/googledrive.php:351
|
1240 |
msgid "Client ID"
|
1241 |
msgstr ""
|
1242 |
|
1243 |
+
#: methods/googledrive.php:352
|
1244 |
msgid "If Google later shows you the message \"invalid_client\", then you did not enter a valid client ID here."
|
1245 |
msgstr ""
|
1246 |
|
1247 |
+
#: methods/googledrive.php:355
|
1248 |
msgid "Client Secret"
|
1249 |
msgstr ""
|
1250 |
|
1251 |
+
#: methods/googledrive.php:359
|
1252 |
msgid "Folder ID"
|
1253 |
msgstr ""
|
1254 |
|
1255 |
+
#: methods/googledrive.php:360
|
1256 |
msgid "<strong>This is NOT a folder name</strong>. To get a folder's ID navigate to that folder in Google Drive in your web browser and copy the ID from your browser's address bar. It is the part that comes after <kbd>#folders/.</kbd> Leave empty to use your root folder)"
|
1257 |
msgstr ""
|
1258 |
|
1259 |
+
#: methods/googledrive.php:363
|
1260 |
msgid "Authenticate with Google"
|
1261 |
msgstr ""
|
1262 |
|
1263 |
+
#: methods/googledrive.php:364
|
1264 |
msgid "<strong>After</strong> you have saved your settings (by clicking 'Save Changes' below), then come back here once and click this link to complete authentication with Google."
|
1265 |
msgstr ""
|
1266 |
|
1267 |
+
#: methods/cloudfiles.php:58
|
1268 |
+
#: methods/cloudfiles.php:62
|
1269 |
+
#: methods/cloudfiles.php:219
|
1270 |
+
#: methods/cloudfiles.php:223
|
1271 |
+
#: methods/cloudfiles.php:429
|
1272 |
+
#: methods/cloudfiles.php:432
|
1273 |
+
#: methods/cloudfiles.php:435
|
1274 |
+
msgid "Cloud Files authentication failed"
|
1275 |
+
msgstr ""
|
1276 |
+
|
1277 |
+
#: methods/cloudfiles.php:66
|
1278 |
+
#: methods/cloudfiles.php:227
|
1279 |
+
#: methods/cloudfiles.php:244
|
1280 |
+
msgid "Cloud Files error - failed to create and access the container"
|
1281 |
+
msgstr ""
|
1282 |
+
|
1283 |
+
#: methods/cloudfiles.php:90
|
1284 |
+
#, php-format
|
1285 |
+
msgid "%s Error: Failed to open local file"
|
1286 |
+
msgstr ""
|
1287 |
+
|
1288 |
+
#: methods/cloudfiles.php:107
|
1289 |
+
#: methods/cloudfiles.php:148
|
1290 |
+
#, php-format
|
1291 |
+
msgid "%s Error: Failed to upload"
|
1292 |
+
msgstr ""
|
1293 |
+
|
1294 |
+
#: methods/cloudfiles.php:168
|
1295 |
+
msgid "Cloud Files error - failed to re-assemble chunks"
|
1296 |
+
msgstr ""
|
1297 |
+
|
1298 |
+
#: methods/cloudfiles.php:179
|
1299 |
+
#: methods/cloudfiles.php:180
|
1300 |
+
msgid "Cloud Files error - failed to upload file"
|
1301 |
+
msgstr ""
|
1302 |
+
|
1303 |
+
#: methods/cloudfiles.php:271
|
1304 |
+
#: methods/cloudfiles.php:288
|
1305 |
+
msgid "Cloud Files Error"
|
1306 |
+
msgstr ""
|
1307 |
+
|
1308 |
+
#: methods/cloudfiles.php:271
|
1309 |
+
msgid "Error opening local file: Failed to download"
|
1310 |
+
msgstr ""
|
1311 |
+
|
1312 |
+
#: methods/cloudfiles.php:288
|
1313 |
+
msgid "Error downloading remote file: Failed to download ("
|
1314 |
+
msgstr ""
|
1315 |
+
|
1316 |
+
#: methods/cloudfiles.php:297
|
1317 |
+
msgid "Cloud Files error - no such file exists at Cloud Files"
|
1318 |
+
msgstr ""
|
1319 |
+
|
1320 |
+
#: methods/cloudfiles.php:300
|
1321 |
+
#: methods/cloudfiles.php:301
|
1322 |
+
msgid "Cloud Files error - failed to download the file"
|
1323 |
+
msgstr ""
|
1324 |
+
|
1325 |
+
#: methods/cloudfiles.php:343
|
1326 |
+
msgid "Get your API key <a href=\"https://mycloud.rackspace.com/\">from your Rackspace Cloud console</a> (read instructions <a href=\"http://www.rackspace.com/knowledge_center/article/rackspace-cloud-essentials-1-generating-your-api-key\">here</a>), then pick a container name to use for storage. This container will be created for you if it does not already exist."
|
1327 |
+
msgstr ""
|
1328 |
+
|
1329 |
+
#: methods/cloudfiles.php:343
|
1330 |
+
msgid "Also, you should read this important FAQ."
|
1331 |
+
msgstr ""
|
1332 |
+
|
1333 |
+
#: methods/cloudfiles.php:347
|
1334 |
+
msgid "US or UK Cloud"
|
1335 |
+
msgstr ""
|
1336 |
+
|
1337 |
+
#: methods/cloudfiles.php:353
|
1338 |
+
msgid "US (default)"
|
1339 |
+
msgstr ""
|
1340 |
+
|
1341 |
+
#: methods/cloudfiles.php:354
|
1342 |
+
msgid "UK"
|
1343 |
+
msgstr ""
|
1344 |
+
|
1345 |
+
#: methods/cloudfiles.php:359
|
1346 |
+
msgid "Cloud Files username"
|
1347 |
+
msgstr ""
|
1348 |
+
|
1349 |
+
#: methods/cloudfiles.php:363
|
1350 |
+
msgid "Cloud Files API key"
|
1351 |
+
msgstr ""
|
1352 |
+
|
1353 |
+
#: methods/cloudfiles.php:367
|
1354 |
+
msgid "Cloud Files container"
|
1355 |
+
msgstr ""
|
1356 |
+
|
1357 |
+
#: methods/cloudfiles.php:377
|
1358 |
+
#, php-format
|
1359 |
+
msgid "UpdraftPlus's %s module <strong>requires</strong> %s. Please do not file any support requests; there is no alternative."
|
1360 |
+
msgstr ""
|
1361 |
+
|
1362 |
+
#: methods/cloudfiles.php:387
|
1363 |
+
#, php-format
|
1364 |
+
msgid "Test %s Settings"
|
1365 |
+
msgstr ""
|
1366 |
+
|
1367 |
+
#: methods/cloudfiles.php:395
|
1368 |
+
#: methods/cloudfiles.php:400
|
1369 |
+
#, php-format
|
1370 |
+
msgid "Failure: No %s was given."
|
1371 |
+
msgstr ""
|
1372 |
+
|
1373 |
+
#: methods/cloudfiles.php:395
|
1374 |
+
msgid "API key"
|
1375 |
+
msgstr ""
|
1376 |
+
|
1377 |
+
#: methods/cloudfiles.php:400
|
1378 |
+
msgid "Username"
|
1379 |
+
msgstr ""
|
1380 |
+
|
1381 |
+
#: methods/cloudfiles.php:420
|
1382 |
+
msgid "Failure: No container details were given."
|
1383 |
+
msgstr ""
|
1384 |
+
|
1385 |
+
#: methods/cloudfiles.php:445
|
1386 |
+
msgid "Cloud Files error - we accessed the container, but failed to create a file within it"
|
1387 |
+
msgstr ""
|
1388 |
+
|
1389 |
+
#: methods/cloudfiles.php:449
|
1390 |
+
msgid "We accessed the container, and were able to create files within it."
|
1391 |
+
msgstr ""
|
1392 |
+
|
1393 |
#: methods/email.php:15
|
1394 |
msgid "WordPress Backup"
|
1395 |
msgstr ""
|
1410 |
msgid "The email address entered above will be used. If choosing \"E-Mail\", then <strong>be aware</strong> that mail servers tend to have size limits; typically around 10-20Mb; backups larger than any limits will not arrive. If you really need a large backup via email, then you could fund a new feature (to break the backup set into configurable-size pieces) - but the demand has not yet existed for such a feature."
|
1411 |
msgstr ""
|
1412 |
|
1413 |
+
#: methods/s3.php:126
|
|
|
|
|
|
|
|
|
|
|
1414 |
msgid "S3 upload: getting uploadID for multipart upload failed - see log file for more details"
|
1415 |
msgstr ""
|
1416 |
|
1417 |
+
#: methods/s3.php:158
|
1418 |
#, php-format
|
1419 |
msgid "S3 chunk %s: upload failed"
|
1420 |
msgstr ""
|
1421 |
|
1422 |
+
#: methods/s3.php:172
|
1423 |
#, php-format
|
1424 |
msgid "S3 upload (%s): re-assembly failed (see log for more details)"
|
1425 |
msgstr ""
|
1426 |
|
1427 |
+
#: methods/s3.php:176
|
1428 |
#, php-format
|
1429 |
msgid "S3 re-assembly error (%s): (see log file for more)"
|
1430 |
msgstr ""
|
1431 |
|
1432 |
+
#: methods/s3.php:188
|
1433 |
#, php-format
|
1434 |
msgid "S3 Error: Failed to create bucket %s. Check your permissions and credentials."
|
1435 |
msgstr ""
|
1436 |
|
1437 |
+
#: methods/s3.php:243
|
1438 |
#, php-format
|
1439 |
msgid "S3 Error: Failed to download %s. Check your permissions and credentials."
|
1440 |
msgstr ""
|
1441 |
|
1442 |
+
#: methods/s3.php:247
|
1443 |
#, php-format
|
1444 |
msgid "S3 Error: Failed to access bucket %s. Check your permissions and credentials."
|
1445 |
msgstr ""
|
1446 |
|
1447 |
+
#: methods/s3.php:284
|
1448 |
msgid "Get your access key and secret key <a href=\"http://aws.amazon.com/console/\">from your AWS console</a>, then pick a (globally unique - all Amazon S3 users) bucket name (letters and numbers) (and optionally a path) to use for storage. This bucket will be created for you if it does not already exist."
|
1449 |
msgstr ""
|
1450 |
|
1451 |
+
#: methods/s3.php:284
|
1452 |
+
msgid "If you see errors about SSL certificates, then please go here for help."
|
1453 |
+
msgstr ""
|
1454 |
+
|
1455 |
+
#: methods/s3.php:287
|
1456 |
msgid "S3 access key"
|
1457 |
msgstr ""
|
1458 |
|
1459 |
+
#: methods/s3.php:291
|
1460 |
msgid "S3 secret key"
|
1461 |
msgstr ""
|
1462 |
|
1463 |
+
#: methods/s3.php:295
|
1464 |
msgid "S3 location"
|
1465 |
msgstr ""
|
1466 |
|
1467 |
+
#: methods/s3.php:319
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1468 |
msgid "API secret"
|
1469 |
msgstr ""
|
1470 |
|
1471 |
+
#: methods/s3.php:339
|
1472 |
msgid "Failure: No bucket details were given."
|
1473 |
msgstr ""
|
1474 |
|
1475 |
+
#: methods/s3.php:348
|
1476 |
msgid "Amazon region"
|
1477 |
msgstr ""
|
1478 |
|
1479 |
+
#: methods/s3.php:358
|
1480 |
msgid "Failure: We could not successfully access or create such a bucket. Please check your access credentials, and if those are correct then try another bucket name (as another S3 user may already have taken your name)."
|
1481 |
msgstr ""
|
1482 |
|
1483 |
+
#: methods/s3.php:368
|
1484 |
+
#: methods/s3.php:379
|
1485 |
msgid "Failure"
|
1486 |
msgstr ""
|
1487 |
|
1488 |
+
#: methods/s3.php:368
|
1489 |
+
#: methods/s3.php:379
|
1490 |
msgid "We successfully accessed the bucket, but the attempt to create a file in it failed."
|
1491 |
msgstr ""
|
1492 |
|
1493 |
+
#: methods/s3.php:370
|
1494 |
msgid "We accessed the bucket, and were able to create files within it."
|
1495 |
msgstr ""
|
1496 |
|
1497 |
+
#: methods/s3.php:372
|
1498 |
+
#, php-format
|
1499 |
+
msgid "The communication with %s was encrypted."
|
1500 |
+
msgstr ""
|
1501 |
+
|
1502 |
+
#: methods/s3.php:374
|
1503 |
+
#, php-format
|
1504 |
+
msgid "The communication with %s was not encrypted."
|
1505 |
+
msgstr ""
|
1506 |
+
|
1507 |
#: methods/dropbox.php:35
|
1508 |
#: methods/dropbox.php:167
|
1509 |
msgid "You do not appear to be authenticated with Dropbox"
|
1544 |
msgid "<strong>After</strong> you have saved your settings (by clicking 'Save Changes' below), then come back here once and click this link to complete authentication with Dropbox."
|
1545 |
msgstr ""
|
1546 |
|
1547 |
+
#: methods/dropbox.php:289
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1548 |
msgid "though part of the returned information was not as expected - your mileage may vary"
|
1549 |
msgstr ""
|
1550 |
|
1551 |
+
#: methods/dropbox.php:292
|
1552 |
#, php-format
|
1553 |
msgid "Your %s account name"
|
1554 |
msgstr ""
|
1555 |
|
1556 |
+
#: methods/ftp.php:30
|
1557 |
+
#: methods/ftp.php:80
|
1558 |
msgid "FTP login failure"
|
1559 |
msgstr ""
|
1560 |
|
1561 |
+
#: methods/ftp.php:49
|
1562 |
msgid "FTP upload failed"
|
1563 |
msgstr ""
|
1564 |
|
1565 |
+
#: methods/ftp.php:115
|
1566 |
msgid "Settings test result"
|
1567 |
msgstr ""
|
1568 |
|
1569 |
+
#: methods/ftp.php:131
|
1570 |
msgid "Only non-encrypted FTP is supported by regular UpdraftPlus."
|
1571 |
msgstr ""
|
1572 |
|
1573 |
+
#: methods/ftp.php:131
|
1574 |
msgid "If you want encryption (e.g. you are storing sensitive business data), then an add-on is available."
|
1575 |
msgstr ""
|
1576 |
|
1577 |
+
#: methods/ftp.php:135
|
1578 |
msgid "FTP Server"
|
1579 |
msgstr ""
|
1580 |
|
1581 |
+
#: methods/ftp.php:139
|
1582 |
msgid "FTP Login"
|
1583 |
msgstr ""
|
1584 |
|
1585 |
+
#: methods/ftp.php:143
|
1586 |
msgid "FTP Password"
|
1587 |
msgstr ""
|
1588 |
|
1589 |
+
#: methods/ftp.php:147
|
1590 |
msgid "Remote Path"
|
1591 |
msgstr ""
|
1592 |
|
1593 |
+
#: methods/ftp.php:148
|
1594 |
msgid "Needs to already exist"
|
1595 |
msgstr ""
|
1596 |
|
1597 |
+
#: methods/ftp.php:166
|
1598 |
msgid "Failure: No server details were given."
|
1599 |
msgstr ""
|
1600 |
|
1601 |
+
#: methods/ftp.php:181
|
1602 |
msgid "Failure: we did not successfully log in with those credentials."
|
1603 |
msgstr ""
|
1604 |
|
1605 |
+
#: methods/ftp.php:189
|
1606 |
msgid "Failure: an unexpected internal UpdraftPlus error occurred when testing the credentials - please contact the developer"
|
1607 |
msgstr ""
|
1608 |
|
1609 |
+
#: methods/ftp.php:193
|
1610 |
msgid "Success: we successfully logged in, and confirmed our ability to create a file in the given directory (login type:"
|
1611 |
msgstr ""
|
1612 |
|
1613 |
+
#: methods/ftp.php:196
|
1614 |
msgid "Failure: we successfully logged in, but were not able to create a file in the given directory."
|
1615 |
msgstr ""
|
1616 |
|
1617 |
#: addons/webdav.php:40
|
1618 |
#: addons/webdav.php:170
|
1619 |
+
#: addons/sftp.php:28
|
1620 |
#, php-format
|
1621 |
msgid "No %s settings were found"
|
1622 |
msgstr ""
|
1633 |
msgid "WebDAV Error"
|
1634 |
msgstr ""
|
1635 |
|
|
|
|
|
|
|
|
|
1636 |
#: addons/webdav.php:188
|
1637 |
msgid "Error opening remote file: Failed to download"
|
1638 |
msgstr ""
|
1651 |
msgstr ""
|
1652 |
|
1653 |
#: addons/webdav.php:281
|
1654 |
+
#: addons/sftp.php:281
|
1655 |
msgid "Failed"
|
1656 |
msgstr ""
|
1657 |
|
1659 |
msgid "Failed: We were not able to place a file in that directory - please check your credentials."
|
1660 |
msgstr ""
|
1661 |
|
1662 |
+
#: addons/morefiles.php:26
|
1663 |
+
msgid "The above files comprise everything in a WordPress installation."
|
1664 |
+
msgstr ""
|
1665 |
+
|
1666 |
+
#: addons/morefiles.php:34
|
1667 |
+
msgid "WordPress core (including any additions to your WordPress root directory)"
|
1668 |
+
msgstr ""
|
1669 |
+
|
1670 |
+
#: addons/morefiles.php:75
|
1671 |
+
#, php-format
|
1672 |
+
msgid "No backup of %s directories: there was nothing found to back up"
|
1673 |
+
msgstr ""
|
1674 |
+
|
1675 |
+
#: addons/morefiles.php:75
|
1676 |
+
msgid "WordPress Core"
|
1677 |
+
msgstr ""
|
1678 |
+
|
1679 |
+
#: addons/sftp.php:23
|
1680 |
+
msgid "Encrypted FTP is available, and will be automatically tried first (before falling back to non-encrypted if it is not successful), unless you disable it using the expert options. The 'Test FTP Login' button will tell you what type of connection is in use."
|
1681 |
+
msgstr ""
|
1682 |
+
|
1683 |
#: addons/sftp.php:23
|
1684 |
+
msgid "Some servers advertise encrypted FTP as available, but then time-out (after a long time, by which time when you attempt to use it. If you find this happenning, then go into the \"Expert Options\" (below) and turn off SSL there."
|
1685 |
msgstr ""
|
1686 |
|
1687 |
#: addons/sftp.php:30
|
1700 |
msgstr ""
|
1701 |
|
1702 |
#: addons/sftp.php:32
|
1703 |
+
msgid "SFTP password"
|
1704 |
msgstr ""
|
1705 |
|
1706 |
#: addons/sftp.php:50
|
1725 |
msgid "Port"
|
1726 |
msgstr ""
|
1727 |
|
|
|
|
|
|
|
|
|
1728 |
#: addons/sftp.php:198
|
1729 |
msgid "Password"
|
1730 |
msgstr ""
|
1767 |
msgid "Enter in format HH:MM (e.g. 14:22)"
|
1768 |
msgstr ""
|
1769 |
|
1770 |
+
#: addons/multisite.php:114
|
1771 |
msgid "Multisite Install"
|
1772 |
msgstr ""
|
1773 |
|
1774 |
+
#: addons/multisite.php:120
|
1775 |
msgid "You do not have sufficient permissions to access this page."
|
1776 |
msgstr ""
|
1777 |
|
1778 |
+
#: addons/multisite.php:139
|
1779 |
msgid "You do not have permission to access this page."
|
1780 |
msgstr ""
|
1781 |
|
1782 |
+
#: addons/multisite.php:195
|
1783 |
msgid "Must-use plugins"
|
1784 |
msgstr ""
|
1785 |
|
1786 |
+
#: addons/multisite.php:196
|
1787 |
msgid "Blog uploads"
|
1788 |
msgstr ""
|
1789 |
|
methods/cloudfiles.php
ADDED
@@ -0,0 +1,483 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
# TODO: Test again (some code has been changed)
|
4 |
+
# TODO: Implement list_dir (needed for deleting all potential chunks)
|
5 |
+
# TODO: In the delete method, we need to list all potential chunks, and delete them too.
|
6 |
+
# TODO: Change chunks to have names beginning with chunk-do-not-delete to avoid confusion
|
7 |
+
|
8 |
+
class UpdraftPlus_BackupModule_cloudfiles {
|
9 |
+
|
10 |
+
// This function does not catch any exceptions - that should be done by the caller
|
11 |
+
function getCF($user, $apikey, $authurl, $useservercerts = false) {
|
12 |
+
|
13 |
+
global $updraftplus;
|
14 |
+
|
15 |
+
if(!class_exists('CF_Authentication')) require_once(UPDRAFTPLUS_DIR.'/includes/cloudfiles/cloudfiles.php');
|
16 |
+
|
17 |
+
if (!defined('UPDRAFTPLUS_SSL_DISABLEVERIFY')) define('UPDRAFTPLUS_SSL_DISABLEVERIFY', UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify'));
|
18 |
+
|
19 |
+
$auth = new CF_Authentication($user, $apikey, NULL, $authurl);
|
20 |
+
|
21 |
+
$updraftplus->log("Cloud Files authentication URL: $authurl");
|
22 |
+
|
23 |
+
$auth->authenticate();
|
24 |
+
|
25 |
+
$conn = new CF_Connection($auth);
|
26 |
+
|
27 |
+
if (!$useservercerts) $conn->ssl_use_cabundle(UPDRAFTPLUS_DIR.'/includes/cacert.pem');
|
28 |
+
|
29 |
+
return $conn;
|
30 |
+
|
31 |
+
}
|
32 |
+
|
33 |
+
function backup($backup_array) {
|
34 |
+
|
35 |
+
global $updraftplus;
|
36 |
+
|
37 |
+
$updraft_dir = $updraftplus->backups_dir_location().'/';
|
38 |
+
$path = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_path'));
|
39 |
+
$authurl = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_authurl', 'https://auth.api.rackspacecloud.com');
|
40 |
+
|
41 |
+
// if (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) {
|
42 |
+
// $container = $bmatches[1];
|
43 |
+
// $path = $bmatches[2];
|
44 |
+
// } else {
|
45 |
+
// $container = $path;
|
46 |
+
// $path = "";
|
47 |
+
// }
|
48 |
+
$container = $path;
|
49 |
+
|
50 |
+
$user = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_user');
|
51 |
+
$apikey = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_apikey');
|
52 |
+
|
53 |
+
try {
|
54 |
+
$conn = $this->getCF($user, $apikey, $authurl, UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts'));
|
55 |
+
$cont_obj = $conn->create_container($container);
|
56 |
+
} catch(AuthenticationException $e) {
|
57 |
+
$updraftplus->log('Cloud Files authentication failed ('.$e->getMessage().')');
|
58 |
+
$updraftplus->error(__('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')');
|
59 |
+
return false;
|
60 |
+
} catch(NoSuchAccountException $s) {
|
61 |
+
$updraftplus->log('Cloud Files authentication failed ('.$e->getMessage().')');
|
62 |
+
$updraftplus->error(__('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')');
|
63 |
+
return false;
|
64 |
+
} catch (Exception $e) {
|
65 |
+
$updraftplus->log('Cloud Files error - failed to create and access the container ('.$e->getMessage().')');
|
66 |
+
$updraftplus->error(__('Cloud Files error - failed to create and access the container', 'updraftplus').' ('.$e->getMessage().')');
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
|
70 |
+
$chunk_size = 5*1024*1024;
|
71 |
+
|
72 |
+
foreach($backup_array as $key => $file) {
|
73 |
+
|
74 |
+
$fullpath = $updraft_dir.$file;
|
75 |
+
$orig_file_size = filesize($fullpath);
|
76 |
+
|
77 |
+
// $cfpath = ($path == '') ? $file : "$path/$file";
|
78 |
+
// $chunk_path = ($path == '') ? "chunk-do-not-delete-$file" : "$path/chunk-do-not-delete-$file";
|
79 |
+
$cfpath = $file;
|
80 |
+
$chunk_path = "chunk-do-not-delete-$file";
|
81 |
+
|
82 |
+
try {
|
83 |
+
$object = new CF_Object($cont_obj, $cfpath);
|
84 |
+
$object->content_type = "application/zip";
|
85 |
+
|
86 |
+
$uploaded_size = (isset($object->content_length)) ? $object->content_length : 0;
|
87 |
+
|
88 |
+
if ($uploaded_size <= $orig_file_size) {
|
89 |
+
|
90 |
+
$fp = @fopen($fullpath, "rb");
|
91 |
+
if (!$fp) {
|
92 |
+
$updraftplus->log("Cloud Files: failed to open file: $fullpath");
|
93 |
+
$updraftplus->error("$file: ".sprintf(__('%s Error: Failed to open local file','updraftplus'),'Cloud Files'));
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
|
97 |
+
$chunks = floor($orig_file_size / $chunk_size);
|
98 |
+
// There will be a remnant unless the file size was exactly on a 5Mb boundary
|
99 |
+
if ($orig_file_size % $chunk_size > 0 ) $chunks++;
|
100 |
+
|
101 |
+
$updraftplus->log("Cloud Files upload: $file (chunks: $chunks) -> cloudfiles://$container/$cfpath ($uploaded_size)");
|
102 |
+
|
103 |
+
if ($chunks < 2) {
|
104 |
+
try {
|
105 |
+
$object->load_from_filename($fullpath);
|
106 |
+
$updraftplus->log("Cloud Files regular upload: success");
|
107 |
+
$updraftplus->uploaded_file($file);
|
108 |
+
} catch (Exception $e) {
|
109 |
+
$updraftplus->log("Cloud Files regular upload: failed ($file) (".$e->getMessage().")");
|
110 |
+
$updraftplus->error("$file: ".sprintf(__('%s Error: Failed to upload','updraftplus'),'Cloud Files'));
|
111 |
+
}
|
112 |
+
} else {
|
113 |
+
$errors_so_far = 0;
|
114 |
+
for ($i = 1 ; $i <= $chunks; $i++) {
|
115 |
+
$upload_start = ($i-1)*$chunk_size;
|
116 |
+
$upload_end = min($i*$chunk_size-1, $orig_file_size);
|
117 |
+
$upload_remotepath = $chunk_path."_$i";
|
118 |
+
$upload_size = $upload_end - $upload_start;
|
119 |
+
|
120 |
+
$chunk_object = new CF_Object($cont_obj, $upload_remotepath);
|
121 |
+
$chunk_object->content_type = "application/zip";
|
122 |
+
// Without this, some versions of Curl add Expect: 100-continue, which results in Curl then giving this back: curl error: 55) select/poll returned error
|
123 |
+
// Didn't make the difference - instead we just check below for actual success even when Curl reports an error
|
124 |
+
// $chunk_object->headers = array('Expect' => '');
|
125 |
+
|
126 |
+
$remote_size = (isset($chunk_object->content_length)) ? $chunk_object->content_length : 0;
|
127 |
+
|
128 |
+
if ($remote_size >= $upload_size) {
|
129 |
+
$updraftplus->log("Cloud Files: Chunk $i ($upload_start - $upload_end): already uploaded");
|
130 |
+
} else {
|
131 |
+
$updraftplus->log("Cloud Files: Chunk $i ($upload_start - $upload_end): begin upload");
|
132 |
+
// Upload the chunk
|
133 |
+
fseek($fp, $upload_start);
|
134 |
+
try {
|
135 |
+
$chunk_object->write($fp, $upload_size, false);
|
136 |
+
$updraftplus->record_uploaded_chunk(round(100*$i/$chunks,1), $i, $fullpath);
|
137 |
+
} catch (Exception $e) {
|
138 |
+
$updraftplus->log("Cloud Files chunk upload: error: ($file / $i) (".$e->getMessage().")");
|
139 |
+
// Experience shows that Curl sometimes returns a select/poll error (curl error 55) even when everything succeeded. Google seems to indicate that this is a known bug.
|
140 |
+
|
141 |
+
$chunk_object = new CF_Object($cont_obj, $upload_remotepath);
|
142 |
+
$chunk_object->content_type = "application/zip";
|
143 |
+
$remote_size = (isset($chunk_object->content_length)) ? $chunk_object->content_length : 0;
|
144 |
+
|
145 |
+
if ($remote_size >= $upload_size) {
|
146 |
+
|
147 |
+
$updraftplus->log("$file: Chunk now exists; ignoring error (presuming it was an apparently known curl bug)");
|
148 |
+
|
149 |
+
} else {
|
150 |
+
|
151 |
+
$updraftplus->error("$file: ".sprintf(__('%s Error: Failed to upload','updraftplus'),'Cloud Files'));
|
152 |
+
$errors_so_far++;
|
153 |
+
if ($errors_so_far >=3 ) return false;
|
154 |
+
|
155 |
+
}
|
156 |
+
|
157 |
+
}
|
158 |
+
}
|
159 |
+
}
|
160 |
+
if ($errors_so_far) return false;
|
161 |
+
// All chunks are uploaded - now upload the manifest
|
162 |
+
|
163 |
+
try {
|
164 |
+
$object->manifest = $container."/".$chunk_path."_";
|
165 |
+
// Put a zero-length file
|
166 |
+
$object->write("", 0, false);
|
167 |
+
$object->sync_manifest();
|
168 |
+
$updraftplus->log("Cloud Files upload: success");
|
169 |
+
$updraftplus->uploaded_file($file);
|
170 |
+
// } catch (InvalidResponseException $e) {
|
171 |
+
} catch (Exception $e) {
|
172 |
+
$updraftplus->log('Cloud Files error - failed to re-assemble chunks ('.$e->getMessage().')');
|
173 |
+
$updraftplus->error(__('Cloud Files error - failed to re-assemble chunks', 'updraftplus').' ('.$e->getMessage().')');
|
174 |
+
return false;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
}
|
179 |
+
|
180 |
+
|
181 |
+
} catch (Exception $e) {
|
182 |
+
$updraftplus->log(__('Cloud Files error - failed to upload file', 'updraftplus').' ('.$e->getMessage().')');
|
183 |
+
$updraftplus->error(__('Cloud Files error - failed to upload file', 'updraftplus').' ('.$e->getMessage().')');
|
184 |
+
return false;
|
185 |
+
}
|
186 |
+
|
187 |
+
}
|
188 |
+
|
189 |
+
$updraftplus->prune_retained_backups('cloudfiles', $this, array('cloudfiles_object' => $cont_obj, 'cloudfiles_orig_path' => $path, 'cloudfiles_container' => $container));
|
190 |
+
|
191 |
+
}
|
192 |
+
|
193 |
+
function delete($file, $cloudfilesarr) {
|
194 |
+
|
195 |
+
global $updraftplus;
|
196 |
+
|
197 |
+
$cont_obj = $cloudfilesarr['cloudfiles_object'];
|
198 |
+
$container = $cloudfilesarr['cloudfiles_container'];
|
199 |
+
$path = $cloudfilesarr['cloudfiles_orig_path'];
|
200 |
+
// $fpath = ($path == '') ? $file : "$path/$file";
|
201 |
+
$fpath = $file;
|
202 |
+
|
203 |
+
$updraftplus->log("Cloud Files: Delete remote: container=$container, path=$fpath");
|
204 |
+
|
205 |
+
// We need to search for chunks
|
206 |
+
//$chunk_path = ($path == '') ? "chunk-do-not-delete-$file_" : "$path/chunk-do-not-delete-$file_";
|
207 |
+
$chunk_path = "chunk-do-not-delete-$file";
|
208 |
+
|
209 |
+
try {
|
210 |
+
$objects = $cont_obj->list_objects(0, NULL, $chunk_path.'_');
|
211 |
+
foreach ($objects as $chunk) {
|
212 |
+
$updraftplus->log('Cloud Files: Chunk to delete: '.$chunk);
|
213 |
+
$cont_obj->delete_object($chunk);
|
214 |
+
$updraftplus->log('Cloud Files: Chunk deleted: '.$chunk);
|
215 |
+
}
|
216 |
+
} catch (Exception $e) {
|
217 |
+
$updraftplus->log('Cloud Files chunk delete failed: '.$e->getMessage());
|
218 |
+
}
|
219 |
+
|
220 |
+
try {
|
221 |
+
$cont_obj->delete_object($fpath);
|
222 |
+
$updraftplus->log('Cloud Files: Deleted: '.$fpath);
|
223 |
+
} catch (Exception $e) {
|
224 |
+
$updraftplus->log('Cloud Files delete failed: '.$e->getMessage());
|
225 |
+
}
|
226 |
+
|
227 |
+
}
|
228 |
+
|
229 |
+
function download($file) {
|
230 |
+
|
231 |
+
global $updraftplus;
|
232 |
+
$updraft_dir = $updraftplus->backups_dir_location();
|
233 |
+
|
234 |
+
$user = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_user');
|
235 |
+
$apikey = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_apikey');
|
236 |
+
$authurl = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_authurl');
|
237 |
+
|
238 |
+
try {
|
239 |
+
$conn = $this->getCF($user, $apikey, $authurl, UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts'));
|
240 |
+
} catch(AuthenticationException $e) {
|
241 |
+
$updraftplus->log('Cloud Files authentication failed ('.$e->getMessage().')');
|
242 |
+
$updraftplus->error(__('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')');
|
243 |
+
return false;
|
244 |
+
} catch(NoSuchAccountException $s) {
|
245 |
+
$updraftplus->log('Cloud Files authentication failed ('.$e->getMessage().')');
|
246 |
+
$updraftplus->error(__('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')');
|
247 |
+
return false;
|
248 |
+
} catch (Exception $e) {
|
249 |
+
$updraftplus->log('Cloud Files error - failed to create and access the container ('.$e->getMessage().')');
|
250 |
+
$updraftplus->error(__('Cloud Files error - failed to create and access the container', 'updraftplus').' ('.$e->getMessage().')');
|
251 |
+
return;
|
252 |
+
}
|
253 |
+
|
254 |
+
$path = untrailingslashit(get_option('updraft_cloudfiles_path'));
|
255 |
+
|
256 |
+
// if (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) {
|
257 |
+
// $container = $bmatches[1];
|
258 |
+
// $path = $bmatches[2];
|
259 |
+
// } else {
|
260 |
+
// $container = $path;
|
261 |
+
// $path = "";
|
262 |
+
// }
|
263 |
+
$container = $path;
|
264 |
+
|
265 |
+
try {
|
266 |
+
$cont_obj = $conn->create_container($container);
|
267 |
+
} catch(Exception $e) {
|
268 |
+
$updraftplus->error(__('Cloud Files error - failed to create and access the container','updraftplus').' ('.$e->getMessage().')');
|
269 |
+
}
|
270 |
+
|
271 |
+
// $path = ($path == '') ? $file : "$path/$file";
|
272 |
+
$path = $file;
|
273 |
+
|
274 |
+
$updraftplus->log("Cloud Files download: cloudfiles://$container/$path");
|
275 |
+
|
276 |
+
try {
|
277 |
+
// The third parameter causes an exception to be thrown if the object does not exist remotely
|
278 |
+
$object = new CF_Object($cont_obj, $path, true);
|
279 |
+
|
280 |
+
$fullpath = $updraft_dir.'/'.$file;
|
281 |
+
|
282 |
+
$start_offset = (file_exists($fullpath)) ? filesize($fullpath): 0;
|
283 |
+
|
284 |
+
// Get file size from remote - see if we've already finished
|
285 |
+
|
286 |
+
$remote_size = $object->content_length;
|
287 |
+
|
288 |
+
if ($start_offset >= $remote_size) {
|
289 |
+
$updraftplus->log("Cloud Files: file is already completely downloaded ($start_offset/$remote_size)");
|
290 |
+
return true;
|
291 |
+
}
|
292 |
+
|
293 |
+
// Some more remains to download - so let's do it
|
294 |
+
if (!$fh = fopen($fullpath, 'a')) {
|
295 |
+
$updraftplus->log("Cloud Files: Error opening local file: $fullpath");
|
296 |
+
$updraftplus->error("$file: ".__("Cloud Files Error",'updraftplus').": ".__('Error opening local file: Failed to download','updraftplus'));
|
297 |
+
return false;
|
298 |
+
}
|
299 |
+
|
300 |
+
$headers = array();
|
301 |
+
// If resuming, then move to the end of the file
|
302 |
+
if ($start_offset) {
|
303 |
+
$updraftplus->log("Cloud Files: local file is already partially downloaded ($start_offset/$remote_size)");
|
304 |
+
fseek($fh, $start_offset);
|
305 |
+
$headers['Range'] = "bytes=$start_offset-";
|
306 |
+
}
|
307 |
+
|
308 |
+
// Now send the request itself
|
309 |
+
try {
|
310 |
+
$object->stream($fh, $headers);
|
311 |
+
} catch (Exception $e) {
|
312 |
+
$updraftplus->log("Cloud Files: Failed to download: $file (".$e->getMessage().")");
|
313 |
+
$updraftplus->error("$file: ".__("Cloud Files Error",'updraftplus').": ".__('Error downloading remote file: Failed to download'.' ('.$e->getMessage().")",'updraftplus'));
|
314 |
+
return false;
|
315 |
+
}
|
316 |
+
|
317 |
+
// All-in-one-go method:
|
318 |
+
// $object->save_to_filename($fullpath);
|
319 |
+
|
320 |
+
} catch (NoSuchObjectException $e) {
|
321 |
+
$updraftplus->log('Cloud Files error - no such file exists at Cloud Files ('.$e->getMessage().')');
|
322 |
+
$updraftplus->error(__('Cloud Files error - no such file exists at Cloud Files','updraftplus').' ('.$e->getMessage().')');
|
323 |
+
return false;
|
324 |
+
} catch(Exception $e) {
|
325 |
+
$updraftplus->log('Cloud Files error - failed to download the file ('.$e->getMessage().')');
|
326 |
+
$updraftplus->error(__('Cloud Files error - failed to download the file','updraftplus').' ('.$e->getMessage().')');
|
327 |
+
return false;
|
328 |
+
}
|
329 |
+
|
330 |
+
}
|
331 |
+
|
332 |
+
public static function config_print_javascript_onready() {
|
333 |
+
?>
|
334 |
+
jQuery('#updraft-cloudfiles-test').click(function(){
|
335 |
+
jQuery(this).html('<?php echo __('Testing - Please Wait...','updraftplus');?>');
|
336 |
+
var data = {
|
337 |
+
action: 'updraft_ajax',
|
338 |
+
subaction: 'credentials_test',
|
339 |
+
method: 'cloudfiles',
|
340 |
+
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>',
|
341 |
+
apikey: jQuery('#updraft_cloudfiles_apikey').val(),
|
342 |
+
user: jQuery('#updraft_cloudfiles_user').val(),
|
343 |
+
path: jQuery('#updraft_cloudfiles_path').val(),
|
344 |
+
authurl: jQuery('#updraft_cloudfiles_authurl').val(),
|
345 |
+
useservercerts: jQuery('#updraft_cloudfiles_useservercerts').val(),
|
346 |
+
disableverify: jQuery('#updraft_ssl_disableverify').val()
|
347 |
+
};
|
348 |
+
jQuery.post(ajaxurl, data, function(response) {
|
349 |
+
jQuery('#updraft-cloudfiles-test').html('<?php echo sprintf(__('Test %s Settings','updraftplus'),'Cloud Files');?>');
|
350 |
+
alert('Settings test result: ' + response);
|
351 |
+
});
|
352 |
+
});
|
353 |
+
<?php
|
354 |
+
}
|
355 |
+
|
356 |
+
public static function config_print() {
|
357 |
+
|
358 |
+
?>
|
359 |
+
<tr class="updraftplusmethod cloudfiles">
|
360 |
+
<td></td>
|
361 |
+
<td><img alt="Rackspace Cloud Files" src="<?php echo UPDRAFTPLUS_URL.'/images/rackspacecloud-logo.png' ?>">
|
362 |
+
<p><em><?php printf(__('%s is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your blog is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts.','updraftplus'),'Rackspace Cloud Files');?></em></p></td>
|
363 |
+
</tr>
|
364 |
+
|
365 |
+
|
366 |
+
|
367 |
+
<tr class="updraftplusmethod cloudfiles">
|
368 |
+
<th></th>
|
369 |
+
<td>
|
370 |
+
<p><?php _e('Get your API key <a href="https://mycloud.rackspace.com/">from your Rackspace Cloud console</a> (read instructions <a href="http://www.rackspace.com/knowledge_center/article/rackspace-cloud-essentials-1-generating-your-api-key">here</a>), then pick a container name to use for storage. This container will be created for you if it does not already exist.','updraftplus');?>. <a href="http://updraftplus.com/faqs/there-appear-to-be-lots-of-extra-files-in-my-rackspace-cloud-files-container/"><?php _e('Also, you should read this important FAQ.', 'updraftplus'); ?></a></p>
|
371 |
+
</td>
|
372 |
+
</tr>
|
373 |
+
<tr class="updraftplusmethod cloudfiles">
|
374 |
+
<th><?php _e('US or UK Cloud','updraftplus');?>:</th>
|
375 |
+
<td>
|
376 |
+
<?php
|
377 |
+
$authurl = UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_authurl');
|
378 |
+
?>
|
379 |
+
<select id="updraft_cloudfiles_authurl" name="updraft_cloudfiles_authurl">
|
380 |
+
<option <?php if ($authurl !='https://lon.auth.api.rackspacecloud.com') echo 'selected="selected"'; ?> value="https://auth.api.rackspacecloud.com"><?php _e('US (default)','updraftplus'); ?></option>
|
381 |
+
<option <?php if ($authurl =='https://lon.auth.api.rackspacecloud.com') echo 'selected="selected"'; ?> value="https://lon.auth.api.rackspacecloud.com"><?php _e('UK', 'updraftplus'); ?></option>
|
382 |
+
</select>
|
383 |
+
</td>
|
384 |
+
</tr>
|
385 |
+
<tr class="updraftplusmethod cloudfiles">
|
386 |
+
<th><?php _e('Cloud Files username','updraftplus');?>:</th>
|
387 |
+
<td><input type="text" autocomplete="off" style="width: 252px" id="updraft_cloudfiles_user" name="updraft_cloudfiles_user" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_user')) ?>" /></td>
|
388 |
+
</tr>
|
389 |
+
<tr class="updraftplusmethod cloudfiles">
|
390 |
+
<th><?php _e('Cloud Files API key','updraftplus');?>:</th>
|
391 |
+
<td><input type="text" autocomplete="off" style="width: 252px" id="updraft_cloudfiles_apikey" name="updraft_cloudfiles_apikey" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_apikey')); ?>" /></td>
|
392 |
+
</tr>
|
393 |
+
<tr class="updraftplusmethod cloudfiles">
|
394 |
+
<th><?php echo apply_filters('updraftplus_cloudfiles_location_description',__('Cloud Files container','updraftplus'));?>:</th>
|
395 |
+
<td><input type="text" style="width: 252px" name="updraft_cloudfiles_path" id="updraft_cloudfiles_path" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_cloudfiles_path')); ?>" /></td>
|
396 |
+
</tr>
|
397 |
+
|
398 |
+
<tr class="updraftplusmethod cloudfiles">
|
399 |
+
<th></th>
|
400 |
+
<td>
|
401 |
+
<?php
|
402 |
+
// Check requirements.
|
403 |
+
if (!function_exists('mb_substr')) {
|
404 |
+
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php echo sprintf(__('Your web server\'s PHP installation does not included a required module (%s). Please contact your web hosting provider\'s support.', 'updraftplus'), 'mbstring'); ?> <?php echo sprintf(__("UpdraftPlus's %s module <strong>requires</strong> %s. Please do not file any support requests; there is no alternative.",'updraftplus'),'Cloud Files', 'mbstring');?></p><?php
|
405 |
+
}
|
406 |
+
global $updraftplus_admin;
|
407 |
+
$updraftplus_admin->curl_check('Rackspace Cloud Files', false);
|
408 |
+
?>
|
409 |
+
</td>
|
410 |
+
</tr>
|
411 |
+
|
412 |
+
<tr class="updraftplusmethod cloudfiles">
|
413 |
+
<th></th>
|
414 |
+
<td><p><button id="updraft-cloudfiles-test" type="button" class="button-primary" style="font-size:18px !important"><?php echo sprintf(__('Test %s Settings','updraftplus'),'Cloud Files');?></button></p></td>
|
415 |
+
</tr>
|
416 |
+
<?php
|
417 |
+
}
|
418 |
+
|
419 |
+
public static function credentials_test() {
|
420 |
+
|
421 |
+
if (empty($_POST['apikey'])) {
|
422 |
+
printf(__("Failure: No %s was given.",'updraftplus'),__('API key','updraftplus'));
|
423 |
+
return;
|
424 |
+
}
|
425 |
+
|
426 |
+
if (empty($_POST['user'])) {
|
427 |
+
printf(__("Failure: No %s was given.",'updraftplus'),__('Username','updraftplus'));
|
428 |
+
return;
|
429 |
+
}
|
430 |
+
|
431 |
+
$key = $_POST['apikey'];
|
432 |
+
$user = $_POST['user'];
|
433 |
+
$path = $_POST['path'];
|
434 |
+
$authurl = $_POST['authurl'];
|
435 |
+
$useservercerts = $_POST['useservercerts'];
|
436 |
+
$disableverify = $_POST['disableverify'];
|
437 |
+
|
438 |
+
if (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) {
|
439 |
+
$container = $bmatches[1];
|
440 |
+
$path = $bmatches[2];
|
441 |
+
} else {
|
442 |
+
$container = $path;
|
443 |
+
$path = "";
|
444 |
+
}
|
445 |
+
|
446 |
+
if (empty($container)) {
|
447 |
+
_e("Failure: No container details were given.",'updraftplus');
|
448 |
+
return;
|
449 |
+
}
|
450 |
+
|
451 |
+
define('UPDRAFTPLUS_SSL_DISABLEVERIFY', $disableverify);
|
452 |
+
|
453 |
+
try {
|
454 |
+
$conn = self::getCF($user, $key, $authurl, $useservercerts);
|
455 |
+
$cont_obj = $conn->create_container($container);
|
456 |
+
} catch(AuthenticationException $e) {
|
457 |
+
echo __('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')';
|
458 |
+
die;
|
459 |
+
} catch(NoSuchAccountException $s) {
|
460 |
+
echo __('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')';
|
461 |
+
die;
|
462 |
+
} catch (Exception $e) {
|
463 |
+
echo __('Cloud Files authentication failed','updraftplus').' ('.$e->getMessage().')';
|
464 |
+
die;
|
465 |
+
}
|
466 |
+
|
467 |
+
$try_file = md5(rand());
|
468 |
+
|
469 |
+
try {
|
470 |
+
$object = $cont_obj->create_object($try_file);
|
471 |
+
$object->write('UpdraftPlus test file');
|
472 |
+
} catch (Exception $e) {
|
473 |
+
echo __('Cloud Files error - we accessed the container, but failed to create a file within it', 'updraftplus').' ('.$e->getMessage().')';
|
474 |
+
return;
|
475 |
+
}
|
476 |
+
|
477 |
+
echo __('Success','updraftplus').": ${container_verb}".__('We accessed the container, and were able to create files within it.','updraftplus');
|
478 |
+
|
479 |
+
@$cont_obj->delete_object($try_file);
|
480 |
+
}
|
481 |
+
|
482 |
+
}
|
483 |
+
?>
|
methods/dropbox.php
CHANGED
@@ -237,17 +237,10 @@ class UpdraftPlus_BackupModule_dropbox {
|
|
237 |
<?php
|
238 |
// Check requirements.
|
239 |
if (!function_exists('mcrypt_encrypt')) {
|
240 |
-
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php
|
241 |
-
}
|
242 |
-
if (!function_exists("curl_init")) {
|
243 |
-
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php _e("Your web server's PHP installation does not included a required module (Curl). Please contact your web hosting provider's support. UpdraftPlus's Dropbox module <strong>requires</strong> Curl. Your only options to get this working are 1) Install/enable curl or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this.",'updraftplus');?></p><?php
|
244 |
-
} else {
|
245 |
-
$curl_version = curl_version();
|
246 |
-
$curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
|
247 |
-
if (!$curl_ssl_supported) {
|
248 |
-
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php _e("Your web server's PHP/Curl installation does not support https access. We cannot access Dropbox without this support. Please contact your web hosting provider's support. UpdraftPlus's Dropbox module <strong>requires</strong> Curl+https. Your only options to get this working are 1) Install/enable curl with https or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this.",'updraftplus');?></p><?php
|
249 |
-
}
|
250 |
}
|
|
|
|
|
251 |
?>
|
252 |
</td>
|
253 |
</tr>
|
237 |
<?php
|
238 |
// Check requirements.
|
239 |
if (!function_exists('mcrypt_encrypt')) {
|
240 |
+
?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php echo sprintf(__('Your web server\'s PHP installation does not included a required module (%s). Please contact your web hosting provider\'s support.', 'updraftplus'), 'mcrypt'); ?> <?php echo sprintf(__("UpdraftPlus's %s module <strong>requires</strong> %s. Please do not file any support requests; there is no alternative.",'updraftplus'),'Dropbox', 'mcrypt');?></p><?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
}
|
242 |
+
global $updraftplus_admin;
|
243 |
+
$updraftplus_admin->curl_check('Dropbox', false);
|
244 |
?>
|
245 |
</td>
|
246 |
</tr>
|
methods/ftp.php
CHANGED
@@ -2,17 +2,28 @@
|
|
2 |
|
3 |
class UpdraftPlus_BackupModule_ftp {
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
function backup($backup_array) {
|
6 |
|
7 |
global $updraftplus;
|
8 |
|
9 |
-
if( !class_exists('UpdraftPlus_ftp_wrapper')) require_once(UPDRAFTPLUS_DIR.'/includes/ftp.class.php');
|
10 |
-
|
11 |
$server = UpdraftPlus_Options::get_updraft_option('updraft_server_address');
|
12 |
-
|
13 |
$user = UpdraftPlus_Options::get_updraft_option('updraft_ftp_login');
|
14 |
-
|
15 |
-
$ftp
|
16 |
|
17 |
if (!$ftp->connect()) {
|
18 |
$updraftplus->log("FTP Failure: we did not successfully log in with those credentials.");
|
@@ -30,7 +41,7 @@ class UpdraftPlus_BackupModule_ftp {
|
|
30 |
$updraftplus->log("FTP upload attempt: $file -> ftp://$user@$server/${ftp_remote_path}${file}");
|
31 |
$timer_start = microtime(true);
|
32 |
$size_k = round(filesize($fullpath)/1024,1);
|
33 |
-
if ($ftp->put($fullpath, $ftp_remote_path.$file, FTP_BINARY)) {
|
34 |
$updraftplus->log("FTP upload attempt successful (".$size_k."Kb in ".(round(microtime(true)-$timer_start,2)).'s)');
|
35 |
$updraftplus->uploaded_file($file);
|
36 |
} else {
|
@@ -58,9 +69,11 @@ class UpdraftPlus_BackupModule_ftp {
|
|
58 |
|
59 |
global $updraftplus;
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
64 |
|
65 |
if (!$ftp->connect()) {
|
66 |
$updraftplus->log("FTP Failure: we did not successfully log in with those credentials.");
|
@@ -73,7 +86,13 @@ class UpdraftPlus_BackupModule_ftp {
|
|
73 |
$ftp_remote_path = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
|
74 |
$fullpath = $updraftplus->backups_dir_location().'/'.$file;
|
75 |
|
76 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
}
|
78 |
|
79 |
public static function config_print_javascript_onready() {
|
@@ -87,7 +106,10 @@ class UpdraftPlus_BackupModule_ftp {
|
|
87 |
server: jQuery('#updraft_server_address').val(),
|
88 |
login: jQuery('#updraft_ftp_login').val(),
|
89 |
pass: jQuery('#updraft_ftp_pass').val(),
|
90 |
-
path: jQuery('#updraft_ftp_remote_path').val()
|
|
|
|
|
|
|
91 |
};
|
92 |
jQuery.post(ajaxurl, data, function(response) {
|
93 |
alert('<?php _e('Settings test result','updraftplus');?>: ' + response);
|
@@ -99,9 +121,14 @@ class UpdraftPlus_BackupModule_ftp {
|
|
99 |
public static function config_print() {
|
100 |
?>
|
101 |
|
|
|
|
|
|
|
|
|
|
|
102 |
<tr class="updraftplusmethod ftp">
|
103 |
<th></th>
|
104 |
-
<td><em><?php echo apply_filters('updraft_sftp_ftps_notice', '<strong>'.__('Only non-encrypted FTP is supported by regular UpdraftPlus.').'</strong> <a href="http://updraftplus.com/shop/sftp/">'.__('If you want encryption (e.g. you are storing sensitive business data), then an add-on is available.','updraftplus')).'</a>'; ?></em></td>
|
105 |
</tr>
|
106 |
|
107 |
<tr class="updraftplusmethod ftp">
|
@@ -133,6 +160,7 @@ class UpdraftPlus_BackupModule_ftp {
|
|
133 |
$login = $_POST['login'];
|
134 |
$pass = $_POST['pass'];
|
135 |
$path = $_POST['path'];
|
|
|
136 |
|
137 |
if (empty($server)) {
|
138 |
_e("Failure: No server details were given.",'updraftplus');
|
@@ -147,11 +175,7 @@ class UpdraftPlus_BackupModule_ftp {
|
|
147 |
return;
|
148 |
}
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
//handle SSL and errors at some point TODO
|
153 |
-
$ftp = new UpdraftPlus_ftp_wrapper($server, $login, $pass);
|
154 |
-
$ftp->passive = true;
|
155 |
|
156 |
if (!$ftp->connect()) {
|
157 |
_e("Failure: we did not successfully log in with those credentials.",'updraftplus');
|
@@ -165,7 +189,7 @@ class UpdraftPlus_BackupModule_ftp {
|
|
165 |
_e("Failure: an unexpected internal UpdraftPlus error occurred when testing the credentials - please contact the developer");
|
166 |
return;
|
167 |
}
|
168 |
-
if ($ftp->put(ABSPATH.'wp-includes/version.php', $fullpath, FTP_BINARY)) {
|
169 |
echo __("Success: we successfully logged in, and confirmed our ability to create a file in the given directory (login type:",'updraftplus')." ".$ftp->login_type.')';
|
170 |
@$ftp->delete($fullpath);
|
171 |
} else {
|
@@ -176,4 +200,4 @@ class UpdraftPlus_BackupModule_ftp {
|
|
176 |
|
177 |
}
|
178 |
|
179 |
-
?>
|
2 |
|
3 |
class UpdraftPlus_BackupModule_ftp {
|
4 |
|
5 |
+
// Get FTP object with parameters set
|
6 |
+
function getFTP($server, $user, $pass, $disable_ssl = false, $passive = true) {
|
7 |
+
|
8 |
+
if( !class_exists('UpdraftPlus_ftp_wrapper')) require_once(UPDRAFTPLUS_DIR.'/includes/ftp.class.php');
|
9 |
+
|
10 |
+
$ftp = new UpdraftPlus_ftp_wrapper($server, $user, $pass);
|
11 |
+
|
12 |
+
if ($disable_ssl) $ftp->ssl = false;
|
13 |
+
if ($passive) $ftp->passive = true;
|
14 |
+
|
15 |
+
return $ftp;
|
16 |
+
|
17 |
+
}
|
18 |
+
|
19 |
function backup($backup_array) {
|
20 |
|
21 |
global $updraftplus;
|
22 |
|
|
|
|
|
23 |
$server = UpdraftPlus_Options::get_updraft_option('updraft_server_address');
|
|
|
24 |
$user = UpdraftPlus_Options::get_updraft_option('updraft_ftp_login');
|
25 |
+
|
26 |
+
$ftp = $this->getFTP($server, $user, UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl'));
|
27 |
|
28 |
if (!$ftp->connect()) {
|
29 |
$updraftplus->log("FTP Failure: we did not successfully log in with those credentials.");
|
41 |
$updraftplus->log("FTP upload attempt: $file -> ftp://$user@$server/${ftp_remote_path}${file}");
|
42 |
$timer_start = microtime(true);
|
43 |
$size_k = round(filesize($fullpath)/1024,1);
|
44 |
+
if ($ftp->put($fullpath, $ftp_remote_path.$file, FTP_BINARY, true, $updraftplus)) {
|
45 |
$updraftplus->log("FTP upload attempt successful (".$size_k."Kb in ".(round(microtime(true)-$timer_start,2)).'s)');
|
46 |
$updraftplus->uploaded_file($file);
|
47 |
} else {
|
69 |
|
70 |
global $updraftplus;
|
71 |
|
72 |
+
$ftp = $this->getFTP(
|
73 |
+
UpdraftPlus_Options::get_updraft_option('updraft_server_address'),
|
74 |
+
UpdraftPlus_Options::get_updraft_option('updraft_ftp_login'),
|
75 |
+
UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')
|
76 |
+
);
|
77 |
|
78 |
if (!$ftp->connect()) {
|
79 |
$updraftplus->log("FTP Failure: we did not successfully log in with those credentials.");
|
86 |
$ftp_remote_path = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
|
87 |
$fullpath = $updraftplus->backups_dir_location().'/'.$file;
|
88 |
|
89 |
+
$resume = false;
|
90 |
+
if (file_exists($fullpath)) {
|
91 |
+
$resume = true;
|
92 |
+
$updraftplus->log("File already exists locally; will resume: size: ".filesize($fullpath));
|
93 |
+
}
|
94 |
+
|
95 |
+
$ftp->get($fullpath, $ftp_remote_path.$file, FTP_BINARY, $resume, $updraftplus);
|
96 |
}
|
97 |
|
98 |
public static function config_print_javascript_onready() {
|
106 |
server: jQuery('#updraft_server_address').val(),
|
107 |
login: jQuery('#updraft_ftp_login').val(),
|
108 |
pass: jQuery('#updraft_ftp_pass').val(),
|
109 |
+
path: jQuery('#updraft_ftp_remote_path').val(),
|
110 |
+
disableverify: (jQuery('#updraft_ssl_disableverify').is(':checked')) ? 1 : 0,
|
111 |
+
useservercerts: (jQuery('#updraft_ssl_useservercerts').is(':checked')) ? 1 : 0,
|
112 |
+
nossl: (jQuery('#updraft_ssl_nossl').is(':checked')) ? 1 : 0,
|
113 |
};
|
114 |
jQuery.post(ajaxurl, data, function(response) {
|
115 |
alert('<?php _e('Settings test result','updraftplus');?>: ' + response);
|
121 |
public static function config_print() {
|
122 |
?>
|
123 |
|
124 |
+
<tr class="updraftplusmethod ftp">
|
125 |
+
<td></td>
|
126 |
+
<td><p><em><?php printf(__('%s is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your blog is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts.','updraftplus'),'FTP');?></em></p></td>
|
127 |
+
</tr>
|
128 |
+
|
129 |
<tr class="updraftplusmethod ftp">
|
130 |
<th></th>
|
131 |
+
<td><em><?php echo apply_filters('updraft_sftp_ftps_notice', '<strong>'.htmlspecialchars(__('Only non-encrypted FTP is supported by regular UpdraftPlus.').'</strong> <a href="http://updraftplus.com/shop/sftp/">'.__('If you want encryption (e.g. you are storing sensitive business data), then an add-on is available.','updraftplus'))).'</a>'; ?></em></td>
|
132 |
</tr>
|
133 |
|
134 |
<tr class="updraftplusmethod ftp">
|
160 |
$login = $_POST['login'];
|
161 |
$pass = $_POST['pass'];
|
162 |
$path = $_POST['path'];
|
163 |
+
$nossl = $_POST['nossl'];
|
164 |
|
165 |
if (empty($server)) {
|
166 |
_e("Failure: No server details were given.",'updraftplus');
|
175 |
return;
|
176 |
}
|
177 |
|
178 |
+
$ftp = self::getFTP($server, $login, $pass, $nossl);
|
|
|
|
|
|
|
|
|
179 |
|
180 |
if (!$ftp->connect()) {
|
181 |
_e("Failure: we did not successfully log in with those credentials.",'updraftplus');
|
189 |
_e("Failure: an unexpected internal UpdraftPlus error occurred when testing the credentials - please contact the developer");
|
190 |
return;
|
191 |
}
|
192 |
+
if ($ftp->put(ABSPATH.'wp-includes/version.php', $fullpath, FTP_BINARY, false)) {
|
193 |
echo __("Success: we successfully logged in, and confirmed our ability to create a file in the given directory (login type:",'updraftplus')." ".$ftp->login_type.')';
|
194 |
@$ftp->delete($fullpath);
|
195 |
} else {
|
200 |
|
201 |
}
|
202 |
|
203 |
+
?>
|
methods/googledrive.php
CHANGED
@@ -23,6 +23,7 @@ class UpdraftPlus_BackupModule_googledrive {
|
|
23 |
$updraftplus->log("Google Drive: requesting access token: client_id=$client_id");
|
24 |
|
25 |
$query_body = array( 'refresh_token' => $token, 'client_id' => $client_id, 'client_secret' => $client_secret, 'grant_type' => 'refresh_token' );
|
|
|
26 |
$result = wp_remote_post('https://accounts.google.com/o/oauth2/token', array('timeout' => '15', 'method' => 'POST', 'body' => $query_body) );
|
27 |
|
28 |
if (is_wp_error($result)) {
|
@@ -91,7 +92,7 @@ class UpdraftPlus_BackupModule_googledrive {
|
|
91 |
$json_values = json_decode( $result['body'], true );
|
92 |
if ( isset( $json_values['refresh_token'] ) ) {
|
93 |
UpdraftPlus_Options::update_updraft_option('updraft_googledrive_token', $json_values['refresh_token']); // Save token
|
94 |
-
header('Location: '.admin_url('options-general.php?page=updraftplus&message='.__('Success','updraftplus').' '.sprintf(__('you have authenticated your %s account','updraftplus'),__('Google Drive','updraftplus'))));
|
95 |
|
96 |
}
|
97 |
else {
|
@@ -309,6 +310,11 @@ class UpdraftPlus_BackupModule_googledrive {
|
|
309 |
$this->gdocs->set_option( 'chunk_size', 0.2 ); # 0.2Mb; change from default of 512Kb
|
310 |
$this->gdocs->set_option( 'request_timeout', 15 ); # Change from default of 5s
|
311 |
$this->gdocs->set_option( 'max_resume_attempts', 36 ); # Doesn't look like GDocs class actually uses this anyway
|
|
|
|
|
|
|
|
|
|
|
312 |
}
|
313 |
return true;
|
314 |
}
|
23 |
$updraftplus->log("Google Drive: requesting access token: client_id=$client_id");
|
24 |
|
25 |
$query_body = array( 'refresh_token' => $token, 'client_id' => $client_id, 'client_secret' => $client_secret, 'grant_type' => 'refresh_token' );
|
26 |
+
|
27 |
$result = wp_remote_post('https://accounts.google.com/o/oauth2/token', array('timeout' => '15', 'method' => 'POST', 'body' => $query_body) );
|
28 |
|
29 |
if (is_wp_error($result)) {
|
92 |
$json_values = json_decode( $result['body'], true );
|
93 |
if ( isset( $json_values['refresh_token'] ) ) {
|
94 |
UpdraftPlus_Options::update_updraft_option('updraft_googledrive_token', $json_values['refresh_token']); // Save token
|
95 |
+
header('Location: '.admin_url('options-general.php?page=updraftplus&message='.__('Success','updraftplus').': '.sprintf(__('you have authenticated your %s account','updraftplus'),__('Google Drive','updraftplus'))));
|
96 |
|
97 |
}
|
98 |
else {
|
310 |
$this->gdocs->set_option( 'chunk_size', 0.2 ); # 0.2Mb; change from default of 512Kb
|
311 |
$this->gdocs->set_option( 'request_timeout', 15 ); # Change from default of 5s
|
312 |
$this->gdocs->set_option( 'max_resume_attempts', 36 ); # Doesn't look like GDocs class actually uses this anyway
|
313 |
+
if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) {
|
314 |
+
$this->gdocs->set_option('ssl_verify', false);
|
315 |
+
} else {
|
316 |
+
$this->gdocs->set_option('ssl_verify', true);
|
317 |
+
}
|
318 |
}
|
319 |
return true;
|
320 |
}
|
methods/s3.php
CHANGED
@@ -2,8 +2,35 @@
|
|
2 |
|
3 |
class UpdraftPlus_BackupModule_s3 {
|
4 |
|
5 |
-
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
}
|
8 |
|
9 |
function set_endpoint($obj, $region) {
|
@@ -32,9 +59,10 @@ class UpdraftPlus_BackupModule_s3 {
|
|
32 |
|
33 |
global $updraftplus;
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
38 |
|
39 |
$bucket_name = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path'));
|
40 |
$bucket_path = "";
|
@@ -66,7 +94,7 @@ class UpdraftPlus_BackupModule_s3 {
|
|
66 |
if ($orig_file_size % 5242880 > 0 ) $chunks++;
|
67 |
$hash = md5($file);
|
68 |
|
69 |
-
$updraftplus->log("S3 upload ($region): $
|
70 |
|
71 |
$filepath = $bucket_path.$file;
|
72 |
|
@@ -192,9 +220,11 @@ class UpdraftPlus_BackupModule_s3 {
|
|
192 |
function download($file) {
|
193 |
|
194 |
global $updraftplus;
|
195 |
-
if(!class_exists('S3')) require_once(UPDRAFTPLUS_DIR.'/includes/S3.php');
|
196 |
|
197 |
-
$s3 = $this->getS3(
|
|
|
|
|
|
|
198 |
|
199 |
$bucket_name = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path'));
|
200 |
$bucket_path = "";
|
@@ -229,7 +259,10 @@ class UpdraftPlus_BackupModule_s3 {
|
|
229 |
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>',
|
230 |
apikey: jQuery('#updraft_s3_apikey').val(),
|
231 |
apisecret: jQuery('#updraft_s3_apisecret').val(),
|
232 |
-
path: jQuery('#updraft_s3_path').val()
|
|
|
|
|
|
|
233 |
};
|
234 |
jQuery.post(ajaxurl, data, function(response) {
|
235 |
alert('Settings test result: ' + response);
|
@@ -248,7 +281,7 @@ class UpdraftPlus_BackupModule_s3 {
|
|
248 |
<tr class="updraftplusmethod s3">
|
249 |
<th></th>
|
250 |
<td>
|
251 |
-
<p><?php _e('Get your access key and secret key <a href="http://aws.amazon.com/console/">from your AWS console</a>, then pick a (globally unique - all Amazon S3 users) bucket name (letters and numbers) (and optionally a path) to use for storage. This bucket will be created for you if it does not already exist.','updraftplus');?></p>
|
252 |
</td></tr>
|
253 |
<tr class="updraftplusmethod s3">
|
254 |
<th><?php _e('S3 access key','updraftplus');?>:</th>
|
@@ -266,6 +299,13 @@ class UpdraftPlus_BackupModule_s3 {
|
|
266 |
<th></th>
|
267 |
<td><p><button id="updraft-s3-test" type="button" class="button-primary" style="font-size:18px !important"><?php echo sprintf(__('Test %s Settings','updraftplus'),'S3');?></button></p></td>
|
268 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
<?php
|
270 |
}
|
271 |
|
@@ -283,6 +323,9 @@ class UpdraftPlus_BackupModule_s3 {
|
|
283 |
$key = $_POST['apikey'];
|
284 |
$secret = $_POST['apisecret'];
|
285 |
$path = $_POST['path'];
|
|
|
|
|
|
|
286 |
|
287 |
if (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) {
|
288 |
$bucket = $bmatches[1];
|
@@ -297,8 +340,7 @@ class UpdraftPlus_BackupModule_s3 {
|
|
297 |
return;
|
298 |
}
|
299 |
|
300 |
-
|
301 |
-
$s3 = new S3($key, $secret);
|
302 |
|
303 |
$location = @$s3->getBucketLocation($bucket);
|
304 |
if ($location) {
|
@@ -320,11 +362,21 @@ class UpdraftPlus_BackupModule_s3 {
|
|
320 |
if (isset($bucket_exists)) {
|
321 |
$try_file = md5(rand());
|
322 |
self::set_endpoint($s3, $location);
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
}
|
329 |
}
|
330 |
|
2 |
|
3 |
class UpdraftPlus_BackupModule_s3 {
|
4 |
|
5 |
+
// Get an S3 object, after setting our options
|
6 |
+
function getS3($key, $secret, $useservercerts, $disableverify, $nossl) {
|
7 |
+
global $updraftplus;
|
8 |
+
|
9 |
+
if (!class_exists('S3')) require_once(UPDRAFTPLUS_DIR.'/includes/S3.php');
|
10 |
+
|
11 |
+
$s3 = new S3($key, $secret);
|
12 |
+
if (!$nossl) {
|
13 |
+
$curl_version = (function_exists('curl_version')) ? curl_version() : array('features' => null);
|
14 |
+
$curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
|
15 |
+
if ($curl_ssl_supported) {
|
16 |
+
$s3->useSSL = true;
|
17 |
+
if ($disableverify) {
|
18 |
+
$s3->useSSLValidation = false;
|
19 |
+
$updraftplus->log("S3: Disabling verification of SSL certificates");
|
20 |
+
}
|
21 |
+
if ($useservercerts) {
|
22 |
+
$updraftplus->log("S3: Using the server's SSL certificates");
|
23 |
+
} else {
|
24 |
+
$s3->SSLCACert = UPDRAFTPLUS_DIR.'/includes/cacert.pem';
|
25 |
+
}
|
26 |
+
} else {
|
27 |
+
$updraftplus->log("S3: Curl/SSL is not available. Communications with Amazon S3 will not be encrypted.");
|
28 |
+
}
|
29 |
+
} else {
|
30 |
+
$s3->useSSL = false;
|
31 |
+
$updraftplus->log("SSL was disabled via the user's preference. Communications with Amazon S3 will not be encrypted.");
|
32 |
+
}
|
33 |
+
return $s3;
|
34 |
}
|
35 |
|
36 |
function set_endpoint($obj, $region) {
|
59 |
|
60 |
global $updraftplus;
|
61 |
|
62 |
+
$s3 = $this->getS3(
|
63 |
+
UpdraftPlus_Options::get_updraft_option('updraft_s3_login'), UpdraftPlus_Options::get_updraft_option('updraft_s3_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify'),
|
64 |
+
UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')
|
65 |
+
);
|
66 |
|
67 |
$bucket_name = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path'));
|
68 |
$bucket_path = "";
|
94 |
if ($orig_file_size % 5242880 > 0 ) $chunks++;
|
95 |
$hash = md5($file);
|
96 |
|
97 |
+
$updraftplus->log("S3 upload ($region): $file (chunks: $chunks) -> s3://$bucket_name/$bucket_path$file");
|
98 |
|
99 |
$filepath = $bucket_path.$file;
|
100 |
|
220 |
function download($file) {
|
221 |
|
222 |
global $updraftplus;
|
|
|
223 |
|
224 |
+
$s3 = $this->getS3(
|
225 |
+
UpdraftPlus_Options::get_updraft_option('updraft_s3_login'), UpdraftPlus_Options::get_updraft_option('updraft_s3_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify'),
|
226 |
+
UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')
|
227 |
+
);
|
228 |
|
229 |
$bucket_name = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path'));
|
230 |
$bucket_path = "";
|
259 |
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>',
|
260 |
apikey: jQuery('#updraft_s3_apikey').val(),
|
261 |
apisecret: jQuery('#updraft_s3_apisecret').val(),
|
262 |
+
path: jQuery('#updraft_s3_path').val(),
|
263 |
+
disableverify: (jQuery('#updraft_ssl_disableverify').is(':checked')) ? 1 : 0,
|
264 |
+
useservercerts: (jQuery('#updraft_ssl_useservercerts').is(':checked')) ? 1 : 0,
|
265 |
+
nossl: (jQuery('#updraft_ssl_nossl').is(':checked')) ? 1 : 0,
|
266 |
};
|
267 |
jQuery.post(ajaxurl, data, function(response) {
|
268 |
alert('Settings test result: ' + response);
|
281 |
<tr class="updraftplusmethod s3">
|
282 |
<th></th>
|
283 |
<td>
|
284 |
+
<p><?php _e('Get your access key and secret key <a href="http://aws.amazon.com/console/">from your AWS console</a>, then pick a (globally unique - all Amazon S3 users) bucket name (letters and numbers) (and optionally a path) to use for storage. This bucket will be created for you if it does not already exist.','updraftplus');?> <a href="http://updraftplus.com/faqs/i-get-ssl-certificate-errors-when-backing-up-andor-restoring/"><?php _e('If you see errors about SSL certificates, then please go here for help.','updraftplus');?></a></p>
|
285 |
</td></tr>
|
286 |
<tr class="updraftplusmethod s3">
|
287 |
<th><?php _e('S3 access key','updraftplus');?>:</th>
|
299 |
<th></th>
|
300 |
<td><p><button id="updraft-s3-test" type="button" class="button-primary" style="font-size:18px !important"><?php echo sprintf(__('Test %s Settings','updraftplus'),'S3');?></button></p></td>
|
301 |
</tr>
|
302 |
+
|
303 |
+
<tr class="updraftplusmethod s3">
|
304 |
+
<th></th>
|
305 |
+
<td>
|
306 |
+
<?php global $updraftplus_admin; $updraftplus_admin->curl_check('Amazon S3', true); ?>
|
307 |
+
</td>
|
308 |
+
</tr>
|
309 |
<?php
|
310 |
}
|
311 |
|
323 |
$key = $_POST['apikey'];
|
324 |
$secret = $_POST['apisecret'];
|
325 |
$path = $_POST['path'];
|
326 |
+
$useservercerts = (isset($_POST['useservercerts'])) ? absint($_POST['useservercerts']) : 0;
|
327 |
+
$disableverify = (isset($_POST['disableverify'])) ? absint($_POST['disableverify']) : 0;
|
328 |
+
$nossl = (isset($_POST['nossl'])) ? absint($_POST['nossl']) : 0;
|
329 |
|
330 |
if (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) {
|
331 |
$bucket = $bmatches[1];
|
340 |
return;
|
341 |
}
|
342 |
|
343 |
+
$s3 = self::getS3($key, $secret, $useservercerts, $disableverify, $nossl);
|
|
|
344 |
|
345 |
$location = @$s3->getBucketLocation($bucket);
|
346 |
if ($location) {
|
362 |
if (isset($bucket_exists)) {
|
363 |
$try_file = md5(rand());
|
364 |
self::set_endpoint($s3, $location);
|
365 |
+
$s3->setExceptions(true);
|
366 |
+
try {
|
367 |
+
if (!$s3->putObjectString($try_file, $bucket, $path.$try_file)) {
|
368 |
+
echo __('Failure','updraftplus').": ${bucket_verb}".__('We successfully accessed the bucket, but the attempt to create a file in it failed.','updraftplus');
|
369 |
+
} else {
|
370 |
+
echo __('Success','updraftplus').": ${bucket_verb}".__('We accessed the bucket, and were able to create files within it.','updraftplus').' ';
|
371 |
+
if ($s3->useSSL) {
|
372 |
+
echo sprintf(__('The communication with %s was encrypted.', 'updraftplus'), 'Amazon S3');
|
373 |
+
} else {
|
374 |
+
echo sprintf(__('The communication with %s was not encrypted.', 'updraftplus'), 'Amazon S3');
|
375 |
+
}
|
376 |
+
@$s3->deleteObject($bucket, $path.$try_file);
|
377 |
+
}
|
378 |
+
} catch (Exception $e) {
|
379 |
+
echo __('Failure','updraftplus').": ${bucket_verb}".__('We successfully accessed the bucket, but the attempt to create a file in it failed.','updraftplus').' ('.$e->getMessage().')';
|
380 |
}
|
381 |
}
|
382 |
|
methods/sftp.php
CHANGED
@@ -58,14 +58,14 @@ class UpdraftPlus_BackupModule_sftp {
|
|
58 |
// config_print: prints out table rows for the configuration screen
|
59 |
// Your rows need to have a class exactly matching your method (in this example, sftp), and also a class of updraftplusmethod
|
60 |
// Note that logging is not available from this context; it will do nothing.
|
61 |
-
function config_print() {
|
62 |
|
63 |
-
$link = sprintf(__('%s support is available as an add-on','updraftplus'),'SFTP').' - <a href="http://updraftplus.com/shop/sftp/">'.__('follow this link to get it','updraftplus');
|
64 |
|
65 |
$default = <<<ENDHERE
|
66 |
<tr class="updraftplusmethod sftp">
|
67 |
<th>SFTP:</th>
|
68 |
-
<td>$link</
|
69 |
</tr>
|
70 |
ENDHERE;
|
71 |
|
@@ -83,4 +83,4 @@ ENDHERE;
|
|
83 |
|
84 |
}
|
85 |
|
86 |
-
}
|
58 |
// config_print: prints out table rows for the configuration screen
|
59 |
// Your rows need to have a class exactly matching your method (in this example, sftp), and also a class of updraftplusmethod
|
60 |
// Note that logging is not available from this context; it will do nothing.
|
61 |
+
public static function config_print() {
|
62 |
|
63 |
+
$link = sprintf(__('%s support is available as an add-on','updraftplus'),'SFTP').' - <a href="http://updraftplus.com/shop/sftp/">'.__('follow this link to get it','updraftplus').'</a>';
|
64 |
|
65 |
$default = <<<ENDHERE
|
66 |
<tr class="updraftplusmethod sftp">
|
67 |
<th>SFTP:</th>
|
68 |
+
<td>$link</td>
|
69 |
</tr>
|
70 |
ENDHERE;
|
71 |
|
83 |
|
84 |
}
|
85 |
|
86 |
+
}
|
methods/template.php
CHANGED
@@ -53,7 +53,7 @@ class UpdraftPlus_BackupModule_template {
|
|
53 |
// config_print: prints out table rows for the configuration screen
|
54 |
// Your rows need to have a class exactly matching your method (in this example, template), and also a class of updraftplusmethod
|
55 |
// Note that logging is not available from this context; it will do nothing.
|
56 |
-
function config_print() {
|
57 |
|
58 |
?>
|
59 |
<tr class="updraftplusmethod template">
|
@@ -68,4 +68,4 @@ class UpdraftPlus_BackupModule_template {
|
|
68 |
|
69 |
}
|
70 |
|
71 |
-
}
|
53 |
// config_print: prints out table rows for the configuration screen
|
54 |
// Your rows need to have a class exactly matching your method (in this example, template), and also a class of updraftplusmethod
|
55 |
// Note that logging is not available from this context; it will do nothing.
|
56 |
+
public static function config_print() {
|
57 |
|
58 |
?>
|
59 |
<tr class="updraftplusmethod template">
|
68 |
|
69 |
}
|
70 |
|
71 |
+
}
|
methods/webdav.php
CHANGED
@@ -58,7 +58,7 @@ class UpdraftPlus_BackupModule_webdav {
|
|
58 |
// config_print: prints out table rows for the configuration screen
|
59 |
// Your rows need to have a class exactly matching your method (in this example, webdav), and also a class of updraftplusmethod
|
60 |
// Note that logging is not available from this context; it will do nothing.
|
61 |
-
function config_print() {
|
62 |
|
63 |
$link = sprintf(__('%s support is available as an add-on','updraftplus'),'WebDAV').' - <a href="http://updraftplus.com/shop/webdav/">'.__('follow this link to get it','updraftplus');
|
64 |
|
58 |
// config_print: prints out table rows for the configuration screen
|
59 |
// Your rows need to have a class exactly matching your method (in this example, webdav), and also a class of updraftplusmethod
|
60 |
// Note that logging is not available from this context; it will do nothing.
|
61 |
+
public static function config_print() {
|
62 |
|
63 |
$link = sprintf(__('%s support is available as an add-on','updraftplus'),'WebDAV').' - <a href="http://updraftplus.com/shop/webdav/">'.__('follow this link to get it','updraftplus');
|
64 |
|
options.php
CHANGED
@@ -22,8 +22,8 @@ class UpdraftPlus_Options {
|
|
22 |
}
|
23 |
|
24 |
public static function add_admin_pages() {
|
25 |
-
global $
|
26 |
-
add_submenu_page('options-general.php', 'UpdraftPlus', __('UpdraftPlus Backups','updraftplus'), "manage_options", "updraftplus", array($
|
27 |
}
|
28 |
|
29 |
public static function options_form_begin() {
|
@@ -33,7 +33,7 @@ class UpdraftPlus_Options {
|
|
33 |
|
34 |
public static function admin_init() {
|
35 |
|
36 |
-
global $updraftplus;
|
37 |
register_setting('updraft-options-group', 'updraft_interval', array($updraftplus, 'schedule_backup') );
|
38 |
register_setting('updraft-options-group', 'updraft_interval_database', array($updraftplus, 'schedule_backup_database') );
|
39 |
register_setting('updraft-options-group', 'updraft_retain', array($updraftplus, 'retain_range') );
|
@@ -45,6 +45,11 @@ class UpdraftPlus_Options {
|
|
45 |
register_setting('updraft-options-group', 'updraft_s3_pass' );
|
46 |
register_setting('updraft-options-group', 'updraft_s3_remote_path' );
|
47 |
|
|
|
|
|
|
|
|
|
|
|
48 |
register_setting('updraft-options-group', 'updraft_sftp_settings' );
|
49 |
register_setting('updraft-options-group', 'updraft_webdav_settings' );
|
50 |
|
@@ -52,6 +57,10 @@ class UpdraftPlus_Options {
|
|
52 |
register_setting('updraft-options-group', 'updraft_dropbox_secret' );
|
53 |
register_setting('updraft-options-group', 'updraft_dropbox_folder' );
|
54 |
|
|
|
|
|
|
|
|
|
55 |
register_setting('updraft-options-group', 'updraft_googledrive_clientid', array($updraftplus, 'googledrive_clientid_checkchange') );
|
56 |
register_setting('updraft-options-group', 'updraft_googledrive_secret' );
|
57 |
register_setting('updraft-options-group', 'updraft_googledrive_remotepath' );
|
@@ -60,7 +69,7 @@ class UpdraftPlus_Options {
|
|
60 |
register_setting('updraft-options-group', 'updraft_ftp_pass' );
|
61 |
register_setting('updraft-options-group', 'updraft_ftp_remote_path' );
|
62 |
register_setting('updraft-options-group', 'updraft_server_address' );
|
63 |
-
register_setting('updraft-options-group', 'updraft_dir', array($
|
64 |
register_setting('updraft-options-group', 'updraft_email');
|
65 |
register_setting('updraft-options-group', 'updraft_delete_local', 'absint' );
|
66 |
register_setting('updraft-options-group', 'updraft_debug_mode', 'absint' );
|
@@ -68,10 +77,13 @@ class UpdraftPlus_Options {
|
|
68 |
register_setting('updraft-options-group', 'updraft_include_themes', 'absint' );
|
69 |
register_setting('updraft-options-group', 'updraft_include_uploads', 'absint' );
|
70 |
register_setting('updraft-options-group', 'updraft_include_others', 'absint' );
|
|
|
71 |
register_setting('updraft-options-group', 'updraft_include_others_exclude' );
|
72 |
|
73 |
-
register_setting('updraft-options-group', 'updraft_starttime_files', array(
|
74 |
-
register_setting('updraft-options-group', 'updraft_starttime_db', array(
|
|
|
|
|
75 |
|
76 |
global $pagenow;
|
77 |
if (is_multisite() && $pagenow == 'options-general.php' && isset($_REQUEST['page']) && 'updraftplus' == substr($_REQUEST['page'], 0, 11)) {
|
@@ -80,15 +92,23 @@ class UpdraftPlus_Options {
|
|
80 |
|
81 |
}
|
82 |
|
83 |
-
public static function
|
|
|
|
|
84 |
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
-
$
|
|
|
88 |
|
89 |
}
|
90 |
|
91 |
-
|
92 |
}
|
93 |
|
94 |
add_action('admin_init', array('UpdraftPlus_Options', 'admin_init'));
|
22 |
}
|
23 |
|
24 |
public static function add_admin_pages() {
|
25 |
+
global $updraftplus_admin;
|
26 |
+
add_submenu_page('options-general.php', 'UpdraftPlus', __('UpdraftPlus Backups','updraftplus'), "manage_options", "updraftplus", array($updraftplus_admin, "settings_output"));
|
27 |
}
|
28 |
|
29 |
public static function options_form_begin() {
|
33 |
|
34 |
public static function admin_init() {
|
35 |
|
36 |
+
global $updraftplus, $updraftplus_admin;
|
37 |
register_setting('updraft-options-group', 'updraft_interval', array($updraftplus, 'schedule_backup') );
|
38 |
register_setting('updraft-options-group', 'updraft_interval_database', array($updraftplus, 'schedule_backup_database') );
|
39 |
register_setting('updraft-options-group', 'updraft_retain', array($updraftplus, 'retain_range') );
|
45 |
register_setting('updraft-options-group', 'updraft_s3_pass' );
|
46 |
register_setting('updraft-options-group', 'updraft_s3_remote_path' );
|
47 |
|
48 |
+
register_setting('updraft-options-group', 'updraft_cloudfiles_authurl' );
|
49 |
+
register_setting('updraft-options-group', 'updraft_cloudfiles_user' );
|
50 |
+
register_setting('updraft-options-group', 'updraft_cloudfiles_apikey' );
|
51 |
+
register_setting('updraft-options-group', 'updraft_cloudfiles_path' );
|
52 |
+
|
53 |
register_setting('updraft-options-group', 'updraft_sftp_settings' );
|
54 |
register_setting('updraft-options-group', 'updraft_webdav_settings' );
|
55 |
|
57 |
register_setting('updraft-options-group', 'updraft_dropbox_secret' );
|
58 |
register_setting('updraft-options-group', 'updraft_dropbox_folder' );
|
59 |
|
60 |
+
register_setting('updraft-options-group', 'updraft_ssl_nossl', 'absint' );
|
61 |
+
register_setting('updraft-options-group', 'updraft_ssl_useservercerts', 'absint' );
|
62 |
+
register_setting('updraft-options-group', 'updraft_ssl_disableverify', 'absint' );
|
63 |
+
|
64 |
register_setting('updraft-options-group', 'updraft_googledrive_clientid', array($updraftplus, 'googledrive_clientid_checkchange') );
|
65 |
register_setting('updraft-options-group', 'updraft_googledrive_secret' );
|
66 |
register_setting('updraft-options-group', 'updraft_googledrive_remotepath' );
|
69 |
register_setting('updraft-options-group', 'updraft_ftp_pass' );
|
70 |
register_setting('updraft-options-group', 'updraft_ftp_remote_path' );
|
71 |
register_setting('updraft-options-group', 'updraft_server_address' );
|
72 |
+
register_setting('updraft-options-group', 'updraft_dir', array($updraftplus_admin, 'prune_updraft_dir_prefix') );
|
73 |
register_setting('updraft-options-group', 'updraft_email');
|
74 |
register_setting('updraft-options-group', 'updraft_delete_local', 'absint' );
|
75 |
register_setting('updraft-options-group', 'updraft_debug_mode', 'absint' );
|
77 |
register_setting('updraft-options-group', 'updraft_include_themes', 'absint' );
|
78 |
register_setting('updraft-options-group', 'updraft_include_uploads', 'absint' );
|
79 |
register_setting('updraft-options-group', 'updraft_include_others', 'absint' );
|
80 |
+
register_setting('updraft-options-group', 'updraft_include_wpcore', 'absint' );
|
81 |
register_setting('updraft-options-group', 'updraft_include_others_exclude' );
|
82 |
|
83 |
+
register_setting('updraft-options-group', 'updraft_starttime_files', array('UpdraftPlus_Options', 'hourminute') );
|
84 |
+
register_setting('updraft-options-group', 'updraft_starttime_db', array('UpdraftPlus_Options', 'hourminute') );
|
85 |
+
|
86 |
+
register_setting('updraft-options-group', 'updraft_disable_ping', array('UpdraftPlus_Options', 'pingfilter') );
|
87 |
|
88 |
global $pagenow;
|
89 |
if (is_multisite() && $pagenow == 'options-general.php' && isset($_REQUEST['page']) && 'updraftplus' == substr($_REQUEST['page'], 0, 11)) {
|
92 |
|
93 |
}
|
94 |
|
95 |
+
public static function pingfilter($disable) {
|
96 |
+
return apply_filters('updraftplus_pingfilter', $disable);
|
97 |
+
}
|
98 |
|
99 |
+
public static function hourminute($pot) {
|
100 |
+
if (preg_match("/^[0-2][0-9]:[0-5][0-9]$/", $pot)) return $pot;
|
101 |
+
if ('' == $pot) return date('H:i', time()+300);
|
102 |
+
return '00:00';
|
103 |
+
}
|
104 |
+
|
105 |
+
public static function show_admin_warning_multisite() {
|
106 |
|
107 |
+
global $updraftplus_admin;
|
108 |
+
$updraftplus_admin->show_admin_warning('<strong>UpdraftPlus warning:</strong> This is a WordPress multi-site (a.k.a. network) installation. <a href="http://updraftplus.com">WordPress Multisite is supported, with extra features, by UpdraftPlus Premium, or the Multisite add-on</a>. Without upgrading, UpdraftPlus allows <strong>every</strong> blog admin who can modify plugin settings to back up (and hence access the data, including passwords, from) and restore (including with customised modifications, e.g. changed passwords) <strong>the entire network</strong>. (This applies to all WordPress backup plugins unless they have been explicitly coded for multisite compatibility).', "error");
|
109 |
|
110 |
}
|
111 |
|
|
|
112 |
}
|
113 |
|
114 |
add_action('admin_init', array('UpdraftPlus_Options', 'admin_init'));
|
readme.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
=== UpdraftPlus Backup ===
|
2 |
-
Contributors:
|
3 |
-
Tags: backup, restore, database,
|
4 |
Requires at least: 3.2
|
5 |
Tested up to: 3.5.1
|
6 |
Stable tag: 1.5.5
|
@@ -8,14 +8,15 @@ Author URI: http://updraftplus.com
|
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPLv3 or later
|
10 |
|
11 |
-
|
|
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
-
<a href="http://updraftplus.com">UpdraftPlus</a> simplifies backups (and restoration). Backup into the cloud (Amazon S3, Dropbox, Google Drive, FTP, SFTP, WebDAV and email) and restore with a single click. Backups of files and database can have separate schedules.
|
16 |
|
17 |
-
* Supports backups to Amazon S3, Dropbox, Google Drive, FTP (including SSL), email, SFTP and WebDAV
|
18 |
-
* Quick restore
|
19 |
* Backup automatically on a repeating schedule
|
20 |
* Files and databases can have separate schedules
|
21 |
* Failed uploads are automatically resumed/retried
|
@@ -24,7 +25,7 @@ Easy and complete backups and restoration. Manual or automated backups (Amazon S
|
|
24 |
* Download backup archives direct from your WordPress dashboard
|
25 |
* Database backups can be encrypted for security
|
26 |
* Debug mode that gives full logging of the backup
|
27 |
-
* Thousands of users: widely tested and reliable
|
28 |
* Internationalised (translations very welcome - see below)
|
29 |
* Premium version and support available - <a href="http://updraftplus.com">http://updraftplus.com</a>
|
30 |
|
@@ -50,6 +51,9 @@ Many thanks to the existing translators:
|
|
50 |
|
51 |
* Deutsch / German (de_DE): Marcel Herrguth - mherrguth@mrgeneration.de
|
52 |
* Magyar / Hungarian (hu_HU): Szépe Viktor - http://www.szepe.net
|
|
|
|
|
|
|
53 |
|
54 |
= Other support =
|
55 |
|
@@ -95,7 +99,7 @@ You can check the changelog for changes; but the original Updraft, before I fork
|
|
95 |
|
96 |
= Any known bugs ? =
|
97 |
|
98 |
-
Not a bug, but one issue to be aware of is that backups of very large sites (lots of uploaded media) are quite complex matters, given the limits of running inside WordPress on a huge variety of different web hosting setups. With large sites, you need to use Amazon S3, which UpdraftPlus supports (since 0.9.20), Google Drive (0.9.21), Dropbox (since 1.2.19)
|
99 |
|
100 |
= My site was hacked, and I have no backups! I thought UpdraftPlus was working! Can I kill you? =
|
101 |
|
@@ -111,10 +115,35 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
|
|
111 |
|
112 |
== Changelog ==
|
113 |
|
114 |
-
= 1.5.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
* Now translatable - .pot file included (translators welcome!)
|
116 |
* When restoring, you can now select only some components to restore
|
117 |
-
* History of previous backups can re-scan to find backups manually imported (e.g. via FTP) (trunk
|
118 |
* Multisite add-on (http://updraftplus.com/shop/) now stores/restores blogs and mu-plugins separately
|
119 |
* Display UpdraftPlus's disk space usage
|
120 |
* Internationalisation hooks in main body of plugin
|
@@ -128,6 +157,7 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
|
|
128 |
* Clean up temporary files left behind by zipArchive::addFile
|
129 |
* Tweak Dropbox library to work from behind very weird proxies that double-surround the HTTP header
|
130 |
* Improved help for people with broken schedulers
|
|
|
131 |
|
132 |
= 1.4.48 - 03/11/2013 =
|
133 |
* Improve batching on zip creation for sites with very large files
|
@@ -368,7 +398,7 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
|
|
368 |
3. Showing and downloading backup sets
|
369 |
|
370 |
We recognise and thank the following for code and/or libraries used and/or modified under the terms of their licences:
|
371 |
-
* UpdraftPlus is
|
372 |
* Sorin Iclanzan, http://profiles.wordpress.org/hel.io/
|
373 |
* Ben Tadiar, https://github.com/BenTheDesigner/Dropbox
|
374 |
* Beau Brownlee, http://www.solutionbot.com/2009/01/02/php-ftp-class/
|
@@ -381,7 +411,7 @@ We recognise and thank the following for code and/or libraries used and/or modif
|
|
381 |
|
382 |
This program is free software; you can redistribute it and/or modify
|
383 |
it under the terms of the GNU General Public License as published by
|
384 |
-
the Free Software Foundation; either version
|
385 |
(at your option) any later version.
|
386 |
|
387 |
This program is distributed in the hope that it will be useful,
|
@@ -393,5 +423,4 @@ We recognise and thank the following for code and/or libraries used and/or modif
|
|
393 |
along with this program; if not, write to the Free Software
|
394 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
395 |
|
396 |
-
|
397 |
-
New features: selective restoration, importing remote backups; plus many tweaks, optimisations + small bug-fixes: recommended upgrade for all
|
1 |
=== UpdraftPlus Backup ===
|
2 |
+
Contributors: David Anderson
|
3 |
+
Tags: backup, restore, database, rackspace, amazon, s3, dropbox, google drive, ftp, webdav, back up, multisite
|
4 |
Requires at least: 3.2
|
5 |
Tested up to: 3.5.1
|
6 |
Stable tag: 1.5.5
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPLv3 or later
|
10 |
|
11 |
+
== Upgrade Notice ==
|
12 |
+
New features: selective restoration, importing remote backups; plus many tweaks, optimisations + small bug-fixes: recommended upgrade for all
|
13 |
|
14 |
== Description ==
|
15 |
|
16 |
+
<a href="http://updraftplus.com">UpdraftPlus</a> simplifies backups (and restoration). Backup into the cloud (Amazon S3, Dropbox, Google Drive, Rackspace Cloud, FTP, SFTP, WebDAV and email) and restore with a single click. Backups of files and database can have separate schedules.
|
17 |
|
18 |
+
* Supports backups to Amazon S3, Dropbox, Google Drive, Rackspace Cloud, FTP (including SSL), email, SFTP and WebDAV
|
19 |
+
* Quick restore (both file and database backups)
|
20 |
* Backup automatically on a repeating schedule
|
21 |
* Files and databases can have separate schedules
|
22 |
* Failed uploads are automatically resumed/retried
|
25 |
* Download backup archives direct from your WordPress dashboard
|
26 |
* Database backups can be encrypted for security
|
27 |
* Debug mode that gives full logging of the backup
|
28 |
+
* Thousands of users: widely tested and reliable (over 100,000 downloads)
|
29 |
* Internationalised (translations very welcome - see below)
|
30 |
* Premium version and support available - <a href="http://updraftplus.com">http://updraftplus.com</a>
|
31 |
|
51 |
|
52 |
* Deutsch / German (de_DE): Marcel Herrguth - mherrguth@mrgeneration.de
|
53 |
* Magyar / Hungarian (hu_HU): Szépe Viktor - http://www.szepe.net
|
54 |
+
* Spanish / Español (es_ES): Fernando Villasmil - villasmil.fernando@gmail.com
|
55 |
+
|
56 |
+
Disclaimer: Use of a translation is at your own risk. UpdraftPlus can give no guarantees that translations from the original English are accurate.
|
57 |
|
58 |
= Other support =
|
59 |
|
99 |
|
100 |
= Any known bugs ? =
|
101 |
|
102 |
+
Not a bug, but one issue to be aware of is that backups of very large sites (lots of uploaded media) are quite complex matters, given the limits of running inside WordPress on a huge variety of different web hosting setups. With large sites, you need to use Amazon S3, which UpdraftPlus supports (since 0.9.20), Google Drive (0.9.21), Dropbox (since 1.2.19), WebDAV (since 1.4.30), or FTP (since 1.5.9) because these support chunked, resumable uploads. Other backup methods have code (since 0.9.0) to retry failed uploads of an archive, but the upload cannot be chunked, so if an archive is enormous (i.e. cannot be completely uploaded in the time that PHP is allowed for running on your web host) it cannot work.
|
103 |
|
104 |
= My site was hacked, and I have no backups! I thought UpdraftPlus was working! Can I kill you? =
|
105 |
|
115 |
|
116 |
== Changelog ==
|
117 |
|
118 |
+
= 1.5.20 - not yet released/supported =
|
119 |
+
* FEATURE: Now restores databases (we recommend the MySQL command-line for versions created with previous versions of UpdraftPlus)
|
120 |
+
* FEATURE: Rackspace Cloud Files support (http://www.rackspace.com/cloud/files/)
|
121 |
+
* FEATURE: Built-in multi-uploader, allowing easier restoration of old backup sets
|
122 |
+
* FEATURE: Allow instant downloading of the most recently modified log file
|
123 |
+
* FEATURE: Built in drag-and-drop database decrypter for manual decryption
|
124 |
+
* FEATURE: Deutsch / German translation: thanks to Marcel Herrguth - mherrguth@mrgeneration.de
|
125 |
+
* FEATURE: Magyar / Hungarian translation: thanks to Szépe Viktor - http://www.szepe.net
|
126 |
+
* FEATURE: Spanish / Español translation: thanks to Fernando Villasmil - villasmil.fernando@gmail.com
|
127 |
+
* FEATURE: Added encryption (used by default) to Amazon S3 communications
|
128 |
+
* RELIABILITY: Various algorithm tweaks to help larger sites on lower resources. Largest site a known user has: 1.5Gb
|
129 |
+
* RELIABILITY/FEATURE: Ship up-to-date SSL certificates, and added expert options to prefer server SSL CA certificates, and to disable peer verification
|
130 |
+
* SPEED: Batch INSERT commands in database backups, for much faster restoration (typically 95% faster)
|
131 |
+
* SPEED/RELIABILITY: FTP and FTPS (not SFTP) are now chunked and resumable (both download and upload), subject to your FTP server responding correctly to SIZE
|
132 |
+
* SPEED: Re-factoring of admin-area and some backup code into separate lazy-loaded files, to reduce memory consumption on sites generally
|
133 |
+
* FIX: Clear PHP's file stat cache when checking for zip file activity - fixes potential halt on very enormous sites or sites with very low PHP timeouts.
|
134 |
+
* FIX: Caught some untranslated strings
|
135 |
+
* FIX: Respect WordPress's WP_MAX_MEMORY_LIMIT constant
|
136 |
+
* FIX: Remove timezone display from local time - WordPress's get_date_from_gmt function does not completely do what the manual says it does
|
137 |
+
* FIX: A small typo slipped into 1.5.5 which prevented some Google Drive users from setting up new installations
|
138 |
+
* TWEAK: In fix-time add-on, fade UI when relevant
|
139 |
+
* TWEAK: Improved UI of downloader
|
140 |
+
* TWEAK: Decrease FTP timeouts to improve our chances of getting back an error before PHP aborts
|
141 |
+
* TWEAK: Tweaked al relevant methods to follow the general SSL CA certificate options
|
142 |
+
|
143 |
+
= 1.5.5 - 03/26/2013 =
|
144 |
* Now translatable - .pot file included (translators welcome!)
|
145 |
* When restoring, you can now select only some components to restore
|
146 |
+
* History of previous backups can re-scan to find backups manually imported (e.g. via FTP) (trunk has drag-and-drop uploader)
|
147 |
* Multisite add-on (http://updraftplus.com/shop/) now stores/restores blogs and mu-plugins separately
|
148 |
* Display UpdraftPlus's disk space usage
|
149 |
* Internationalisation hooks in main body of plugin
|
157 |
* Clean up temporary files left behind by zipArchive::addFile
|
158 |
* Tweak Dropbox library to work from behind very weird proxies that double-surround the HTTP header
|
159 |
* Improved help for people with broken schedulers
|
160 |
+
* Fix FTP download error
|
161 |
|
162 |
= 1.4.48 - 03/11/2013 =
|
163 |
* Improve batching on zip creation for sites with very large files
|
398 |
3. Showing and downloading backup sets
|
399 |
|
400 |
We recognise and thank the following for code and/or libraries used and/or modified under the terms of their licences:
|
401 |
+
* UpdraftPlus is derived from the original Updraft by Paul Kehrer (Twitter: http://twitter.com/reaperhulk, Blog: http://langui.sh)
|
402 |
* Sorin Iclanzan, http://profiles.wordpress.org/hel.io/
|
403 |
* Ben Tadiar, https://github.com/BenTheDesigner/Dropbox
|
404 |
* Beau Brownlee, http://www.solutionbot.com/2009/01/02/php-ftp-class/
|
411 |
|
412 |
This program is free software; you can redistribute it and/or modify
|
413 |
it under the terms of the GNU General Public License as published by
|
414 |
+
the Free Software Foundation; either version 3 of the License, or
|
415 |
(at your option) any later version.
|
416 |
|
417 |
This program is distributed in the hope that it will be useful,
|
423 |
along with this program; if not, write to the Free Software
|
424 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
425 |
|
426 |
+
Furthermore, reliance upon any non-English translation is at your own risk. UpdraftPlus can give no guarantees that translations from the original English are accurate.
|
|
updraftplus.php
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
/*
|
3 |
Plugin Name: UpdraftPlus - Backup/Restore
|
4 |
Plugin URI: http://updraftplus.com
|
5 |
-
Description: Backup and restore:
|
6 |
Author: UpdraftPlus.Com, DavidAnderson
|
7 |
-
Version: 1.5.
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPLv3 or later
|
10 |
Text Domain: updraftplus
|
@@ -13,14 +13,27 @@ Author URI: http://updraftplus.com
|
|
13 |
|
14 |
/*
|
15 |
TODO - some of these are out of date/done, needs pruning
|
16 |
-
// Add an appeal for translators to email me
|
17 |
-
//
|
18 |
// Search for other TODO-s in the code
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
// Make mcrypt warning on dropbox more prominent - one customer missed it
|
20 |
// Store meta-data on which version of UD the backup was made with (will help if we ever introduce quirks that need ironing)
|
21 |
// Test restoration when uploads dir is /assets/ (e.g. with Shoestrap theme)
|
22 |
// Send the user an email upon their first backup with tips on what to do (e.g. support/improve) (include legacy check to not bug existing users)
|
23 |
//Allow use of /usr/bin/zip - since this can escape from PHP's memory limit. Can still batch as we do so, in order to monitor/measure progress
|
|
|
|
|
24 |
//Do an automated test periodically for the success of loop-back connections
|
25 |
//When a manual backup is run, use a timer to update the 'Download backups and logs' section, just like 'Last finished backup run'. Beware of over-writing anything that's in there from a resumable downloader.
|
26 |
//Change DB encryption to not require whole gzip in memory (twice)
|
@@ -33,13 +46,11 @@ TODO - some of these are out of date/done, needs pruning
|
|
33 |
// Should we resume if the only errors were upon deletion (i.e. the backup itself was fine?) Presently we do, but it displays errors for the user to confuse them. Perhaps better to make pruning a separate scheuled task??
|
34 |
// Warn the user if their zip-file creation is slooowww...
|
35 |
// Create a "Want Support?" button/console, that leads them through what is needed, and performs some basic tests...
|
36 |
-
//
|
37 |
-
// Translations
|
38 |
// Add-on to manage all your backups from a single dashboard
|
39 |
// Make disk space check more intelligent (currently hard-coded at 35Mb)
|
40 |
// Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install - some kind of single-use code which a remote UpdraftPlus can use to authenticate
|
41 |
// Multiple jobs
|
42 |
-
// Multisite - a separate 'blogs' zip
|
43 |
// Allow connecting to remote storage, scanning + populating backup history from it
|
44 |
// GoogleDrive in-dashboard download resumption loads the whole archive into memory - should instead either chunk or directly stream fo the file handle
|
45 |
// Multisite add-on should allow restoring of each blog individually
|
@@ -49,14 +60,12 @@ TODO - some of these are out of date/done, needs pruning
|
|
49 |
// Remove the recurrence of admin notices when settings are saved due to _wp_referer
|
50 |
|
51 |
Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
|
52 |
-
// Does not delete old custom directories upon a restore?
|
53 |
// New sub-module to verify that the backups are there, independently of backup thread
|
54 |
*/
|
55 |
|
56 |
/* Portions copyright 2010 Paul Kehrer
|
57 |
Portions copyright 2011-13 David Anderson
|
58 |
Other portions copyright as indicated authors in the relevant files
|
59 |
-
Particular thanks to Sorin Iclanzan, author of the "Backup" plugin, from which much Google Drive code was taken under the GPLv3+
|
60 |
|
61 |
This program is free software; you can redistribute it and/or modify
|
62 |
it under the terms of the GNU General Public License as published by
|
@@ -73,9 +82,6 @@ along with this program; if not, write to the Free Software
|
|
73 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
74 |
*/
|
75 |
|
76 |
-
// 15 minutes
|
77 |
-
@set_time_limit(900);
|
78 |
-
|
79 |
define('UPDRAFTPLUS_DIR', dirname(__FILE__));
|
80 |
define('UPDRAFTPLUS_URL', plugins_url('', __FILE__));
|
81 |
define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php,backup,backups');
|
@@ -85,6 +91,7 @@ define('UPDRAFT_TRANSTIME', 3600*9+5);
|
|
85 |
|
86 |
// Load add-ons
|
87 |
if (is_file(UPDRAFTPLUS_DIR.'/premium.php')) require_once(UPDRAFTPLUS_DIR.'/premium.php');
|
|
|
88 |
|
89 |
if ($dir_handle = opendir(UPDRAFTPLUS_DIR.'/addons')) {
|
90 |
while ($e = readdir($dir_handle)) {
|
@@ -99,7 +106,7 @@ if (!isset($updraftplus)) $updraftplus = new UpdraftPlus();
|
|
99 |
|
100 |
if (!$updraftplus->memory_check(192)) {
|
101 |
// Experience appears to show that the memory limit is only likely to be hit (unless it is very low) by single files that are larger than available memory (when compressed)
|
102 |
-
@ini_set('memory_limit',
|
103 |
}
|
104 |
|
105 |
if (!class_exists('UpdraftPlus_Options')) require_once(UPDRAFTPLUS_DIR.'/options.php');
|
@@ -140,13 +147,6 @@ class UpdraftPlus {
|
|
140 |
var $current_resumption;
|
141 |
var $newresumption_scheduled = false;
|
142 |
|
143 |
-
var $zipfiles_added;
|
144 |
-
var $zipfiles_existingfiles;
|
145 |
-
var $zipfiles_dirbatched;
|
146 |
-
var $zipfiles_batched;
|
147 |
-
|
148 |
-
var $zip_preferpcl = false;
|
149 |
-
|
150 |
function __construct() {
|
151 |
|
152 |
// Initialisation actions - takes place on plugin load
|
@@ -160,33 +160,74 @@ class UpdraftPlus {
|
|
160 |
}
|
161 |
|
162 |
# Create admin page
|
163 |
-
add_action('
|
|
|
|
|
|
|
|
|
164 |
add_action('updraft_backup', array($this,'backup_files'));
|
165 |
add_action('updraft_backup_database', array($this,'backup_database'));
|
166 |
-
# backup_all is used by the manual "Backup Now" button
|
167 |
add_action('updraft_backup_all', array($this,'backup_all'));
|
168 |
# this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
|
169 |
add_action('updraft_backup_resume', array($this,'backup_resume'), 10, 3);
|
170 |
-
add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
|
171 |
-
add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
|
172 |
# http://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
|
173 |
add_filter('cron_schedules', array($this,'modify_cron_schedules'));
|
174 |
-
add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
|
175 |
-
add_action('init', array($this, 'handle_url_actions'));
|
176 |
add_action('plugins_loaded', array($this, 'load_translations'));
|
177 |
|
178 |
-
|
179 |
|
180 |
}
|
181 |
|
182 |
-
function
|
183 |
-
//
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
}
|
186 |
|
187 |
// Handle actions passed on to method plugins; e.g. Google OAuth 2.0 - ?page=updraftplus&action=updraftmethod-googledrive-auth
|
188 |
// Also handle action=downloadlog
|
189 |
function handle_url_actions() {
|
|
|
190 |
// First, basic security check: must be an admin page, with ability to manage options, with the right parameters
|
191 |
if ( UpdraftPlus_Options::user_can_manage() && isset( $_GET['page'] ) && $_GET['page'] == 'updraftplus' && isset($_GET['action']) ) {
|
192 |
if (preg_match("/^updraftmethod-([a-z]+)-([a-z]+)$/", $_GET['action'], $matches) && file_exists(UPDRAFTPLUS_DIR.'/methods/'.$matches[1].'.php')) {
|
@@ -194,8 +235,13 @@ class UpdraftPlus {
|
|
194 |
require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
195 |
$call_class = "UpdraftPlus_BackupModule_".$method;
|
196 |
$call_method = "action_".$matches[2];
|
|
|
|
|
197 |
if (method_exists($call_class, $call_method)) call_user_func(array($call_class,$call_method));
|
|
|
|
|
198 |
} elseif ($_GET['action'] == 'downloadlog' && isset($_GET['updraftplus_backup_nonce']) && preg_match("/^[0-9a-f]{12}$/",$_GET['updraftplus_backup_nonce'])) {
|
|
|
199 |
$updraft_dir = $this->backups_dir_location();
|
200 |
$log_file = $updraft_dir.'/log.'.$_GET['updraftplus_backup_nonce'].'.txt';
|
201 |
if (is_readable($log_file)) {
|
@@ -205,10 +251,40 @@ class UpdraftPlus {
|
|
205 |
} else {
|
206 |
add_action('admin_notices', array($this,'show_admin_warning_unreadablelog') );
|
207 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
}
|
209 |
}
|
210 |
}
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
// Cleans up temporary files found in the updraft directory
|
213 |
function clean_temporary_files() {
|
214 |
$updraft_dir = $this->backups_dir_location();
|
@@ -225,19 +301,6 @@ class UpdraftPlus {
|
|
225 |
}
|
226 |
}
|
227 |
|
228 |
-
# Adds the settings link under the plugin on the plugin screen.
|
229 |
-
function plugin_action_links($links, $file) {
|
230 |
-
if ($file == plugin_basename(__FILE__)){
|
231 |
-
$settings_link = '<a href="'.site_url().'/wp-admin/options-general.php?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
|
232 |
-
array_unshift($links, $settings_link);
|
233 |
-
// $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
|
234 |
-
// array_unshift($links, $settings_link);
|
235 |
-
$settings_link = '<a href="http://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
|
236 |
-
array_unshift($links, $settings_link);
|
237 |
-
}
|
238 |
-
return $links;
|
239 |
-
}
|
240 |
-
|
241 |
function backup_time_nonce() {
|
242 |
$this->backup_time = time();
|
243 |
$nonce = substr(md5(time().rand()), 20);
|
@@ -255,7 +318,7 @@ class UpdraftPlus {
|
|
255 |
$this->opened_log_time = microtime(true);
|
256 |
$this->log('Opened log file at time: '.date('r'));
|
257 |
global $wp_version;
|
258 |
-
$logline = "UpdraftPlus: ".$this->version." WP: ".$wp_version." PHP: ".phpversion()." (".php_uname().") max_execution_time: ".@ini_get("max_execution_time")." memory_limit: ".ini_get('memory_limit')." ZipArchive::addFile : ";
|
259 |
|
260 |
// method_exists causes some faulty PHP installations to segfault, leading to support requests
|
261 |
if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
|
@@ -297,11 +360,31 @@ class UpdraftPlus {
|
|
297 |
// i.e. Max 109 runs = 545 minutes = 9 hrs 05
|
298 |
// If they get 2 minutes on each run, and the file is 1Gb, then that equals 10.2Mb/120s = minimum 87Kb/s upload speed required
|
299 |
|
300 |
-
if ($
|
301 |
$this->something_useful_happened();
|
302 |
}
|
303 |
}
|
304 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
305 |
function minimum_resume_interval() {
|
306 |
// Bringing this down brings in more risk of undetectable overlaps than is worth it
|
307 |
return 300;
|
@@ -332,6 +415,7 @@ class UpdraftPlus {
|
|
332 |
|
333 |
$arr = apply_filters('updraft_backupable_file_entities', $arr, $full_info);
|
334 |
|
|
|
335 |
if ($include_others) {
|
336 |
if ($full_info) {
|
337 |
$arr['others'] = array('path' => WP_CONTENT_DIR, 'description' => __('Others','updraftplus'));
|
@@ -346,14 +430,25 @@ class UpdraftPlus {
|
|
346 |
|
347 |
function backup_resume($resumption_no, $bnonce) {
|
348 |
|
|
|
|
|
|
|
349 |
@ignore_user_abort(true);
|
350 |
// This is scheduled for 5 minutes after a backup job starts
|
351 |
|
352 |
// Restore state
|
|
|
353 |
if ($resumption_no > 0) {
|
354 |
$this->nonce = $bnonce;
|
355 |
$this->backup_time = $this->jobdata_get('backup_time');
|
356 |
$this->logfile_open($bnonce);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
}
|
358 |
|
359 |
$btime = $this->backup_time;
|
@@ -365,13 +460,37 @@ class UpdraftPlus {
|
|
365 |
$time_ago = time()-$btime;
|
366 |
|
367 |
$this->current_resumption = $resumption_no;
|
368 |
-
$this->log("Backup run: resumption=$resumption_no, nonce=$bnonce, begun at=$btime (${time_ago}s ago), job type
|
369 |
|
370 |
// Schedule again, to run in 5 minutes again, in case we again fail
|
371 |
// The actual interval can be increased (for future resumptions) by other code, if it detects apparent overlapping
|
372 |
$resume_interval = $this->jobdata_get('resume_interval');
|
373 |
if (!is_numeric($resume_interval) || $resume_interval<$this->minimum_resume_interval()) $resume_interval = $this->minimum_resume_interval();
|
374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
// A different argument than before is needed otherwise the event is ignored
|
376 |
$next_resumption = $resumption_no+1;
|
377 |
if ($next_resumption < 10) {
|
@@ -380,12 +499,12 @@ class UpdraftPlus {
|
|
380 |
wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($next_resumption, $bnonce));
|
381 |
$this->newresumption_scheduled = $schedule_for;
|
382 |
} else {
|
383 |
-
$this->log(sprintf('The current run is
|
384 |
}
|
385 |
|
386 |
// Sanity check
|
387 |
if (empty($this->backup_time)) {
|
388 |
-
$this->log('Abort this run: the backup_time parameter appears to be empty');
|
389 |
return false;
|
390 |
}
|
391 |
|
@@ -522,7 +641,6 @@ class UpdraftPlus {
|
|
522 |
set_transient("updraft_jobdata_".$this->nonce, $this->jobdata, 14400);
|
523 |
}
|
524 |
|
525 |
-
|
526 |
function jobdata_get($key) {
|
527 |
if (!is_array($this->jobdata)) {
|
528 |
$this->jobdata = get_transient("updraft_jobdata_".$this->nonce);
|
@@ -559,6 +677,8 @@ class UpdraftPlus {
|
|
559 |
function boot_backup($backup_files, $backup_database) {
|
560 |
|
561 |
@ignore_user_abort(true);
|
|
|
|
|
562 |
|
563 |
//generate backup information
|
564 |
$this->backup_time_nonce();
|
@@ -572,6 +692,7 @@ class UpdraftPlus {
|
|
572 |
|
573 |
// Some house-cleaning
|
574 |
$this->clean_temporary_files();
|
|
|
575 |
|
576 |
// Log some information that may be helpful
|
577 |
$this->log("Tasks: Backup files: $backup_files (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval', 'unset').") Backup DB: $backup_database (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval_database', 'unset').")");
|
@@ -668,13 +789,13 @@ class UpdraftPlus {
|
|
668 |
// Make sure that the final status is shown
|
669 |
if (empty($this->errors)) {
|
670 |
$send_an_email = true;
|
671 |
-
$final_message = "The backup apparently succeeded and is now complete";
|
672 |
} elseif ($this->newresumption_scheduled == false) {
|
673 |
$send_an_email = true;
|
674 |
-
$final_message = "The backup attempt has finished, apparently unsuccessfully";
|
675 |
} else {
|
676 |
// There are errors, but a resumption will be attempted
|
677 |
-
$final_message = "The backup has not finished; a resumption is scheduled within 5 minutes";
|
678 |
}
|
679 |
|
680 |
// Now over-ride the decision to send an email, if needed
|
@@ -761,7 +882,9 @@ class UpdraftPlus {
|
|
761 |
@set_time_limit(900);
|
762 |
|
763 |
$method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
|
|
|
764 |
if (file_exists($method_include)) require_once($method_include);
|
|
|
765 |
|
766 |
if ($service == "none") {
|
767 |
$this->log("No remote despatch: user chose no remote backup service");
|
@@ -933,64 +1056,19 @@ class UpdraftPlus {
|
|
933 |
$this->newresumption_scheduled = $schedule_for;
|
934 |
}
|
935 |
|
936 |
-
function increase_resume_and_reschedule($howmuch = 120) {
|
937 |
-
$resume_interval = $this->jobdata_get('resume_interval');
|
938 |
-
if (!is_numeric($resume_interval) || $resume_interval < $this->minimum_resume_interval()) { $resume_interval = $this->minimum_resume_interval(); }
|
939 |
-
if (!empty($this->newresumption_scheduled)) $this->reschedule($resume_interval+$howmuch);
|
940 |
-
$this->jobdata_set('resume_interval', $resume_interval+$howmuch);
|
941 |
-
$this->log("To decrease the likelihood of overlaps, increasing resumption interval to: $resume_interval + $howmuch = ".($resume_interval+$howmuch));
|
942 |
-
}
|
943 |
-
|
944 |
-
function create_zip($create_from_dir, $whichone, $create_in_dir, $backup_file_basename) {
|
945 |
-
// Note: $create_from_dir can be an array or a string
|
946 |
-
@set_time_limit(900);
|
947 |
-
|
948 |
-
if ($whichone != "others") $this->log("Beginning creation of dump of $whichone");
|
949 |
-
|
950 |
-
$full_path = $create_in_dir.'/'.$backup_file_basename.'-'.$whichone.'.zip';
|
951 |
-
$time_now = time();
|
952 |
-
|
953 |
-
if (file_exists($full_path)) {
|
954 |
-
$this->log("$backup_file_basename-$whichone.zip: this file has already been created");
|
955 |
-
$time_mod = (int)@filemtime($full_path);
|
956 |
-
if ($time_mod>100 && ($time_now-$time_mod)<30) {
|
957 |
-
$this->log("Terminate: the zip $full_path already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=".filesize($full_path)."). This likely means that another UpdraftPlus run is still at work; so we will exit.");
|
958 |
-
$this->increase_resume_and_reschedule(120);
|
959 |
-
die;
|
960 |
-
}
|
961 |
-
return basename($full_path);
|
962 |
-
}
|
963 |
|
964 |
-
|
|
|
965 |
|
966 |
-
|
967 |
-
|
968 |
-
$time_mod = (int)@filemtime($zip_name);
|
969 |
-
if (file_exists($zip_name) && $time_mod>100 && ($time_now-$time_mod)<30) {
|
970 |
-
$file_size = filesize($zip_name);
|
971 |
-
$this->log("Terminate: the temporary file $zip_name already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=$file_size). This likely means that another UpdraftPlus run is still at work; so we will exit.");
|
972 |
-
$this->increase_resume_and_reschedule(120);
|
973 |
-
die;
|
974 |
-
} elseif (file_exists($zip_name)) {
|
975 |
-
$this->log("File exists ($zip_name), but was apparently not modified within the last 30 seconds, so we assume that any previous run has now terminated (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).")");
|
976 |
}
|
977 |
|
978 |
-
$
|
979 |
-
|
980 |
-
$zipcode = $this->make_zipfile($create_from_dir, $zip_name);
|
981 |
-
if ($zipcode !== true) {
|
982 |
-
$this->log("ERROR: Zip failure: Could not create $whichone zip: code=$zipcode");
|
983 |
-
$this->error(sprintf(__("Could not create %s zip. Consult the log file for more information.",'updraftplus'),$whichone));
|
984 |
-
return false;
|
985 |
-
} else {
|
986 |
-
rename($full_path.'.tmp', $full_path);
|
987 |
-
$timetaken = max(microtime(true)-$microtime_start, 0.000001);
|
988 |
-
$kbsize = filesize($full_path)/1024;
|
989 |
-
$rate = round($kbsize/$timetaken, 1);
|
990 |
-
$this->log("Created $whichone zip - file size is ".round($kbsize,1)." Kb in ".round($timetaken,1)." s ($rate Kb/s)");
|
991 |
-
}
|
992 |
|
993 |
-
|
994 |
}
|
995 |
|
996 |
// For detecting another run, and aborting if one was found
|
@@ -999,9 +1077,7 @@ class UpdraftPlus {
|
|
999 |
$time_mod = (int)@filemtime($file);
|
1000 |
$time_now = time();
|
1001 |
if ($time_mod>100 && ($time_now-$time_mod)<30) {
|
1002 |
-
$this->
|
1003 |
-
$this->increase_resume_and_reschedule(120);
|
1004 |
-
die;
|
1005 |
}
|
1006 |
}
|
1007 |
}
|
@@ -1018,6 +1094,10 @@ class UpdraftPlus {
|
|
1018 |
return array();
|
1019 |
}
|
1020 |
|
|
|
|
|
|
|
|
|
1021 |
//get the blog name and rip out all non-alphanumeric chars other than _
|
1022 |
$blog_name = str_replace(' ','_',substr(get_bloginfo(), 0, 96));
|
1023 |
$blog_name = preg_replace('/[^A-Za-z0-9_]/','', $blog_name);
|
@@ -1032,7 +1112,8 @@ class UpdraftPlus {
|
|
1032 |
# Plugins, themes, uploads
|
1033 |
foreach ($possible_backups as $youwhat => $whichdir) {
|
1034 |
|
1035 |
-
|
|
|
1036 |
|
1037 |
$zip_file = $updraft_dir.'/'.$backup_file_basename.'-'.$youwhat.'.zip';
|
1038 |
|
@@ -1042,7 +1123,12 @@ class UpdraftPlus {
|
|
1042 |
$backup_array[$youwhat] = $backup_file_basename.'-'.$youwhat.'.zip';
|
1043 |
if (file_exists($zip_file)) $backup_array[$youwhat.'-size'] = filesize($zip_file);
|
1044 |
} else {
|
1045 |
-
|
|
|
|
|
|
|
|
|
|
|
1046 |
if ($created) {
|
1047 |
$backup_array[$youwhat] = $created;
|
1048 |
$backup_array[$youwhat.'-size'] = filesize($updraft_dir.'/'.$created);
|
@@ -1074,41 +1160,17 @@ class UpdraftPlus {
|
|
1074 |
A string containing a list of filename or dirname separated by a comma.
|
1075 |
*/
|
1076 |
|
1077 |
-
#
|
1078 |
-
$other_dirlist = array();
|
1079 |
-
|
1080 |
$others_skip = preg_split("/,/",UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude', UPDRAFT_DEFAULT_OTHERS_EXCLUDE));
|
1081 |
# Make the values into the keys
|
1082 |
$others_skip = array_flip($others_skip);
|
1083 |
|
1084 |
-
$
|
1085 |
-
|
1086 |
-
|
1087 |
-
$possible_backups_dirs = array_flip($possible_backups);
|
1088 |
-
|
1089 |
-
while (false !== ($entry = readdir($handle))) {
|
1090 |
-
$candidate = WP_CONTENT_DIR.'/'.$entry;
|
1091 |
-
if ($entry != "." && $entry != "..") {
|
1092 |
-
if (isset($possible_backups_dirs[$candidate])) {
|
1093 |
-
$this->log("others: $entry: skipping: this is the ".$possible_backups_dirs[$candidate]." directory");
|
1094 |
-
} elseif ($candidate == $updraft_dir) {
|
1095 |
-
$this->log("others: $entry: skipping: this is the updraft directory");
|
1096 |
-
} elseif (isset($others_skip[$entry])) {
|
1097 |
-
$this->log("others: $entry: skipping: excluded by options");
|
1098 |
-
} else {
|
1099 |
-
$this->log("others: $entry: adding to list");
|
1100 |
-
array_push($other_dirlist, $candidate);
|
1101 |
-
}
|
1102 |
-
}
|
1103 |
-
}
|
1104 |
-
@closedir($handle);
|
1105 |
-
} else {
|
1106 |
-
$this->log('ERROR: Could not read the content directory: '.WP_CONTENT_DIR);
|
1107 |
-
$this->error(__('Could not read the content directory', 'updraftplus').': '.WP_CONTENT_DIR);
|
1108 |
-
}
|
1109 |
|
1110 |
if (count($other_dirlist)>0) {
|
1111 |
-
$created = $
|
1112 |
if ($created) {
|
1113 |
$backup_array['others'] = $created;
|
1114 |
$backup_array['others-size'] = filesize($updraft_dir.'/'.$created);
|
@@ -1116,6 +1178,7 @@ class UpdraftPlus {
|
|
1116 |
} else {
|
1117 |
$this->log("No backup of other directories: there was nothing found to back up");
|
1118 |
}
|
|
|
1119 |
# If we are not already finished
|
1120 |
}
|
1121 |
} else {
|
@@ -1124,6 +1187,41 @@ class UpdraftPlus {
|
|
1124 |
return $backup_array;
|
1125 |
}
|
1126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1127 |
function save_backup_history($backup_array) {
|
1128 |
if(is_array($backup_array)) {
|
1129 |
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
@@ -1171,6 +1269,7 @@ class UpdraftPlus {
|
|
1171 |
|
1172 |
//Begin new backup of MySql
|
1173 |
$this->stow("# " . 'WordPress MySQL database backup' . "\n");
|
|
|
1174 |
$this->stow("#\n");
|
1175 |
$this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
|
1176 |
$this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
|
@@ -1260,10 +1359,7 @@ class UpdraftPlus {
|
|
1260 |
$time_now = time();
|
1261 |
$time_mod = (int)@filemtime($backup_final_file_name);
|
1262 |
if (file_exists($backup_final_file_name) && $time_mod>100 && ($time_now-$time_mod)<20) {
|
1263 |
-
$
|
1264 |
-
$this->log("Terminate: the final database file ($backup_final_file_name) exists, and was modified within the last 20 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=$file_size). This likely means that another UpdraftPlus run is at work; so we will exit.");
|
1265 |
-
$this->increase_resume_and_reschedule(120);
|
1266 |
-
die;
|
1267 |
} elseif (file_exists($backup_final_file_name)) {
|
1268 |
$this->log("The final database file ($backup_final_file_name) exists, but was apparently not modified within the last 20 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod)."). Thus we assume that another UpdraftPlus terminated; thus we will continue.");
|
1269 |
}
|
@@ -1308,6 +1404,13 @@ class UpdraftPlus {
|
|
1308 |
|
1309 |
} //wp_db_backup
|
1310 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1311 |
/**
|
1312 |
* Taken partially from phpMyAdmin and partially from
|
1313 |
* Alain Wolf, Zurich - Switzerland
|
@@ -1357,13 +1460,12 @@ class UpdraftPlus {
|
|
1357 |
$this->stow($create_table[0][1] . ' ;');
|
1358 |
|
1359 |
if (false === $table_structure) {
|
1360 |
-
$err_msg = sprintf(
|
1361 |
-
//$this->error($err_msg);
|
1362 |
$this->stow("#\n# $err_msg\n#\n");
|
1363 |
}
|
1364 |
|
1365 |
// Comment in SQL-file
|
1366 |
-
$this->stow("\n\n#\n# " . sprintf(
|
1367 |
}
|
1368 |
|
1369 |
// In UpdraftPlus, segment is always 'none'
|
@@ -1389,12 +1491,14 @@ class UpdraftPlus {
|
|
1389 |
|
1390 |
do {
|
1391 |
if ( !@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == "off") @set_time_limit(15*60);
|
|
|
1392 |
$table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
|
1393 |
-
$entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES
|
1394 |
// \x08\\x09, not required
|
1395 |
$search = array("\x00", "\x0a", "\x0d", "\x1a");
|
1396 |
$replace = array('\0', '\n', '\r', '\Z');
|
1397 |
if($table_data) {
|
|
|
1398 |
foreach ($table_data as $row) {
|
1399 |
$total_rows++;
|
1400 |
$values = array();
|
@@ -1408,8 +1512,16 @@ class UpdraftPlus {
|
|
1408 |
$values[] = "'" . str_replace($search, $replace, str_replace('\'', '\\\'', str_replace('\\', '\\\\', $value))) . "'";
|
1409 |
}
|
1410 |
}
|
1411 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1412 |
}
|
|
|
1413 |
$row_start += $row_inc;
|
1414 |
}
|
1415 |
} while((count($table_data) > 0) and ($segment=='none'));
|
@@ -1475,12 +1587,6 @@ class UpdraftPlus {
|
|
1475 |
|
1476 |
/*END OF WP-DB-BACKUP BLOCK */
|
1477 |
|
1478 |
-
function hourminute($pot) {
|
1479 |
-
if (preg_match("/^[0-2][0-9]:[0-5][0-9]$/", $pot)) return $pot;
|
1480 |
-
if ('' == $pot) return date('H:i', time()+300);
|
1481 |
-
return '00:00';
|
1482 |
-
}
|
1483 |
-
|
1484 |
/*
|
1485 |
this function is both the backup scheduler and ostensibly a filter callback for saving the option.
|
1486 |
it is called in the register_setting for the updraft_interval, which means when the admin settings
|
@@ -1505,11 +1611,18 @@ class UpdraftPlus {
|
|
1505 |
return wp_filter_nohtml_kses($interval);
|
1506 |
}
|
1507 |
|
|
|
|
|
|
|
|
|
1508 |
// Acts as a WordPress options filter
|
1509 |
function googledrive_clientid_checkchange($client_id) {
|
1510 |
-
if (UpdraftPlus_Options::get_updraft_option('
|
1511 |
require_once(UPDRAFTPLUS_DIR.'/methods/googledrive.php');
|
|
|
1512 |
UpdraftPlus_BackupModule_googledrive::gdrive_auth_revoke(true);
|
|
|
|
|
1513 |
}
|
1514 |
return $client_id;
|
1515 |
}
|
@@ -1542,16 +1655,6 @@ class UpdraftPlus {
|
|
1542 |
return $schedules;
|
1543 |
}
|
1544 |
|
1545 |
-
// This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
|
1546 |
-
function prune_updraft_dir_prefix($updraft_dir) {
|
1547 |
-
if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
|
1548 |
-
if (strpos($updraft_dir, ABSPATH) === 0) {
|
1549 |
-
$updraft_dir = substr($updraft_dir, strlen(ABSPATH));
|
1550 |
-
}
|
1551 |
-
}
|
1552 |
-
return $updraft_dir;
|
1553 |
-
}
|
1554 |
-
|
1555 |
function backups_dir_location() {
|
1556 |
|
1557 |
if (!empty($this->backup_dir)) return $this->backup_dir;
|
@@ -1579,251 +1682,9 @@ class UpdraftPlus {
|
|
1579 |
return $updraft_dir;
|
1580 |
}
|
1581 |
|
1582 |
-
function
|
1583 |
-
$size = 0;
|
1584 |
-
if(substr($directory,-1) == '/') $directory = substr($directory,0,-1);
|
1585 |
-
|
1586 |
-
if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
|
1587 |
-
|
1588 |
-
if($handle = opendir($directory)) {
|
1589 |
-
while(($file = readdir($handle)) !== false) {
|
1590 |
-
$path = $directory.'/'.$file;
|
1591 |
-
if($file != '.' && $file != '..') {
|
1592 |
-
if(is_file($path)) {
|
1593 |
-
$size += filesize($path);
|
1594 |
-
} elseif(is_dir($path)) {
|
1595 |
-
$handlesize = recursive_directory_size($path);
|
1596 |
-
if($handlesize >= 0) { $size += $handlesize; } else { return -1; }
|
1597 |
-
}
|
1598 |
-
}
|
1599 |
-
}
|
1600 |
-
closedir($handle);
|
1601 |
-
}
|
1602 |
-
if ($size > 1073741824) {
|
1603 |
-
return round($size / 1048576, 1).' Gb';
|
1604 |
-
} elseif ($size > 1048576) {
|
1605 |
-
return round($size / 1048576, 1).' Mb';
|
1606 |
-
} elseif ($size > 1024) {
|
1607 |
-
return round($size / 1024, 1).' Kb';
|
1608 |
-
} else {
|
1609 |
-
return round($size, 1).' b';
|
1610 |
-
}
|
1611 |
-
}
|
1612 |
-
|
1613 |
-
// This function examines inside the updraft directory to see if any new archives have been uploaded. If so, it adds them to the backup set. (No removal of items from the backup set is done)
|
1614 |
-
function rebuild_backup_history() {
|
1615 |
-
|
1616 |
-
$known_files = array();
|
1617 |
-
$known_nonces = array();
|
1618 |
-
$changes = false;
|
1619 |
-
|
1620 |
-
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
1621 |
-
if (!is_array($backup_history)) $backup_history = array();
|
1622 |
-
|
1623 |
-
// Accumulate a list of known files
|
1624 |
-
foreach ($backup_history as $btime => $bdata) {
|
1625 |
-
foreach ($bdata as $key => $value) {
|
1626 |
-
// Record which set this file is found in
|
1627 |
-
if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz)$/i', $value, $matches)) {
|
1628 |
-
$nonce = $matches[2];
|
1629 |
-
$known_files[$value] = $nonce;
|
1630 |
-
$known_nonces[$nonce] = $btime;
|
1631 |
-
}
|
1632 |
-
}
|
1633 |
-
}
|
1634 |
-
|
1635 |
-
$updraft_dir = $this->backups_dir_location();
|
1636 |
-
|
1637 |
-
if (!is_dir($updraft_dir)) return;
|
1638 |
-
|
1639 |
-
if (!$handle = opendir($updraft_dir)) return;
|
1640 |
-
|
1641 |
-
while (false !== ($entry = readdir($handle))) {
|
1642 |
-
if ($entry != "." && $entry != "..") {
|
1643 |
-
if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)\.(zip|gz)$/i', $entry, $matches)) {
|
1644 |
-
$btime = strtotime($matches[1]);
|
1645 |
-
if ($btime > 100) {
|
1646 |
-
if (!isset($known_files[$entry])) {
|
1647 |
-
$changes = true;
|
1648 |
-
$nonce = $matches[2];
|
1649 |
-
$type = $matches[3];
|
1650 |
-
// The time from the filename does not include seconds. Need to identify the seconds to get the right time
|
1651 |
-
if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
|
1652 |
-
if (!isset($backup_history[$btime])) $backup_history[$btime] = array();
|
1653 |
-
$backup_history[$btime][$type] = $entry;
|
1654 |
-
$backup_history[$btime][$type.'-size'] = filesize($updraft_dir.'/'.$entry);
|
1655 |
-
$backup_history[$btime]['nonce'] = $nonce;
|
1656 |
-
}
|
1657 |
-
}
|
1658 |
-
}
|
1659 |
-
}
|
1660 |
-
}
|
1661 |
-
|
1662 |
-
|
1663 |
-
if ($changes) UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backup_history);
|
1664 |
-
|
1665 |
-
}
|
1666 |
-
|
1667 |
-
// Called via AJAX
|
1668 |
-
function updraft_ajax_handler() {
|
1669 |
-
// Test the nonce (probably not needed, since we're presumably admin-authed, but there's no harm)
|
1670 |
-
$nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
|
1671 |
-
if (! wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
|
1672 |
-
|
1673 |
-
if ('lastlog' == $_GET['subaction']) {
|
1674 |
-
echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')'));
|
1675 |
-
} elseif ('lastbackup' == $_GET['subaction']) {
|
1676 |
-
echo $this->last_backup_html();
|
1677 |
-
} elseif ('diskspaceused' == $_GET['subaction']) {
|
1678 |
-
echo $this->recursive_directory_size($this->backups_dir_location());
|
1679 |
-
} elseif ('historystatus' == $_GET['subaction']) {
|
1680 |
-
$rescan = (isset($_GET['rescan']) && $_GET['rescan'] == 1);
|
1681 |
-
if ($rescan) $this->rebuild_backup_history();
|
1682 |
-
echo $this->existing_backup_table();
|
1683 |
-
} elseif ('downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
|
1684 |
-
|
1685 |
-
echo get_transient('ud_dlmess_'.$_GET['timestamp'].'_'.$_GET['type']).'<br>';
|
1686 |
-
|
1687 |
-
if ($file = get_transient('ud_dlfile_'.$_GET['timestamp'].'_'.$_GET['type'])) {
|
1688 |
-
if ('failed' == $file) {
|
1689 |
-
echo "Download failed";
|
1690 |
-
} elseif (preg_match('/^downloaded:(.*)$/', $file, $matches) && file_exists($matches[1])) {
|
1691 |
-
$size = round(filesize($matches[1])/1024, 1);
|
1692 |
-
echo "File ready: $size Kb: You should: <button type=\"button\" onclick=\"updraftplus_downloadstage2('".$_GET['timestamp']."', '".$_GET['type']."')\">Download to your computer</button> and then, if you wish, <button id=\"uddownloaddelete_".$_GET['timestamp']."_".$_GET['type']."\" type=\"button\" onclick=\"updraftplus_deletefromserver('".$_GET['timestamp']."', '".$_GET['type']."')\">Delete from your web server</button>";
|
1693 |
-
} elseif (preg_match('/^downloading:(.*)$/', $file, $matches) && file_exists($matches[1])) {
|
1694 |
-
$size = round(filesize($matches[1])/1024, 1);
|
1695 |
-
echo __('File downloading', 'updraftplus').": ".basename($matches[1]).": $size Kb";
|
1696 |
-
} else {
|
1697 |
-
echo __("No local copy present.", 'updraftplus');
|
1698 |
-
}
|
1699 |
-
}
|
1700 |
-
|
1701 |
-
} elseif ($_POST['subaction'] == 'credentials_test') {
|
1702 |
-
$method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
|
1703 |
-
|
1704 |
-
// Test the credentials, return a code
|
1705 |
-
require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
|
1706 |
-
|
1707 |
-
$objname = "UpdraftPlus_BackupModule_${method}";
|
1708 |
-
if (method_exists($objname, "credentials_test")) call_user_func(array('UpdraftPlus_BackupModule_'.$method, 'credentials_test'));
|
1709 |
-
}
|
1710 |
-
|
1711 |
-
die;
|
1712 |
-
|
1713 |
-
}
|
1714 |
-
|
1715 |
-
function updraft_download_backup() {
|
1716 |
-
|
1717 |
-
if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
|
1718 |
-
|
1719 |
-
if (!isset($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || !isset($_REQUEST['type'])) exit;
|
1720 |
-
|
1721 |
-
$backupable_entities = $this->get_backupable_file_entities(true);
|
1722 |
-
$type_match = false;
|
1723 |
-
foreach ($backupable_entities as $type => $info) {
|
1724 |
-
if ($_REQUEST['type'] == $type) $type_match = true;
|
1725 |
-
}
|
1726 |
-
|
1727 |
-
if (!$type_match && $_REQUEST['type'] != 'db') exit;
|
1728 |
-
|
1729 |
-
// Get the information on what is wanted
|
1730 |
-
$type = $_REQUEST['type'];
|
1731 |
-
$timestamp = $_REQUEST['timestamp'];
|
1732 |
-
|
1733 |
-
// You need a nonce before you can set job data. And we certainly don't yet have one.
|
1734 |
-
$this->backup_time_nonce();
|
1735 |
-
|
1736 |
-
$debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
|
1737 |
-
|
1738 |
-
// Set the job type before logging, as there can be different logging destinations
|
1739 |
-
$this->jobdata_set('job_type', 'download');
|
1740 |
-
|
1741 |
-
// Retrieve the information from our backup history
|
1742 |
-
$backup_history = $this->get_backup_history();
|
1743 |
-
// Base name
|
1744 |
-
$file = $backup_history[$timestamp][$type];
|
1745 |
-
|
1746 |
-
// Where it should end up being downloaded to
|
1747 |
-
$fullpath = $this->backups_dir_location().'/'.$file;
|
1748 |
-
|
1749 |
-
if (isset($_GET['stage']) && '2' == $_GET['stage']) {
|
1750 |
-
$this->spool_file($timestamp, $type, $fullpath);
|
1751 |
-
die;
|
1752 |
-
}
|
1753 |
-
|
1754 |
-
if (isset($_POST['stage']) && 'delete' == $_POST['stage']) {
|
1755 |
-
@unlink($fullpath);
|
1756 |
-
echo 'deleted';
|
1757 |
-
$this->log('The file has been deleted');
|
1758 |
-
die;
|
1759 |
-
}
|
1760 |
-
|
1761 |
-
// TODO: FIXME: Failed downloads may leave log files forever (though they are small)
|
1762 |
-
// Note that log() assumes that the data is in _POST, not _GET
|
1763 |
-
if ($debug_mode) $this->logfile_open($this->nonce);
|
1764 |
-
|
1765 |
-
$this->log("Requested to obtain file: timestamp=$timestamp, type=$type");
|
1766 |
-
|
1767 |
-
// The AJAX responder that updates on progress wants to see this
|
1768 |
-
set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'downloading:'.$fullpath, 3600);
|
1769 |
-
|
1770 |
-
$service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
|
1771 |
-
$this->jobdata_set('service', $service);
|
1772 |
-
|
1773 |
-
// Fetch it from the cloud, if we have not already got it
|
1774 |
-
|
1775 |
-
$needs_downloading = false;
|
1776 |
-
$known_size = isset($backup_history[$timestamp][$type.'-size']) ? $backup_history[$timestamp][$type.'-size'] : false;
|
1777 |
-
|
1778 |
-
if(!file_exists($fullpath)) {
|
1779 |
-
//if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
|
1780 |
-
$needs_downloading = true;
|
1781 |
-
$this->log('File does not yet exist locally - needs downloading');
|
1782 |
-
} elseif ($known_size>0 && filesize($fullpath) < $known_size) {
|
1783 |
-
$this->log('The file was found locally but did not match the size in the backup history - will resume downloading');
|
1784 |
-
$needs_downloading = true;
|
1785 |
-
} elseif ($known_size>0) {
|
1786 |
-
$this->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' Kb)');
|
1787 |
-
} else {
|
1788 |
-
$this->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
|
1789 |
-
}
|
1790 |
-
|
1791 |
-
if ($needs_downloading) {
|
1792 |
-
// Close browser connection so that it can resume AJAX polling
|
1793 |
-
header('Connection: close');
|
1794 |
-
header('Content-Length: 0');
|
1795 |
-
header('Content-Encoding: none');
|
1796 |
-
session_write_close();
|
1797 |
-
echo "\r\n\r\n";
|
1798 |
-
$this->download_file($file, $service);
|
1799 |
-
if (is_readable($fullpath)) {
|
1800 |
-
$this->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
|
1801 |
-
} else {
|
1802 |
-
$this->log('Remote fetch failed');
|
1803 |
-
}
|
1804 |
-
}
|
1805 |
-
|
1806 |
-
// Now, spool the thing to the browser
|
1807 |
-
if(is_file($fullpath) && is_readable($fullpath)) {
|
1808 |
-
|
1809 |
-
// That message is then picked up by the AJAX listener
|
1810 |
-
set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'downloaded:'.$fullpath, 3600);
|
1811 |
-
|
1812 |
-
} else {
|
1813 |
-
|
1814 |
-
set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'failed', 3600);
|
1815 |
-
|
1816 |
-
echo 'Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.';
|
1817 |
-
}
|
1818 |
-
|
1819 |
-
@fclose($this->logfile_handle);
|
1820 |
-
if (!$debug_mode) @unlink($this->logfile_name);
|
1821 |
-
|
1822 |
-
exit;
|
1823 |
|
1824 |
-
|
1825 |
-
|
1826 |
-
function spool_file($timestamp, $type, $fullpath) {
|
1827 |
|
1828 |
if (file_exists($fullpath)) {
|
1829 |
|
@@ -1834,38 +1695,38 @@ class UpdraftPlus {
|
|
1834 |
$filearr = explode('.',$file);
|
1835 |
// //we've only got zip and gz...for now
|
1836 |
$file_ext = array_pop($filearr);
|
1837 |
-
if($file_ext == 'zip') {
|
1838 |
-
header('Content-type: application/zip');
|
1839 |
-
} else {
|
1840 |
-
// This catches both when what was popped was 'crypt' (*-db.gz.crypt) and when it was 'gz' (unencrypted)
|
1841 |
-
header('Content-type: application/x-gzip');
|
1842 |
-
}
|
1843 |
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
|
1844 |
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
|
1845 |
header("Content-Length: $len;");
|
|
|
1846 |
if ($file_ext == 'crypt') {
|
1847 |
-
|
1848 |
-
} else {
|
1849 |
-
header("Content-Disposition: attachment; filename=\"$file\";");
|
1850 |
-
}
|
1851 |
-
ob_end_flush();
|
1852 |
-
if ($file_ext == 'crypt') {
|
1853 |
-
$encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
|
1854 |
if ($encryption == "") {
|
|
|
|
|
1855 |
$this->error('Decryption of database failed: the database file is encrypted, but you have no encryption key entered.');
|
1856 |
} else {
|
1857 |
-
require_once(
|
1858 |
$rijndael = new Crypt_Rijndael();
|
1859 |
$rijndael->setKey($encryption);
|
1860 |
-
$
|
1861 |
-
$ciphertext
|
1862 |
-
|
1863 |
-
|
|
|
|
|
|
|
|
|
|
|
1864 |
}
|
1865 |
-
fclose ($in_handle);
|
1866 |
-
print $rijndael->decrypt($ciphertext);
|
1867 |
}
|
1868 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
1869 |
readfile($fullpath);
|
1870 |
}
|
1871 |
// $this->delete_local($file);
|
@@ -1874,193 +1735,9 @@ class UpdraftPlus {
|
|
1874 |
}
|
1875 |
}
|
1876 |
|
1877 |
-
function
|
1878 |
-
|
1879 |
-
|
1880 |
-
|
1881 |
-
$this->log("Requested file from remote service: service=$service, file=$file");
|
1882 |
-
|
1883 |
-
$method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
|
1884 |
-
if (file_exists($method_include)) require_once($method_include);
|
1885 |
-
|
1886 |
-
$objname = "UpdraftPlus_BackupModule_${service}";
|
1887 |
-
if (method_exists($objname, "download")) {
|
1888 |
-
$remote_obj = new $objname;
|
1889 |
-
$remote_obj->download($file);
|
1890 |
-
} else {
|
1891 |
-
$this->log("Automatic backup restoration is not available with the method: $service.");
|
1892 |
-
$this->error("$file: ".sprintf(__("The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($this->backups_dir_location()).")");
|
1893 |
-
}
|
1894 |
-
|
1895 |
-
}
|
1896 |
-
|
1897 |
-
function restore_backup($timestamp) {
|
1898 |
-
|
1899 |
-
global $wp_filesystem;
|
1900 |
-
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
1901 |
-
if(!is_array($backup_history[$timestamp])) {
|
1902 |
-
echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
|
1903 |
-
return false;
|
1904 |
-
}
|
1905 |
-
|
1906 |
-
$credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp");
|
1907 |
-
WP_Filesystem($credentials);
|
1908 |
-
if ( $wp_filesystem->errors->get_error_code() ) {
|
1909 |
-
foreach ( $wp_filesystem->errors->get_error_messages() as $message )
|
1910 |
-
show_message($message);
|
1911 |
-
exit;
|
1912 |
-
}
|
1913 |
-
|
1914 |
-
//if we make it this far then WP_Filesystem has been instantiated and is functional (tested with ftpext, what about suPHP and other situations where direct may work?)
|
1915 |
-
echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
|
1916 |
-
|
1917 |
-
$updraft_dir = $this->backups_dir_location().'/';
|
1918 |
-
|
1919 |
-
$service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
|
1920 |
-
|
1921 |
-
if (!isset($_POST['updraft_restore']) || !is_array($_POST['updraft_restore'])) {
|
1922 |
-
echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
|
1923 |
-
return false;
|
1924 |
-
}
|
1925 |
-
|
1926 |
-
$entities_to_restore = array_flip($_POST['updraft_restore']);
|
1927 |
-
|
1928 |
-
$backupable_entities = $this->get_backupable_file_entities(true, true);
|
1929 |
-
|
1930 |
-
foreach($backup_history[$timestamp] as $type => $file) {
|
1931 |
-
// All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
|
1932 |
-
|
1933 |
-
if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
|
1934 |
-
|
1935 |
-
if ($type == 'db') {
|
1936 |
-
echo "<h2>".__('Database','updraftplus')."</h2>";
|
1937 |
-
} else {
|
1938 |
-
echo "<h2>".$backupable_entities[$type]['description']."</h2>";
|
1939 |
-
}
|
1940 |
-
|
1941 |
-
if (!isset($entities_to_restore[$type])) {
|
1942 |
-
echo "<p>$type: ".__('This component was not selected for restoration - skipping.', 'updraftplus')."</p>";
|
1943 |
-
continue;
|
1944 |
-
}
|
1945 |
-
|
1946 |
-
$fullpath = $updraft_dir.$file;
|
1947 |
-
|
1948 |
-
echo "Looking for $type archive: file name: ".htmlspecialchars($file)."<br>";
|
1949 |
-
if(!is_readable($fullpath) && $type != 'db') {
|
1950 |
-
echo __("File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)",'updraftplus')."<br>";
|
1951 |
-
$this->download_file($file, $service);
|
1952 |
-
}
|
1953 |
-
// If a file size is stored in the backup data, then verify correctness of the local file
|
1954 |
-
if (isset($backup_history[$timestamp][$type.'-size'])) {
|
1955 |
-
$fs = $backup_history[$timestamp][$type.'-size'];
|
1956 |
-
echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024)." Kb :";
|
1957 |
-
$as = @filesize($fullpath);
|
1958 |
-
if ($as == $fs) {
|
1959 |
-
echo "OK<br>";
|
1960 |
-
} else {
|
1961 |
-
echo "<strong>".__('ERROR','updraftplus').":</strong> is size: ".round($as/1024)." ($fs, $as)<br>";
|
1962 |
-
}
|
1963 |
-
} else {
|
1964 |
-
echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
|
1965 |
-
}
|
1966 |
-
# Types: uploads, themes, plugins, others, db
|
1967 |
-
if(is_readable($fullpath) && $type != 'db') {
|
1968 |
-
|
1969 |
-
if(!class_exists('WP_Upgrader')) require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
|
1970 |
-
require_once(UPDRAFTPLUS_DIR.'/includes/updraft-restorer.php');
|
1971 |
-
$restorer = new Updraft_Restorer();
|
1972 |
-
$val = $restorer->restore_backup($fullpath, $type, $service, $backupable_entities[$type]);
|
1973 |
-
|
1974 |
-
if(is_wp_error($val)) {
|
1975 |
-
foreach ($val->get_error_messages() as $msg) {
|
1976 |
-
echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
|
1977 |
-
}
|
1978 |
-
echo '</div>'; //close the updraft_restore_progress div even if we error
|
1979 |
-
return false;
|
1980 |
-
}
|
1981 |
-
} elseif ($type != 'db') {
|
1982 |
-
$this->error("$file: ".__('Could not find one of the files for restoration', 'updraftplus'));
|
1983 |
-
echo __('Could not find one of the files for restoration', 'updraftplus').": ($file)";
|
1984 |
-
} else {
|
1985 |
-
echo __("Databases are not yet restored through this mechanism - use your web host's control panel, phpMyAdmin or a similar tool",'updraftplus')."<br>";
|
1986 |
-
}
|
1987 |
-
}
|
1988 |
-
echo '</div>'; //close the updraft_restore_progress div
|
1989 |
-
# The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
|
1990 |
-
if(@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
|
1991 |
-
echo "<p>".__('Database could not be restored because PHP safe_mode is active on your server. You will need to manually restore the file via phpMyAdmin or another method.', 'updraftplus')."</p><br/>";
|
1992 |
-
return false;
|
1993 |
-
}
|
1994 |
-
return true;
|
1995 |
-
}
|
1996 |
-
|
1997 |
-
//deletes the -old directories that are created when a backup is restored.
|
1998 |
-
function delete_old_dirs() {
|
1999 |
-
global $wp_filesystem;
|
2000 |
-
$credentials = request_filesystem_credentials(wp_nonce_url("options-general.php?page=updraftplus&action=updraft_delete_old_dirs", 'updraft_delete_old_dirs'));
|
2001 |
-
WP_Filesystem($credentials);
|
2002 |
-
if ( $wp_filesystem->errors->get_error_code() ) {
|
2003 |
-
foreach ( $wp_filesystem->errors->get_error_messages() as $message )
|
2004 |
-
show_message($message);
|
2005 |
-
exit;
|
2006 |
-
}
|
2007 |
-
|
2008 |
-
$list = $wp_filesystem->dirlist(WP_CONTENT_DIR);
|
2009 |
-
|
2010 |
-
$return_code = true;
|
2011 |
-
|
2012 |
-
foreach ($list as $item) {
|
2013 |
-
if (substr($item['name'], -4, 4) == "-old") {
|
2014 |
-
//recursively delete
|
2015 |
-
print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($item['name']).": ";
|
2016 |
-
if(!$wp_filesystem->delete(WP_CONTENT_DIR.'/'.$item['name'], true)) {
|
2017 |
-
$return_code = false;
|
2018 |
-
print "<strong>Failed</strong><br>";
|
2019 |
-
} else {
|
2020 |
-
print "<strong>OK</strong><br>";
|
2021 |
-
}
|
2022 |
-
}
|
2023 |
-
}
|
2024 |
-
|
2025 |
-
return $return_code;
|
2026 |
-
}
|
2027 |
-
|
2028 |
-
//scans the content dir to see if any -old dirs are present
|
2029 |
-
function scan_old_dirs() {
|
2030 |
-
$dirArr = scandir(WP_CONTENT_DIR);
|
2031 |
-
foreach($dirArr as $dir) {
|
2032 |
-
if(strpos($dir,'-old') !== false) return true;
|
2033 |
-
}
|
2034 |
-
return false;
|
2035 |
-
}
|
2036 |
-
|
2037 |
-
|
2038 |
-
function retain_range($input) {
|
2039 |
-
$input = (int)$input;
|
2040 |
-
if($input > 0 && $input < 3650) {
|
2041 |
-
return $input;
|
2042 |
-
} else {
|
2043 |
-
return 1;
|
2044 |
-
}
|
2045 |
-
}
|
2046 |
-
|
2047 |
-
function create_backup_dir() {
|
2048 |
-
global $wp_filesystem;
|
2049 |
-
$credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_create_backup_dir");
|
2050 |
-
WP_Filesystem($credentials);
|
2051 |
-
if ( $wp_filesystem->errors->get_error_code() ) {
|
2052 |
-
foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
|
2053 |
-
exit;
|
2054 |
-
}
|
2055 |
-
|
2056 |
-
$updraft_dir = $this->backups_dir_location();
|
2057 |
-
$default_backup_dir = WP_CONTENT_DIR.'/updraft';
|
2058 |
-
$updraft_dir = ($updraft_dir)?$updraft_dir:$default_backup_dir;
|
2059 |
-
|
2060 |
-
//chmod the backup dir to 0777. ideally we'd rather chgrp it but i'm not sure if it's possible to detect the group apache is running under (or what if it's not apache...)
|
2061 |
-
if(!$wp_filesystem->mkdir($updraft_dir, 0777)) return false;
|
2062 |
-
|
2063 |
-
return true;
|
2064 |
}
|
2065 |
|
2066 |
function memory_check_current() {
|
@@ -2082,47 +1759,11 @@ class UpdraftPlus {
|
|
2082 |
return $memory_limit;
|
2083 |
}
|
2084 |
|
2085 |
-
function disk_space_check($space) {
|
2086 |
-
$updraft_dir = $this->backups_dir_location();
|
2087 |
-
$disk_free_space = @disk_free_space($updraft_dir);
|
2088 |
-
if ($disk_free_space == false) return -1;
|
2089 |
-
return ($disk_free_space > $space) ? true : false;
|
2090 |
-
}
|
2091 |
-
|
2092 |
function memory_check($memory) {
|
2093 |
$memory_limit = $this->memory_check_current();
|
2094 |
return ($memory_limit >= $memory)?true:false;
|
2095 |
}
|
2096 |
|
2097 |
-
function execution_time_check($time) {
|
2098 |
-
$setting = ini_get('max_execution_time');
|
2099 |
-
return ( $setting==0 || $setting >= $time) ? true : false;
|
2100 |
-
}
|
2101 |
-
|
2102 |
-
function admin_init() {
|
2103 |
-
if(UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
|
2104 |
-
@ini_set('display_errors',1);
|
2105 |
-
@error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
|
2106 |
-
@ini_set('track_errors',1);
|
2107 |
-
}
|
2108 |
-
wp_enqueue_script('jquery');
|
2109 |
-
wp_enqueue_script('jquery-ui-dialog');
|
2110 |
-
|
2111 |
-
if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "googledrive" && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid','') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token','') == '') {
|
2112 |
-
add_action('admin_notices', array($this,'show_admin_warning_googledrive') );
|
2113 |
-
}
|
2114 |
-
|
2115 |
-
if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "dropbox" && UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token','') == '') {
|
2116 |
-
add_action('admin_notices', array($this,'show_admin_warning_dropbox') );
|
2117 |
-
}
|
2118 |
-
|
2119 |
-
if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1024*1024*35) === false) add_action('admin_notices', array($this, 'show_admin_warning_diskspace'));
|
2120 |
-
|
2121 |
-
global $wp_version, $pagenow;
|
2122 |
-
if ($pagenow == 'options-general.php' && version_compare($wp_version, '3.2', '<')) add_action('admin_notices', array($this, 'show_admin_warning_wordpressversion'));
|
2123 |
-
|
2124 |
-
}
|
2125 |
-
|
2126 |
function url_start($urls,$url) {
|
2127 |
return ($urls) ? '<a href="http://'.$url.'">' : "";
|
2128 |
}
|
@@ -2142,7 +1783,7 @@ class UpdraftPlus {
|
|
2142 |
if (defined('WPLANG') && strlen(WPLANG)>0 && !is_file(UPDRAFTPLUS_DIR.'/languages/updraftplus-'.WPLANG.
|
2143 |
'.mo')) return __('Can you translate? Want to improve UpdraftPlus for speakers of your language?','updraftplus').$this->url_start($urls,'updraftplus.com/translate/')."Please go here for instructions - it is easy.".$this->url_end($urls,'updraftplus.com/translate/');
|
2144 |
|
2145 |
-
return __('Find UpdraftPlus useful?','updraftplus').$this->url_start($urls,'david.dw-perspective.org.uk/donate').__("Please make a donation", 'updraftplus').$this->url_end($urls,'david.dw-perspective.org.uk/donate');
|
2146 |
case 2:
|
2147 |
return $this->url_start($urls,'wordshell.net')."Check out WordShell".$this->url_end($urls,'www.wordshell.net')." - manage WordPress from the command line - huge time-saver";
|
2148 |
break;
|
@@ -2171,1058 +1812,6 @@ class UpdraftPlus {
|
|
2171 |
}
|
2172 |
}
|
2173 |
|
2174 |
-
function settings_formcontents($last_backup_html) {
|
2175 |
-
$updraft_dir = $this->backups_dir_location();
|
2176 |
-
|
2177 |
-
?>
|
2178 |
-
<table class="form-table" style="width:900px;">
|
2179 |
-
<tr>
|
2180 |
-
<th><?php _e('File backup intervals','updraftplus'); ?>:</th>
|
2181 |
-
<td><select name="updraft_interval">
|
2182 |
-
<?php
|
2183 |
-
$intervals = array ("manual" => _x("Manual",'i.e. Non-automatic','updraftplus'), 'every4hours' => __("Every 4 hours",'updraftplus'), 'every8hours' => __("Every 8 hours",'updraftplus'), 'twicedaily' => __("Every 12 hours",'updraftplus'), 'daily' => __("Daily",'updraftplus'), 'weekly' => __("Weekly",'updraftplus'), 'fortnightly' => __("Fortnightly",'updraftplus'), 'monthly' => __("Monthly",'updraftplus'));
|
2184 |
-
foreach ($intervals as $cronsched => $descrip) {
|
2185 |
-
echo "<option value=\"$cronsched\" ";
|
2186 |
-
if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval','manual')) echo 'selected="selected"';
|
2187 |
-
echo ">$descrip</option>\n";
|
2188 |
-
}
|
2189 |
-
?>
|
2190 |
-
</select> <?php echo apply_filters('updraftplus_schedule_showfileconfig', '<input type="hidden" name="updraftplus_starttime_files" value="">'); ?>
|
2191 |
-
<?php
|
2192 |
-
echo __('and retain this many backups', 'updraftplus').': ';
|
2193 |
-
$updraft_retain = UpdraftPlus_Options::get_updraft_option('updraft_retain', 1);
|
2194 |
-
$updraft_retain = ((int)$updraft_retain > 0) ? (int)$updraft_retain : 1;
|
2195 |
-
?> <input type="text" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
|
2196 |
-
</td>
|
2197 |
-
</tr>
|
2198 |
-
<tr>
|
2199 |
-
<th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
|
2200 |
-
<td><select name="updraft_interval_database">
|
2201 |
-
<?php
|
2202 |
-
foreach ($intervals as $cronsched => $descrip) {
|
2203 |
-
echo "<option value=\"$cronsched\" ";
|
2204 |
-
if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'))) echo 'selected="selected"';
|
2205 |
-
echo ">$descrip</option>\n";
|
2206 |
-
}
|
2207 |
-
?>
|
2208 |
-
</select> <?php echo apply_filters('updraftplus_schedule_showdbconfig', '<input type="hidden" name="updraftplus_starttime_db" value="">'); ?>
|
2209 |
-
<?php
|
2210 |
-
echo __('and retain this many backups', 'updraftplus').': ';
|
2211 |
-
$updraft_retain_db = UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
|
2212 |
-
$updraft_retain_db = ((int)$updraft_retain_db > 0) ? (int)$updraft_retain_db : 1;
|
2213 |
-
?> <input type="text" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
|
2214 |
-
</td>
|
2215 |
-
</tr>
|
2216 |
-
<tr class="backup-interval-description">
|
2217 |
-
<td></td><td><p><?php echo htmlspecialchars(__('If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
|
2218 |
-
<?php echo apply_filters('updraftplus_fixtime_advert', '<p><strong>'.__('To fix the time at which a backup should take place,','updraftplus').' </strong> ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), <a href="http://updraftplus.com/shop/fix-time/">'.htmlspecialchars(__('use the "Fix Time" add-on','updraftplus')).'</a></p>'); ?>
|
2219 |
-
</td>
|
2220 |
-
</tr>
|
2221 |
-
<tr>
|
2222 |
-
<th>Include in files backup:</th>
|
2223 |
-
<td>
|
2224 |
-
|
2225 |
-
<?php
|
2226 |
-
$backupable_entities = $this->get_backupable_file_entities(true, true);
|
2227 |
-
$include_others_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude',UPDRAFT_DEFAULT_OTHERS_EXCLUDE);
|
2228 |
-
# The true (default value if non-existent) here has the effect of forcing a default of on.
|
2229 |
-
foreach ($backupable_entities as $key => $info) {
|
2230 |
-
$included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key",true)) ? 'checked="checked"' : "";
|
2231 |
-
if ('others' == $key) {
|
2232 |
-
?><input id="updraft_include_others" type="checkbox" name="updraft_include_others" value="1" <?php echo $included; ?> /> <label for="updraft_include_<?php echo $key ?>"><?php echo __('Any other directories found inside wp-content but exclude these directories:', 'updraftplus');?></label> <input type="text" name="updraft_include_others_exclude" size="44" value="<?php echo htmlspecialchars($include_others_exclude); ?>"/><br><?php
|
2233 |
-
} else {
|
2234 |
-
echo "<input id=\"updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"updraft_include_$key\">".$info['description']."</label><br>";
|
2235 |
-
}
|
2236 |
-
}
|
2237 |
-
?>
|
2238 |
-
<p><?php echo __('Include all of these, unless you are backing them up outside of UpdraftPlus. The above directories are usually everything (except for WordPress core itself which you can download afresh from WordPress.org). But if you have made customised modifications outside of these directories, you need to back them up another way.', 'updraftplus') ?> (<a href="http://wordshell.net"><?php echo __('Use WordShell for automatic backup, version control and patching', 'updraftplus');?></a>).</p></td>
|
2239 |
-
</td>
|
2240 |
-
</tr>
|
2241 |
-
<tr>
|
2242 |
-
<th><?php _e('Email','updraftplus'); ?>:</th>
|
2243 |
-
<td><input type="text" style="width:260px" name="updraft_email" value="<?php echo UpdraftPlus_Options::get_updraft_option('updraft_email'); ?>" /> <br><?php _e('Enter an address here to have a report sent (and the whole backup, if you choose) to it.','updraftplus'); ?></td>
|
2244 |
-
</tr>
|
2245 |
-
|
2246 |
-
<tr>
|
2247 |
-
<th><?php _e('Database encryption phrase','updraftplus');?>:</th>
|
2248 |
-
<?php
|
2249 |
-
$updraft_encryptionphrase = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
|
2250 |
-
?>
|
2251 |
-
<td><input type="text" name="updraft_encryptionphrase" value="<?php echo $updraft_encryptionphrase ?>" style="width:132px" /></td>
|
2252 |
-
</tr>
|
2253 |
-
<tr class="backup-crypt-description">
|
2254 |
-
<td></td><td><?php _e('If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back). You can also use the file example-decrypt.php from inside the UpdraftPlus plugin directory to decrypt manually.','updraftplus');?></td>
|
2255 |
-
</tr>
|
2256 |
-
</table>
|
2257 |
-
|
2258 |
-
<h2><?php _e('Copying Your Backup To Remote Storage','updraftplus');?></h2>
|
2259 |
-
|
2260 |
-
<table class="form-table" style="width:900px;">
|
2261 |
-
<tr>
|
2262 |
-
<th><?php _e('Choose your remote storage','updraftplus');?>:</th>
|
2263 |
-
<td><select name="updraft_service" id="updraft-service">
|
2264 |
-
<?php
|
2265 |
-
$debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
|
2266 |
-
|
2267 |
-
$set = 'selected="selected"';
|
2268 |
-
|
2269 |
-
// Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
|
2270 |
-
$active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
|
2271 |
-
|
2272 |
-
?>
|
2273 |
-
<option value="none" <?php
|
2274 |
-
if ($active_service == "none") echo $set; ?>>None</option>
|
2275 |
-
<?php
|
2276 |
-
foreach ($this->backup_methods as $method => $description) {
|
2277 |
-
echo "<option value=\"$method\"";
|
2278 |
-
if ($active_service == $method) echo ' '.$set;
|
2279 |
-
echo '>'.$description;
|
2280 |
-
echo "</option>\n";
|
2281 |
-
}
|
2282 |
-
?>
|
2283 |
-
</select></td>
|
2284 |
-
</tr>
|
2285 |
-
<?php
|
2286 |
-
foreach ($this->backup_methods as $method => $description) {
|
2287 |
-
require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
2288 |
-
$call_method = "UpdraftPlus_BackupModule_$method";
|
2289 |
-
call_user_func(array($call_method, 'config_print'));
|
2290 |
-
}
|
2291 |
-
?>
|
2292 |
-
</table>
|
2293 |
-
<script type="text/javascript">
|
2294 |
-
/* <![CDATA[ */
|
2295 |
-
var lastlog_lastmessage = "";
|
2296 |
-
var lastlog_sdata = {
|
2297 |
-
action: 'updraft_ajax',
|
2298 |
-
subaction: 'lastlog',
|
2299 |
-
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
|
2300 |
-
};
|
2301 |
-
function updraft_showlastlog(){
|
2302 |
-
jQuery.get(ajaxurl, lastlog_sdata, function(response) {
|
2303 |
-
nexttimer = 1500;
|
2304 |
-
if (lastlog_lastmessage == response) { nexttimer = 4500; }
|
2305 |
-
setTimeout(function(){updraft_showlastlog()}, nexttimer);
|
2306 |
-
jQuery('#updraft_lastlogcontainer').html(response);
|
2307 |
-
lastlog_lastmessage = response;
|
2308 |
-
});
|
2309 |
-
}
|
2310 |
-
var lastbackup_sdata = {
|
2311 |
-
action: 'updraft_ajax',
|
2312 |
-
subaction: 'lastbackup',
|
2313 |
-
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
|
2314 |
-
};
|
2315 |
-
var lastbackup_laststatus = '<?php echo $last_backup_html?>'
|
2316 |
-
function updraft_showlastbackup(){
|
2317 |
-
jQuery.get(ajaxurl, lastbackup_sdata, function(response) {
|
2318 |
-
if (lastbackup_laststatus == response) {
|
2319 |
-
setTimeout(function(){updraft_showlastbackup()}, 7000);
|
2320 |
-
} else {
|
2321 |
-
jQuery('#updraft_last_backup').html(response);
|
2322 |
-
}
|
2323 |
-
lastbackup_laststatus = response;
|
2324 |
-
});
|
2325 |
-
}
|
2326 |
-
var updraft_historytimer = 0;
|
2327 |
-
var calculated_diskspace = 0;
|
2328 |
-
function updraft_historytimertoggle(forceon) {
|
2329 |
-
if (!updraft_historytimer || forceon == 1) {
|
2330 |
-
updraft_updatehistory(0);
|
2331 |
-
updraft_historytimer = setInterval(function(){updraft_updatehistory(0)}, 30000);
|
2332 |
-
if (!calculated_diskspace) {
|
2333 |
-
updraftplus_diskspace();
|
2334 |
-
calculated_diskspace=1;
|
2335 |
-
}
|
2336 |
-
} else {
|
2337 |
-
clearTimeout(updraft_historytimer);
|
2338 |
-
updraft_historytimer = 0;
|
2339 |
-
}
|
2340 |
-
}
|
2341 |
-
function updraft_updatehistory(rescan) {
|
2342 |
-
if (rescan == 1) {
|
2343 |
-
jQuery('#updraft_existing_backups').html('<p style="text-align:center;"><em>Rescanning (looking for backups that you have uploaded manually into the internal backup store)...</em></p>');
|
2344 |
-
}
|
2345 |
-
jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'historystatus', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>', rescan: rescan }, function(response) {
|
2346 |
-
jQuery('#updraft_existing_backups').html(response);
|
2347 |
-
});
|
2348 |
-
}
|
2349 |
-
|
2350 |
-
jQuery(document).ready(function() {
|
2351 |
-
jQuery( "#updraft-restore-modal" ).dialog({
|
2352 |
-
autoOpen: false, height: 385, width: 480, modal: true,
|
2353 |
-
buttons: {
|
2354 |
-
Restore: function() {
|
2355 |
-
var anyselected = 0;
|
2356 |
-
jQuery('input[name="updraft_restore[]"]').each(function(x,y){
|
2357 |
-
if (jQuery(y).is(':checked')) {
|
2358 |
-
anyselected = 1;
|
2359 |
-
//alert(jQuery(y).val());
|
2360 |
-
}
|
2361 |
-
});
|
2362 |
-
if (anyselected == 1) {
|
2363 |
-
jQuery('#updraft_restore_form').submit();
|
2364 |
-
} else {
|
2365 |
-
alert('You did not select any components to restore. Please select at least one, and then try again.');
|
2366 |
-
}
|
2367 |
-
},
|
2368 |
-
<?php _e('Cancel','updraftplus');?>: function() { jQuery(this).dialog("close"); }
|
2369 |
-
}
|
2370 |
-
});
|
2371 |
-
|
2372 |
-
jQuery( "#updraft-backupnow-modal" ).dialog({
|
2373 |
-
autoOpen: false, height: 265, width: 375, modal: true,
|
2374 |
-
buttons: {
|
2375 |
-
'<?php _e('Backup Now','updraftplus');?>': function() {
|
2376 |
-
jQuery('#updraft-backupnow-form').submit();
|
2377 |
-
},
|
2378 |
-
<?php _e('Cancel','updraftplus');?>: function() { jQuery(this).dialog("close"); }
|
2379 |
-
}
|
2380 |
-
});
|
2381 |
-
|
2382 |
-
jQuery('#enableexpertmode').click(function() {
|
2383 |
-
jQuery('.expertmode').fadeIn();
|
2384 |
-
return false;
|
2385 |
-
});
|
2386 |
-
<?php if (!@is_writable($updraft_dir)) echo "jQuery('.backupdirrow').show();\n"; ?>
|
2387 |
-
setTimeout(function(){updraft_showlastlog();}, 1200);
|
2388 |
-
jQuery('.updraftplusmethod').hide();
|
2389 |
-
<?php
|
2390 |
-
if ($active_service) echo "jQuery('.${active_service}').show();";
|
2391 |
-
foreach ($this->backup_methods as $method => $description) {
|
2392 |
-
// already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
2393 |
-
$call_method = "UpdraftPlus_BackupModule_$method";
|
2394 |
-
if (method_exists($call_method, 'config_print_javascript_onready')) call_user_func(array($call_method, 'config_print_javascript_onready'));
|
2395 |
-
}
|
2396 |
-
?>
|
2397 |
-
});
|
2398 |
-
/* ]]> */
|
2399 |
-
</script>
|
2400 |
-
<table class="form-table" style="width:900px;">
|
2401 |
-
<tr>
|
2402 |
-
<td colspan="2"><h2><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
|
2403 |
-
</tr>
|
2404 |
-
<tr>
|
2405 |
-
<th><?php _e('Debug mode','updraftplus');?>:</th>
|
2406 |
-
<td><input type="checkbox" id="updraft_debug_mode" name="updraft_debug_mode" value="1" <?php echo $debug_mode; ?> /> <br><label for="updraft_debug_mode"><?php _e('Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report.','updraftplus');?></label></td>
|
2407 |
-
</tr>
|
2408 |
-
<tr>
|
2409 |
-
<th><?php _e('Expert settings','updraftplus');?>:</th>
|
2410 |
-
<td><a id="enableexpertmode" href="#"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?></td>
|
2411 |
-
</tr>
|
2412 |
-
<?php
|
2413 |
-
$delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
|
2414 |
-
?>
|
2415 |
-
|
2416 |
-
<tr class="deletelocal expertmode" style="display:none;">
|
2417 |
-
<th><?php _e('Delete local backup','updraftplus');?>:</th>
|
2418 |
-
<td><input type="checkbox" id="updraft_delete_local" name="updraft_delete_local" value="1" <?php if ($delete_local) echo 'checked="checked"'; ?>> <br><label for="updraft_delete_local"><?php _e('Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits).','updraftplus');?></label></td>
|
2419 |
-
</tr>
|
2420 |
-
|
2421 |
-
<tr class="expertmode backupdirrow" style="display:none;">
|
2422 |
-
<th>Backup directory:</th>
|
2423 |
-
<td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
|
2424 |
-
</tr>
|
2425 |
-
<tr class="expertmode backupdirrow" style="display:none;">
|
2426 |
-
<td></td><td><?php
|
2427 |
-
|
2428 |
-
// Suppress warnings, since if the user is dumping warnings to screen, then invalid JavaScript results and the screen breaks.
|
2429 |
-
if(@is_writable($updraft_dir)) {
|
2430 |
-
$dir_info = '<span style="color:green">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
|
2431 |
-
} else {
|
2432 |
-
$dir_info = '<span style="color:red">'.__('Backup directory specified is <b>not</b> writable, or does not exist.','updraftplus').' <span style="font-size:110%;font-weight:bold"><a href="options-general.php?page=updraftplus&action=updraft_create_backup_dir">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" onclick="jQuery(\'#updraft_dir\').val(\''.WP_CONTENT_DIR.'/updraft\'); return false;">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
|
2433 |
-
}
|
2434 |
-
|
2435 |
-
echo $dir_info.' '.__("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...).",'updraftplus');?></td>
|
2436 |
-
</tr>
|
2437 |
-
<tr>
|
2438 |
-
<td></td>
|
2439 |
-
<td>
|
2440 |
-
<?php
|
2441 |
-
$ws_ad = $this->wordshell_random_advert(1);
|
2442 |
-
if ($ws_ad) {
|
2443 |
-
?>
|
2444 |
-
<p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
|
2445 |
-
<?php echo $ws_ad; ?>
|
2446 |
-
</p>
|
2447 |
-
<?php
|
2448 |
-
}
|
2449 |
-
?>
|
2450 |
-
</td>
|
2451 |
-
</tr>
|
2452 |
-
<tr>
|
2453 |
-
<td></td>
|
2454 |
-
<td>
|
2455 |
-
<input type="hidden" name="action" value="update" />
|
2456 |
-
<input type="submit" class="button-primary" value="<?php _e('Save Changes','updraftplus');?>" />
|
2457 |
-
</td>
|
2458 |
-
</tr>
|
2459 |
-
</table>
|
2460 |
-
<?php
|
2461 |
-
}
|
2462 |
-
|
2463 |
-
function last_backup_html() {
|
2464 |
-
|
2465 |
-
$updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
|
2466 |
-
|
2467 |
-
$updraft_dir = $this->backups_dir_location();
|
2468 |
-
|
2469 |
-
if($updraft_last_backup) {
|
2470 |
-
|
2471 |
-
if ($updraft_last_backup['success']) {
|
2472 |
-
// Convert to GMT, then to blog time
|
2473 |
-
$last_backup_text = get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time']), 'D, F j, Y H:i T');
|
2474 |
-
} else {
|
2475 |
-
$last_backup_text = implode("<br>",$updraft_last_backup['errors']);
|
2476 |
-
}
|
2477 |
-
|
2478 |
-
if (!empty($updraft_last_backup['backup_nonce'])) {
|
2479 |
-
$potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
|
2480 |
-
if (is_readable($potential_log_file)) $last_backup_text .= "<br><a href=\"?page=updraftplus&action=downloadlog&updraftplus_backup_nonce=".$updraft_last_backup['backup_nonce']."\">".__('Download log file','updraftplus')."</a>";
|
2481 |
-
}
|
2482 |
-
|
2483 |
-
$last_backup_color = ($updraft_last_backup['success']) ? 'green' : 'red';
|
2484 |
-
|
2485 |
-
} else {
|
2486 |
-
$last_backup_text = __('No backup has been completed.','updraftplus');
|
2487 |
-
$last_backup_color = 'blue';
|
2488 |
-
}
|
2489 |
-
|
2490 |
-
return "<span style=\"color:${last_backup_color}\">${last_backup_text}</span>";
|
2491 |
-
|
2492 |
-
}
|
2493 |
-
|
2494 |
-
function settings_output() {
|
2495 |
-
|
2496 |
-
wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui-1.8.22.custom.css');
|
2497 |
-
|
2498 |
-
/*
|
2499 |
-
we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
|
2500 |
-
for the WP_Filesystem. to do this WP outputs a form that we can't insert variables into (apparently). So the values are
|
2501 |
-
passed back in as GET parameters. REQUEST covers both GET and POST so this weird logic works.
|
2502 |
-
*/
|
2503 |
-
if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) {
|
2504 |
-
$backup_success = $this->restore_backup($_REQUEST['backup_timestamp']);
|
2505 |
-
if(empty($this->errors) && $backup_success == true) {
|
2506 |
-
echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
|
2507 |
-
echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
2508 |
-
return;
|
2509 |
-
} else {
|
2510 |
-
echo '<p>Restore failed...</p><ul style="list-style: disc inside;">';
|
2511 |
-
foreach ($this->errors as $err) {
|
2512 |
-
if (is_wp_error($err)) {
|
2513 |
-
foreach ($err->get_error_messages() as $msg) {
|
2514 |
-
echo '<li>'.htmlspecialchars($msg).'<li>';
|
2515 |
-
}
|
2516 |
-
} elseif (is_string($err)) {
|
2517 |
-
echo "<li>".htmlspecialchars($err)."</li>";
|
2518 |
-
} else {
|
2519 |
-
print "<li>".print_r($err,true)."</li>";
|
2520 |
-
}
|
2521 |
-
}
|
2522 |
-
echo '</ul><b>Actions:</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
2523 |
-
return;
|
2524 |
-
}
|
2525 |
-
//uncomment the below once i figure out how i want the flow of a restoration to work.
|
2526 |
-
//echo '<b>'__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">Return to UpdraftPlus Configuration</a>';
|
2527 |
-
}
|
2528 |
-
$deleted_old_dirs = false;
|
2529 |
-
if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_delete_old_dirs') {
|
2530 |
-
|
2531 |
-
echo '<h1>UpdraftPlus - '.__('Remove old directories','updraftplus').'</h1>';
|
2532 |
-
|
2533 |
-
$nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
|
2534 |
-
if (!wp_verify_nonce($nonce, 'updraft_delete_old_dirs')) die('Security check');
|
2535 |
-
|
2536 |
-
if($this->delete_old_dirs()) {
|
2537 |
-
echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
|
2538 |
-
$deleted_old_dirs = true;
|
2539 |
-
} else {
|
2540 |
-
echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
|
2541 |
-
}
|
2542 |
-
echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
2543 |
-
return;
|
2544 |
-
}
|
2545 |
-
|
2546 |
-
if(isset($_GET['error'])) {
|
2547 |
-
$this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
|
2548 |
-
}
|
2549 |
-
if(isset($_GET['message'])) {
|
2550 |
-
$this->show_admin_warning(htmlspecialchars($_GET['message']));
|
2551 |
-
}
|
2552 |
-
|
2553 |
-
if(isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir') {
|
2554 |
-
if(!$this->create_backup_dir()) {
|
2555 |
-
echo '<p>'.__('Backup directory could not be created','updraftplus').'...</p><br/>';
|
2556 |
-
}
|
2557 |
-
echo '<p>'.__('Backup directory successfully created.','updraftplus').'</p><br/>';
|
2558 |
-
echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
|
2559 |
-
return;
|
2560 |
-
}
|
2561 |
-
|
2562 |
-
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup') {
|
2563 |
-
// For unknown reasons, the <script> runs twice if put inside the <div>
|
2564 |
-
echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"><strong>',__('Schedule backup','updraftplus').':</strong> ';
|
2565 |
-
if (wp_schedule_single_event(time()+5, 'updraft_backup_all') === false) {
|
2566 |
-
$this->log("A backup run failed to schedule");
|
2567 |
-
echo __("Failed.",'updraftplus')."</div>";
|
2568 |
-
} else {
|
2569 |
-
echo htmlspecialchars(__('OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the "Last log message" field below.','updraftplus'))." <a href=\"http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/\">".__('Nothing happening? Follow this link for help.','updraftplus')."</a></div><script>setTimeout(function(){updraft_showlastbackup();}, 7000);</script>";
|
2570 |
-
$this->log("A backup run has been scheduled");
|
2571 |
-
}
|
2572 |
-
}
|
2573 |
-
|
2574 |
-
// updraft_file_ids is not deleted
|
2575 |
-
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $this->boot_backup(true,true); }
|
2576 |
-
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') { $this->backup_db(); }
|
2577 |
-
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
|
2578 |
-
$settings = array('updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_clientid', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder', 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_sftp_settings');
|
2579 |
-
foreach ($settings as $s) {
|
2580 |
-
UpdraftPlus_Options::delete_updraft_option($s);
|
2581 |
-
}
|
2582 |
-
$this->show_admin_warning(__("Your settings have been wiped.",'updraftplus'));
|
2583 |
-
}
|
2584 |
-
|
2585 |
-
?>
|
2586 |
-
<div class="wrap">
|
2587 |
-
<h1><?php echo $this->plugin_title; ?></h1>
|
2588 |
-
|
2589 |
-
<?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('Other WordPress plugins','updraftplus');?></a>). <?php _e('Version','updraftplus');?>: <?php echo $this->version; ?>
|
2590 |
-
<br>
|
2591 |
-
<?php
|
2592 |
-
if(isset($_GET['updraft_restore_success'])) {
|
2593 |
-
echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('Your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.').' '.__('At this time UpdraftPlus does not automatically restore your database. You will need to use an external tool like phpMyAdmin to perform that task.','updraftplus')."</div>";
|
2594 |
-
}
|
2595 |
-
|
2596 |
-
$ws_advert = $this->wordshell_random_advert(1);
|
2597 |
-
if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
|
2598 |
-
|
2599 |
-
if($deleted_old_dirs) echo '<div style="color:blue" class=\"updated fade\">'.__('Old directories successfully deleted.','updraftplus').'</div>';
|
2600 |
-
|
2601 |
-
if(!$this->memory_check(96)) {?>
|
2602 |
-
<div style="color:orange"><?php _e("Your PHP memory limit is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb (though on the other hand, it has been used successfully with a 32Mb limit - your mileage may vary, but don't blame us!).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $this->memory_check_current(); ?> Mb</div>
|
2603 |
-
<?php
|
2604 |
-
}
|
2605 |
-
if(1==0 && !$this->execution_time_check(60)) {?>
|
2606 |
-
<div style="color:orange"><?php _e("Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:",'updraftplus');?> <?php echo ini_get('max_execution_time').' '.__('seconds','updraftplus')?>.</div>
|
2607 |
-
<?php
|
2608 |
-
}
|
2609 |
-
|
2610 |
-
if($this->scan_old_dirs()) {?>
|
2611 |
-
<div class="updated fade" style="padding:8px;"><?php _e('You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked).','updraftplus');?>
|
2612 |
-
<form method="post" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
|
2613 |
-
<?php wp_nonce_field('updraft_delete_old_dirs'); ?>
|
2614 |
-
<input type="hidden" name="action" value="updraft_delete_old_dirs" />
|
2615 |
-
<input type="submit" class="button-primary" value="<?php _e('Delete Old Directories','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('Are you sure you want to delete the old directories? This cannot be undone.','updraftplus'));?>'))" />
|
2616 |
-
</form>
|
2617 |
-
</div>
|
2618 |
-
<?php
|
2619 |
-
}
|
2620 |
-
if(!empty($this->errors)) {
|
2621 |
-
foreach($this->errors as $error) {
|
2622 |
-
// ignoring severity
|
2623 |
-
echo '<div style="color:red">'.$error['error'].'</div>';
|
2624 |
-
}
|
2625 |
-
}
|
2626 |
-
?>
|
2627 |
-
|
2628 |
-
<h2 style="clear:left;"><?php _e('Existing Schedule And Backups','updraftplus');?></h2>
|
2629 |
-
<table class="form-table" style="float:left; clear: both; width:545px;">
|
2630 |
-
<noscript>
|
2631 |
-
<tr>
|
2632 |
-
<th><?php _e('JavaScript warning','updraftplus');?>:</th>
|
2633 |
-
<td style="color:red"><?php _e('This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser.','updraftplus');?></td>
|
2634 |
-
</tr>
|
2635 |
-
</noscript>
|
2636 |
-
<?php
|
2637 |
-
$updraft_dir = $this->backups_dir_location();
|
2638 |
-
// UNIX timestamp
|
2639 |
-
$next_scheduled_backup = wp_next_scheduled('updraft_backup');
|
2640 |
-
if ($next_scheduled_backup) {
|
2641 |
-
// Convert to GMT
|
2642 |
-
$next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
|
2643 |
-
// Convert to blog time zone
|
2644 |
-
$next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i T');
|
2645 |
-
} else {
|
2646 |
-
$next_scheduled_backup = __('Nothing currently scheduled','updraftplus');
|
2647 |
-
}
|
2648 |
-
|
2649 |
-
$next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
|
2650 |
-
if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
|
2651 |
-
$next_scheduled_backup_database = ('Nothing currently scheduled' == $next_scheduled_backup) ? $next_scheduled_backup : __("At the same time as the files backup", 'updraftplus');
|
2652 |
-
} else {
|
2653 |
-
if ($next_scheduled_backup_database) {
|
2654 |
-
// Convert to GMT
|
2655 |
-
$next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
|
2656 |
-
// Convert to blog time zone
|
2657 |
-
$next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i T');
|
2658 |
-
} else {
|
2659 |
-
$next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
|
2660 |
-
}
|
2661 |
-
}
|
2662 |
-
$current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i T');
|
2663 |
-
|
2664 |
-
$backup_disabled = (is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
|
2665 |
-
|
2666 |
-
$last_backup_html = $this->last_backup_html();
|
2667 |
-
|
2668 |
-
?>
|
2669 |
-
|
2670 |
-
<tr>
|
2671 |
-
<th><?php _e('Next scheduled backups','updraftplus');?>:</th>
|
2672 |
-
<td>
|
2673 |
-
<div style="width: 76px; float:left;">Files:</div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup?></div>
|
2674 |
-
<div style="width: 76px; clear: left; float:left;"><?php _e('Database','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup_database?></div>
|
2675 |
-
<div style="width: 76px; clear: left; float:left;"><?php _e('Time now','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $current_time?></div>
|
2676 |
-
</td>
|
2677 |
-
</tr>
|
2678 |
-
<tr>
|
2679 |
-
<th><?php _e('Last finished backup run','updraftplus');?>:</th>
|
2680 |
-
<td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
|
2681 |
-
</tr>
|
2682 |
-
</table>
|
2683 |
-
<div style="float:left; width:200px; padding-top: 20px;">
|
2684 |
-
<p><button type="button" <?php echo $backup_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now','updraftplus');?></button></p>
|
2685 |
-
<div style="position:relative">
|
2686 |
-
<div style="position:absolute;top:0;left:0">
|
2687 |
-
<?php
|
2688 |
-
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
2689 |
-
$backup_history = (is_array($backup_history))?$backup_history:array();
|
2690 |
-
$backup_history_sets = (count($backup_history) == 1) ? 'set' : 'sets';
|
2691 |
-
$restore_disabled = (count($backup_history) == 0) ? 'disabled="disabled"' : "";
|
2692 |
-
?>
|
2693 |
-
<input type="button" class="button-primary" <?php echo $restore_disabled ?> value="<?php _e('Restore','updraftplus');?>" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('.download-backups').slideDown(); updraft_historytimertoggle(1); jQuery('html,body').animate({scrollTop: jQuery('#updraft_lastlogcontainer').offset().top},'slow');">
|
2694 |
-
</div>
|
2695 |
-
</div>
|
2696 |
-
</div>
|
2697 |
-
<br style="clear:both" />
|
2698 |
-
<table class="form-table">
|
2699 |
-
<tr>
|
2700 |
-
<th>Last log message:</th>
|
2701 |
-
<td id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '(Nothing yet logged)')); ?></td>
|
2702 |
-
</tr>
|
2703 |
-
<tr>
|
2704 |
-
<th>Backups, logs & restoring:</th>
|
2705 |
-
<td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="jQuery('.download-backups').toggle(); updraft_historytimertoggle(0);"><?php echo count($backup_history).' '.$backup_history_sets; ?> available</a></td>
|
2706 |
-
</tr>
|
2707 |
-
<tr>
|
2708 |
-
<td></td><td class="download-backups" style="display:none; border: 1px dotted;">
|
2709 |
-
<p style="max-width: 740px;"><ul style="list-style: disc inside;">
|
2710 |
-
<li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
|
2711 |
-
<li><strong><?php _e('Restoring','updraftplus');?>:</strong> <?php _e("Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself.",'updraftplus');?></li>
|
2712 |
-
<li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
|
2713 |
-
<li title="<?php _e('This is a count of the contents of your Updraft directory','updraftplus');?>"><strong><?php _e('Web-server disk space in use by UpdraftPlus','updraftplus');?>:</strong> <span id="updraft_diskspaceused"><em>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li></ul>
|
2714 |
-
<div id="ud_downloadstatus"></div>
|
2715 |
-
<script>
|
2716 |
-
function updraftplus_diskspace() {
|
2717 |
-
jQuery('#updraft_diskspaceused').html('<em><?php _e('calculating...','updraftplus');?></em>');
|
2718 |
-
jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'diskspaceused', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>' }, function(response) {
|
2719 |
-
jQuery('#updraft_diskspaceused').html(response);
|
2720 |
-
});
|
2721 |
-
}
|
2722 |
-
var lastlog_lastmessage = "";
|
2723 |
-
function updraftplus_deletefromserver(timestamp, type) {
|
2724 |
-
var pdata = {
|
2725 |
-
action: 'updraft_download_backup',
|
2726 |
-
stage: 'delete',
|
2727 |
-
timestamp: timestamp,
|
2728 |
-
type: type,
|
2729 |
-
_wpnonce: '<?php echo wp_create_nonce("updraftplus_download"); ?>'
|
2730 |
-
};
|
2731 |
-
jQuery.post(ajaxurl, pdata, function(response) {
|
2732 |
-
if (response == 'deleted') {
|
2733 |
-
|
2734 |
-
} else {
|
2735 |
-
alert('We requested to delete the file, but could not understand the server\'s response '+response);
|
2736 |
-
}
|
2737 |
-
});
|
2738 |
-
}
|
2739 |
-
function updraftplus_downloadstage2(timestamp, type) {
|
2740 |
-
location.href=ajaxurl+'?_wpnonce=<?php echo wp_create_nonce("updraftplus_download"); ?>×tamp='+timestamp+'&type='+type+'&stage=2&action=updraft_download_backup';
|
2741 |
-
}
|
2742 |
-
function updraft_downloader(nonce, what) {
|
2743 |
-
// Create somewhere for the status to be found
|
2744 |
-
var stid = 'uddlstatus_'+nonce+'_'+what;
|
2745 |
-
if (!jQuery('#'+stid).length) {
|
2746 |
-
jQuery('#ud_downloadstatus').append('<div style="clear:left; border: 1px dashed; padding: 8px; margin-top: 4px; max-width:840px;" id="'+stid+'"><button onclick="jQuery(\'#'+stid+'\').fadeOut().remove();" type="button" style="float:right;">X</button><strong>Download '+what+' ('+nonce+')</strong>: <span id="'+stid+'_st">Begun looking for this entity</span></div>');
|
2747 |
-
setTimeout(function(){updraft_downloader_status(nonce, what)}, 200);
|
2748 |
-
}
|
2749 |
-
// Reset, in case this is a re-try
|
2750 |
-
jQuery('#'+stid+'_st').html('Begun looking for this entity');
|
2751 |
-
// Now send the actual request to kick it all off
|
2752 |
-
jQuery.post(ajaxurl, jQuery('#uddownloadform_'+what+'_'+nonce).serialize());
|
2753 |
-
// We don't want the form to submit as that replaces the document
|
2754 |
-
return false;
|
2755 |
-
}
|
2756 |
-
var dlstatus_sdata = {
|
2757 |
-
action: 'updraft_ajax',
|
2758 |
-
subaction: 'downloadstatus',
|
2759 |
-
nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
|
2760 |
-
};
|
2761 |
-
dlstatus_lastlog = '';
|
2762 |
-
function updraft_downloader_status(nonce, what) {
|
2763 |
-
var stid = 'uddlstatus_'+nonce+'_'+what;
|
2764 |
-
if (jQuery('#'+stid).length) {
|
2765 |
-
dlstatus_sdata.timestamp = nonce;
|
2766 |
-
dlstatus_sdata.type = what;
|
2767 |
-
jQuery.get(ajaxurl, dlstatus_sdata, function(response) {
|
2768 |
-
nexttimer = 1250;
|
2769 |
-
if (dlstatus_lastlog == response) { nexttimer = 3000; }
|
2770 |
-
setTimeout(function(){updraft_downloader_status(nonce, what)}, nexttimer);
|
2771 |
-
jQuery('#'+stid+'_st').html(response);
|
2772 |
-
dlstatus_lastlog = response;
|
2773 |
-
});
|
2774 |
-
}
|
2775 |
-
}
|
2776 |
-
</script>
|
2777 |
-
<div id="updraft_existing_backups" style="margin-bottom:12px;">
|
2778 |
-
<?php
|
2779 |
-
print $this->existing_backup_table($backup_history);
|
2780 |
-
?>
|
2781 |
-
</div>
|
2782 |
-
</td>
|
2783 |
-
</tr>
|
2784 |
-
</table>
|
2785 |
-
<div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
|
2786 |
-
<p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span id="updraft_restore_date"></span></p>
|
2787 |
-
<p><?php _e("Restoring will replace this site's themes, plugins, uploads and/or other content directories (according to what is contained in the backup set, and your selection",'updraftplus');?>). <?php _e('Choose the components to restore','updraftplus');?>:</p>
|
2788 |
-
<form id="updraft_restore_form" method="post">
|
2789 |
-
<fieldset>
|
2790 |
-
<input type="hidden" name="action" value="updraft_restore">
|
2791 |
-
<input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
|
2792 |
-
<?php
|
2793 |
-
$backupable_entities = $this->get_backupable_file_entities(true, true);
|
2794 |
-
foreach ($backupable_entities as $type => $info) {
|
2795 |
-
echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label for="updraft_restore_'.$type.'">'.$info['description'].'</label><br></div>';
|
2796 |
-
}
|
2797 |
-
?>
|
2798 |
-
<p><em><?php _e("Databases cannot yet be restored from here - you must download the database file and take it to your web hosting company's control panel.",'updraftplus');?></em></p>
|
2799 |
-
</fieldset>
|
2800 |
-
</form>
|
2801 |
-
</div>
|
2802 |
-
|
2803 |
-
<div id="updraft-backupnow-modal" title="UpdraftPlus - Perform a backup now">
|
2804 |
-
|
2805 |
-
<p><?php _e("This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background.",'updraftplus');?></p>
|
2806 |
-
|
2807 |
-
<form id="updraft-backupnow-form" method="post" action="">
|
2808 |
-
<input type="hidden" name="action" value="updraft_backup" />
|
2809 |
-
</form>
|
2810 |
-
|
2811 |
-
<p><?php _e('Does nothing happen when you schedule backups?','updraftplus');?> <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for help.','updraft');?></a></p>
|
2812 |
-
|
2813 |
-
</div>
|
2814 |
-
|
2815 |
-
<?php
|
2816 |
-
if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
|
2817 |
-
?>
|
2818 |
-
<h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
|
2819 |
-
<table>
|
2820 |
-
<tr>
|
2821 |
-
<td>
|
2822 |
-
<p style="max-width:800px;"><?php echo __('Do you need WordPress Multisite support?','updraftplus').' <a href="http://updraftplus.com/">'. __('Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on.','updraftplus');?></a>.</p>
|
2823 |
-
</td>
|
2824 |
-
</tr>
|
2825 |
-
</table>
|
2826 |
-
<?php } ?>
|
2827 |
-
<h2><?php _e('Configure Backup Contents And Schedule','updraftplus');?></h2>
|
2828 |
-
<?php UpdraftPlus_Options::options_form_begin(); ?>
|
2829 |
-
<?php $this->settings_formcontents($last_backup_html); ?>
|
2830 |
-
</form>
|
2831 |
-
<div style="padding-top: 40px; display:none;" class="expertmode">
|
2832 |
-
<hr>
|
2833 |
-
<h3><?php _e('Debug Information And Expert Options','updraftplus');?></h3>
|
2834 |
-
<p>
|
2835 |
-
<?php
|
2836 |
-
$peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
|
2837 |
-
$memory_usage = memory_get_usage(true)/1024/1024;
|
2838 |
-
echo 'Peak memory usage: '.$peak_memory_usage.' MB<br/>';
|
2839 |
-
echo 'Current memory usage: '.$memory_usage.' MB<br/>';
|
2840 |
-
echo 'PHP memory limit: '.ini_get('memory_limit').' <br/>';
|
2841 |
-
?>
|
2842 |
-
</p>
|
2843 |
-
<p style="max-width: 600px;"><?php _e('The buttons below will immediately execute a backup run, independently of WordPress\'s scheduler. If these work whilst your scheduled backups and the "Backup Now" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the "Backup Now" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them.','updraftplus');?></p>
|
2844 |
-
|
2845 |
-
<form method="post">
|
2846 |
-
<input type="hidden" name="action" value="updraft_backup_debug_all" />
|
2847 |
-
<p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Full Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled).','updraftplus'));?>'))" /></p>
|
2848 |
-
</form>
|
2849 |
-
<form method="post">
|
2850 |
-
<input type="hidden" name="action" value="updraft_backup_debug_db" />
|
2851 |
-
<p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Database Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites..','updraftplus'));?>'))" /></p>
|
2852 |
-
</form>
|
2853 |
-
<h3><?php _e('Wipe Settings','updraftplus');?></h3>
|
2854 |
-
<p style="max-width: 600px;"><?php _e('This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish.','updraftplus');?></p>
|
2855 |
-
<form method="post">
|
2856 |
-
<input type="hidden" name="action" value="updraft_wipesettings" />
|
2857 |
-
<p><input type="submit" class="button-primary" value="Wipe All Settings" onclick="return(confirm('<?php echo htmlspecialchars(__('This will delete all your UpdraftPlus settings - are you sure you want to do this?'));?>'))" /></p>
|
2858 |
-
</form>
|
2859 |
-
</div>
|
2860 |
-
|
2861 |
-
<script type="text/javascript">
|
2862 |
-
/* <![CDATA[ */
|
2863 |
-
jQuery(document).ready(function() {
|
2864 |
-
jQuery('#updraft-service').change(function() {
|
2865 |
-
jQuery('.updraftplusmethod').hide();
|
2866 |
-
var active_class = jQuery(this).val();
|
2867 |
-
jQuery('.'+active_class).show();
|
2868 |
-
});
|
2869 |
-
})
|
2870 |
-
jQuery(window).load(function() {
|
2871 |
-
//this is for hiding the restore progress at the top after it is done
|
2872 |
-
setTimeout('jQuery("#updraft-restore-progress").toggle(1000)',3000)
|
2873 |
-
jQuery('#updraft-restore-progress-toggle').click(function() {
|
2874 |
-
jQuery('#updraft-restore-progress').toggle(500)
|
2875 |
-
})
|
2876 |
-
})
|
2877 |
-
/* ]]> */
|
2878 |
-
</script>
|
2879 |
-
<?php
|
2880 |
-
}
|
2881 |
-
|
2882 |
-
function existing_backup_table($backup_history = false) {
|
2883 |
-
|
2884 |
-
// Fetch it if it was not passed
|
2885 |
-
if ($backup_history === false) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
2886 |
-
if (!is_array($backup_history)) $backup_history=array();
|
2887 |
-
|
2888 |
-
$updraft_dir = $this->backups_dir_location();
|
2889 |
-
|
2890 |
-
$backupable_entities = $this->get_backupable_file_entities(true, true);
|
2891 |
-
|
2892 |
-
echo '<table>';
|
2893 |
-
|
2894 |
-
krsort($backup_history);
|
2895 |
-
|
2896 |
-
foreach($backup_history as $key=>$value) {
|
2897 |
-
$pretty_date = date('Y-m-d G:i',$key);
|
2898 |
-
$entities = '';
|
2899 |
-
?>
|
2900 |
-
<tr>
|
2901 |
-
<td><b><?php echo $pretty_date?></b></td>
|
2902 |
-
<td>
|
2903 |
-
<?php if (isset($value['db'])) { ?>
|
2904 |
-
<form id="uddownloadform_db_<?php echo $key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader(<?php echo $key;?>, 'db')" method="post">
|
2905 |
-
<?php wp_nonce_field('updraftplus_download'); ?>
|
2906 |
-
<input type="hidden" name="action" value="updraft_download_backup" />
|
2907 |
-
<input type="hidden" name="type" value="db" />
|
2908 |
-
<input type="hidden" name="timestamp" value="<?php echo $key?>" />
|
2909 |
-
<input type="submit" value="<?php _e('Database','updraftplus');?>" />
|
2910 |
-
</form>
|
2911 |
-
<?php } else { echo "(No database)"; } ?>
|
2912 |
-
</td>
|
2913 |
-
|
2914 |
-
<?php
|
2915 |
-
foreach ($backupable_entities as $type => $info) {
|
2916 |
-
echo '<td>';
|
2917 |
-
if (isset($value[$type])) {
|
2918 |
-
$entities .= '/'.$type.'/';
|
2919 |
-
$sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
|
2920 |
-
?>
|
2921 |
-
<form id="uddownloadform_<?php echo $type.'_'.$key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader('<?php echo $key."', '".$type;?>')" method="post">
|
2922 |
-
<?php wp_nonce_field('updraftplus_download'); ?>
|
2923 |
-
<input type="hidden" name="action" value="updraft_download_backup" />
|
2924 |
-
<input type="hidden" name="type" value="<?php echo $type; ?>" />
|
2925 |
-
<input type="hidden" name="timestamp" value="<?php echo $key?>" />
|
2926 |
-
<input type="submit" title="<?php echo __('Press here to download','updraftplus').' '.strtolower($info['description']); ?>" value="<?php echo $sdescrip;?>" />
|
2927 |
-
</form>
|
2928 |
-
<?php } else { echo "(No ".strtolower($info['description']).")"; } ?>
|
2929 |
-
</td>
|
2930 |
-
<?php }; ?>
|
2931 |
-
|
2932 |
-
<td>
|
2933 |
-
<?php if (isset($value['nonce']) && preg_match("/^[0-9a-f]{12}$/",$value['nonce']) && is_readable($updraft_dir.'/log.'.$value['nonce'].'.txt')) { ?>
|
2934 |
-
<form action="options-general.php" method="get">
|
2935 |
-
<input type="hidden" name="action" value="downloadlog" />
|
2936 |
-
<input type="hidden" name="page" value="updraftplus" />
|
2937 |
-
<input type="hidden" name="updraftplus_backup_nonce" value="<?php echo $value['nonce']; ?>" />
|
2938 |
-
<input type="submit" value="Backup Log" />
|
2939 |
-
</form>
|
2940 |
-
<?php } else { echo "(No backup log)"; } ?>
|
2941 |
-
</td>
|
2942 |
-
<td>
|
2943 |
-
<form method="post" action="">
|
2944 |
-
<input type="hidden" name="backup_timestamp" value="<?php echo $key;?>">
|
2945 |
-
<input type="hidden" name="action" value="updraft_restore" />
|
2946 |
-
<?php if ($entities) { ?><button title="<?php _e('After pressing this button, you will be given the option to choose which components you wish to restore','updraftplus');?>" type="button" <?php echo $restore_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:16px !important; min-height:26px;" onclick="updraft_restore_options('<?php echo $entities;?>'); jQuery('#updraft_restore_timestamp').val('<?php echo $key;?>'); jQuery('#updraft_restore_date').html('<?php echo $pretty_date;?>'); jQuery('#updraft-restore-modal').dialog('open');">Restore</button><?php } ?>
|
2947 |
-
</form>
|
2948 |
-
</td>
|
2949 |
-
</tr>
|
2950 |
-
<script>
|
2951 |
-
function updraft_restore_options(entities) {
|
2952 |
-
jQuery('input[name="updraft_restore[]"]').each(function(x,y){
|
2953 |
-
var entity = jQuery(y).val();
|
2954 |
-
if (entities.indexOf('/'+entity+'/') != -1) {
|
2955 |
-
jQuery(y).removeAttr('disabled').parent().show();
|
2956 |
-
} else {
|
2957 |
-
jQuery(y).attr('disabled','disabled').parent().hide();
|
2958 |
-
}
|
2959 |
-
});
|
2960 |
-
}
|
2961 |
-
</script>
|
2962 |
-
<?php }
|
2963 |
-
echo '</table>';
|
2964 |
-
}
|
2965 |
-
|
2966 |
-
function show_admin_warning($message, $class = "updated") {
|
2967 |
-
echo '<div id="updraftmessage" class="'.$class.' fade">'."<p>$message</p></div>";
|
2968 |
-
}
|
2969 |
-
|
2970 |
-
function show_admin_warning_diskspace() {
|
2971 |
-
$this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue.','updraftplus'),'35 Mb'));
|
2972 |
-
}
|
2973 |
-
|
2974 |
-
function show_admin_warning_wordpressversion() {
|
2975 |
-
$this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress.'),'3.2'),'updraftplus');
|
2976 |
-
}
|
2977 |
-
|
2978 |
-
function show_admin_warning_unreadablelog() {
|
2979 |
-
$this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> '.__('The log file could not be read.','updraftplus'));
|
2980 |
-
}
|
2981 |
-
|
2982 |
-
function show_admin_warning_dropbox() {
|
2983 |
-
$this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-dropbox-auth&updraftplus_dropboxauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Dropbox','Dropbox').'</a>');
|
2984 |
-
}
|
2985 |
-
|
2986 |
-
function show_admin_warning_googledrive() {
|
2987 |
-
$this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-googledrive-auth&updraftplus_googleauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Google Drive','Google Drive').'</a>');
|
2988 |
-
}
|
2989 |
-
|
2990 |
-
// Caution: $source is allowed to be an array, not just a filename
|
2991 |
-
function make_zipfile($source, $destination) {
|
2992 |
-
|
2993 |
-
// When to prefer PCL:
|
2994 |
-
// - We were asked to
|
2995 |
-
// - No zip extension present and no relevant method present
|
2996 |
-
// The zip extension check is not redundant, because method_exists segfaults some PHP installs, leading to support requests
|
2997 |
-
|
2998 |
-
// Fallback to PclZip - which my tests show is 25% slower (and we can't resume)
|
2999 |
-
if ($this->zip_preferpcl || (!extension_loaded('zip') && !method_exists('ZipArchive', 'AddFile'))) {
|
3000 |
-
if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
|
3001 |
-
$zip_object = new PclZip($destination);
|
3002 |
-
$zipcode = $zip_object->create($source, PCLZIP_OPT_REMOVE_PATH, WP_CONTENT_DIR);
|
3003 |
-
if ($zipcode == 0 ) {
|
3004 |
-
$this->log("PclZip Error: ".$zip_object->errorName());
|
3005 |
-
return $zip_object->errorCode();
|
3006 |
-
} else {
|
3007 |
-
return true;
|
3008 |
-
}
|
3009 |
-
}
|
3010 |
-
|
3011 |
-
$this->existing_files = array();
|
3012 |
-
|
3013 |
-
// If the file exists, then we should grab its index of files inside, and sizes
|
3014 |
-
// Then, when we come to write a file, we should check if it's already there, and only add if it is not
|
3015 |
-
if (file_exists($destination) && is_readable($destination)) {
|
3016 |
-
$zip = new ZipArchive;
|
3017 |
-
$zip->open($destination);
|
3018 |
-
$this->log(basename($destination).": Zip file already exists, with ".$zip->numFiles." files");
|
3019 |
-
for ($i=0; $i<$zip->numFiles; $i++) {
|
3020 |
-
$si = $zip->statIndex($i);
|
3021 |
-
$name = $si['name'];
|
3022 |
-
$this->existing_files[$name] = $si['size'];
|
3023 |
-
}
|
3024 |
-
} elseif (file_exists($destination)) {
|
3025 |
-
$this->log("Zip file already exists, but is not readable; will remove: $destination");
|
3026 |
-
@unlink($destination);
|
3027 |
-
}
|
3028 |
-
|
3029 |
-
$this->zipfiles_added = 0;
|
3030 |
-
$this->zipfiles_dirbatched = array();
|
3031 |
-
$this->zipfiles_batched = array();
|
3032 |
-
|
3033 |
-
// Magic value, used later to detect no error occurring
|
3034 |
-
$last_error = 2349864;
|
3035 |
-
if (is_array($source)) {
|
3036 |
-
foreach ($source as $element) {
|
3037 |
-
$howmany = $this->makezip_recursive_add($destination, $element, basename($element), $element);
|
3038 |
-
if ($howmany < 0) {
|
3039 |
-
$last_error = $howmany;
|
3040 |
-
}
|
3041 |
-
}
|
3042 |
-
} else {
|
3043 |
-
$howmany = $this->makezip_recursive_add($destination, $source, basename($source), $source);
|
3044 |
-
if ($howmany < 0) {
|
3045 |
-
$last_error = $howmany;
|
3046 |
-
}
|
3047 |
-
}
|
3048 |
-
|
3049 |
-
// Any not yet dispatched?
|
3050 |
-
if (count($this->zipfiles_dirbatched)>0 || count($this->zipfiles_batched)>0) {
|
3051 |
-
$howmany = $this->makezip_addfiles($destination);
|
3052 |
-
if ($howmany < 0) {
|
3053 |
-
$last_error = $howmany;
|
3054 |
-
}
|
3055 |
-
}
|
3056 |
-
|
3057 |
-
if ($this->zipfiles_added > 0 || $last_error == 2349864) {
|
3058 |
-
// ZipArchive::addFile sometimes fails
|
3059 |
-
if (filesize($destination) < 100) {
|
3060 |
-
// Retry with PclZip
|
3061 |
-
$this->log("Zip::addFile apparently failed - retrying with PclZip");
|
3062 |
-
$this->zip_preferpcl = true;
|
3063 |
-
return $this->make_zipfile($source, $destination);
|
3064 |
-
}
|
3065 |
-
return true;
|
3066 |
-
} else {
|
3067 |
-
return $last_error;
|
3068 |
-
}
|
3069 |
-
|
3070 |
-
}
|
3071 |
-
|
3072 |
-
// Q. Why don't we only open and close the zip file just once?
|
3073 |
-
// A. Because apparently PHP doesn't write out until the final close, and it will return an error if anything file has vanished in the meantime. So going directory-by-directory reduces our chances of hitting an error if the filesystem is changing underneath us (which is very possible if dealing with e.g. 1Gb of files)
|
3074 |
-
|
3075 |
-
// We batch up the files, rather than do them one at a time. So we are more efficient than open,one-write,close.
|
3076 |
-
function makezip_addfiles($zipfile) {
|
3077 |
-
|
3078 |
-
// Short-circuit the null case, because we want to detect later if something useful happenned
|
3079 |
-
if (count($this->zipfiles_dirbatched) == 0 && count($this->zipfiles_batched) == 0) return true;
|
3080 |
-
|
3081 |
-
// 05-Mar-2013 - added a new check on the total data added; it appears that things fall over if too much data is contained in the cumulative total of files that were addFile'd without a close-open cycle; presumably data is being stored in memory. In the case in question, it was a batch of MP3 files of around 100Mb each - 25 of those equals 2.5Gb!
|
3082 |
-
|
3083 |
-
$data_added_since_reopen = 0;
|
3084 |
-
|
3085 |
-
$zip = new ZipArchive();
|
3086 |
-
if (file_exists($zipfile)) {
|
3087 |
-
$opencode = $zip->open($zipfile);
|
3088 |
-
$original_size = filesize($zipfile);
|
3089 |
-
clearstatcache($zipfile);
|
3090 |
-
} else {
|
3091 |
-
$opencode = $zip->open($zipfile, ZIPARCHIVE::CREATE);
|
3092 |
-
$original_size = 0;
|
3093 |
-
}
|
3094 |
-
|
3095 |
-
if ($opencode !== true) return array($opencode, 0);
|
3096 |
-
// Make sure all directories are created before we start creating files
|
3097 |
-
while ($dir = array_pop($this->zipfiles_dirbatched)) {
|
3098 |
-
$zip->addEmptyDir($dir);
|
3099 |
-
}
|
3100 |
-
foreach ($this->zipfiles_batched as $file => $add_as) {
|
3101 |
-
$fsize = filesize($file);
|
3102 |
-
if (!isset($this->existing_files[$add_as]) || $this->existing_files[$add_as] != $fsize) {
|
3103 |
-
|
3104 |
-
touch($file);
|
3105 |
-
$zip->addFile($file, $add_as);
|
3106 |
-
|
3107 |
-
$data_added_since_reopen += $fsize;
|
3108 |
-
# 25Mb - force a write-out and re-open
|
3109 |
-
if ($data_added_since_reopen > 26214400) {
|
3110 |
-
|
3111 |
-
$before_size = filesize($zipfile);
|
3112 |
-
clearstatcache($zipfile);
|
3113 |
-
|
3114 |
-
$this->log("Adding batch to zip file: over 25Mb added on this batch (".round($data_added_since_reopen/1048576,1)." Mb); re-opening (prior size: ".round($before_size/1024,1).' Kb)');
|
3115 |
-
if (!$zip->close()) {
|
3116 |
-
$this->log("zip::Close returned an error");
|
3117 |
-
}
|
3118 |
-
unset($zip);
|
3119 |
-
$zip = new ZipArchive();
|
3120 |
-
$opencode = $zip->open($zipfile);
|
3121 |
-
if ($opencode !== true) return array($opencode, 0);
|
3122 |
-
$data_added_since_reopen = 0;
|
3123 |
-
// Call here, in case we've got so many big files that we don't complete the whole routine
|
3124 |
-
if (filesize($zipfile) > $before_size) $this->something_useful_happened();
|
3125 |
-
clearstatcache($zipfile);
|
3126 |
-
}
|
3127 |
-
}
|
3128 |
-
$this->zipfiles_added++;
|
3129 |
-
if ($this->zipfiles_added % 100 == 0) $this->log("Zip: ".basename($zipfile).": ".$this->zipfiles_added." files added (on-disk size: ".round(filesize($zipfile)/1024,1)." Kb)");
|
3130 |
-
}
|
3131 |
-
// Reset the array
|
3132 |
-
$this->zipfiles_batched = array();
|
3133 |
-
$ret = $zip->close();
|
3134 |
-
if (filesize($zipfile) > $original_size) $this->something_useful_happened();
|
3135 |
-
clearstatcache(zipfile);
|
3136 |
-
return $ret;
|
3137 |
-
}
|
3138 |
-
|
3139 |
-
function something_useful_happened() {
|
3140 |
-
if ($this->current_resumption >= 9 && $this->newresumption_scheduled == false) {
|
3141 |
-
$resume_interval = $this->jobdata_get('resume_interval');
|
3142 |
-
if (!is_numeric($resume_interval) || $resume_interval<$this->minimum_resume_interval()) { $resume_interval = $this->minimum_resume_interval(); }
|
3143 |
-
$schedule_for = time()+$resume_interval;
|
3144 |
-
$this->newresumption_scheduled = $schedule_for;
|
3145 |
-
$this->log("This is resumption ".$this->current_resumption.", but meaningful activity is still taking place; so a new one will be scheduled");
|
3146 |
-
wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
|
3147 |
-
} else {
|
3148 |
-
$this->reschedule_if_needed();
|
3149 |
-
}
|
3150 |
-
}
|
3151 |
-
|
3152 |
-
// This function recursively packs the zip, dereferencing symlinks but packing into a single-parent tree for universal unpacking
|
3153 |
-
function makezip_recursive_add($zipfile, $fullpath, $use_path_when_storing, $original_fullpath) {
|
3154 |
-
|
3155 |
-
// De-reference
|
3156 |
-
$fullpath = realpath($fullpath);
|
3157 |
-
|
3158 |
-
// Is the place we've ended up above the original base? That leads to infinite recursion
|
3159 |
-
if (($fullpath !== $original_fullpath && strpos($original_fullpath, $fullpath) === 0) || ($original_fullpath == $fullpath && strpos($use_path_when_storing, '/') !== false) ) {
|
3160 |
-
$this->log("Infinite recursion: symlink lead us to $fullpath, which is within $original_fullpath");
|
3161 |
-
$this->error(__("Infinite recursion: consult your log for more information",'updraftplus'));
|
3162 |
-
return false;
|
3163 |
-
}
|
3164 |
-
|
3165 |
-
if(is_file($fullpath)) {
|
3166 |
-
if (is_readable($fullpath)) {
|
3167 |
-
$key = ($fullpath == $original_fullpath) ? basename($fullpath) : $use_path_when_storing.'/'.basename($fullpath);
|
3168 |
-
$this->zipfiles_batched[$fullpath] = $key;
|
3169 |
-
@touch($zipfile);
|
3170 |
-
} else {
|
3171 |
-
$this->log("$fullpath: unreadable file");
|
3172 |
-
$this->error("$fullpath: unreadable file");
|
3173 |
-
}
|
3174 |
-
} elseif (is_dir($fullpath)) {
|
3175 |
-
if (!isset($this->existing_files[$use_path_when_storing])) $this->zipfiles_dirbatched[] = $use_path_when_storing;
|
3176 |
-
if (!$dir_handle = @opendir($fullpath)) {
|
3177 |
-
$this->log("Failed to open directory: $fullpath");
|
3178 |
-
$this->error("Failed to open directory: $fullpath");
|
3179 |
-
return;
|
3180 |
-
}
|
3181 |
-
while ($e = readdir($dir_handle)) {
|
3182 |
-
if ($e != '.' && $e != '..') {
|
3183 |
-
if (is_link($fullpath.'/'.$e)) {
|
3184 |
-
$deref = realpath($fullpath.'/'.$e);
|
3185 |
-
if (is_file($deref)) {
|
3186 |
-
if (is_readable($deref)) {
|
3187 |
-
$this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
|
3188 |
-
@touch($zipfile);
|
3189 |
-
} else {
|
3190 |
-
$this->log("$deref: unreadable file");
|
3191 |
-
$this->error("$deref: unreadable file");
|
3192 |
-
}
|
3193 |
-
} elseif (is_dir($deref)) {
|
3194 |
-
$this->makezip_recursive_add($zipfile, $deref, $use_path_when_storing.'/'.$e, $original_fullpath);
|
3195 |
-
}
|
3196 |
-
} elseif (is_file($fullpath.'/'.$e)) {
|
3197 |
-
if (is_readable($fullpath.'/'.$e)) {
|
3198 |
-
$this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
|
3199 |
-
@touch($zipfile);
|
3200 |
-
} else {
|
3201 |
-
$this->log("$fullpath/$e: unreadable file");
|
3202 |
-
$this->error("$fullpath/$e: unreadable file");
|
3203 |
-
}
|
3204 |
-
} elseif (is_dir($fullpath.'/'.$e)) {
|
3205 |
-
// no need to addEmptyDir here, as it gets done when we recurse
|
3206 |
-
$this->makezip_recursive_add($zipfile, $fullpath.'/'.$e, $use_path_when_storing.'/'.$e, $original_fullpath);
|
3207 |
-
}
|
3208 |
-
}
|
3209 |
-
}
|
3210 |
-
closedir($dir_handle);
|
3211 |
-
}
|
3212 |
-
|
3213 |
-
// We don't want to touch the zip file on every single file, so we batch them up
|
3214 |
-
// We go every 25 files, because if you wait too much longer, the contents may have changed from under you
|
3215 |
-
// And for some redundancy (redundant because of the touches going on anyway), we try to touch the file after 20 seconds, to help with the "recently modified" check on resumption (we saw a case where the file went for 155 seconds without being touched and so the other runner was not detected)
|
3216 |
-
if (count($this->zipfiles_batched) > 25 || (file_exists($zipfile) && ((time()-filemtime($zipfile)) > 20) )) {
|
3217 |
-
$ret = $this->makezip_addfiles($zipfile);
|
3218 |
-
} else {
|
3219 |
-
$ret = true;
|
3220 |
-
}
|
3221 |
-
|
3222 |
-
return $ret;
|
3223 |
-
|
3224 |
-
}
|
3225 |
-
|
3226 |
}
|
3227 |
|
3228 |
|
2 |
/*
|
3 |
Plugin Name: UpdraftPlus - Backup/Restore
|
4 |
Plugin URI: http://updraftplus.com
|
5 |
+
Description: Backup and restore: take backups locally, or backup to Amazon S3, Dropbox, Google Drive, Rackspace, (S)FTP, WebDAV & email, on automatic schedules.
|
6 |
Author: UpdraftPlus.Com, DavidAnderson
|
7 |
+
Version: 1.5.20
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPLv3 or later
|
10 |
Text Domain: updraftplus
|
13 |
|
14 |
/*
|
15 |
TODO - some of these are out of date/done, needs pruning
|
16 |
+
// Add an appeal for translators to email me. If it a fails, use Google Translate Tools and appeal for native users to correct it.
|
17 |
+
// Automatically detect LiteSpeed and scan .htaccess and send them to the relevant FAQ
|
18 |
// Search for other TODO-s in the code
|
19 |
+
// Test in PHP 5.4
|
20 |
+
// Better Dropbox errors (see item in To-Do box)
|
21 |
+
// Count available time before doing a database restore
|
22 |
+
// Add in downloading in the 'Restore' modal, and remove the advice to do so manually.
|
23 |
+
// Provide an expert option to disable sslverify on WP HTTP requests. Mention in FAQs etc.
|
24 |
+
// Save database encryption key inside backup history on per-db basis, so that if it changes we can still decrypt
|
25 |
+
// Switch to Google Drive SDK. Google folders. https://developers.google.com/drive/folder
|
26 |
+
// GlotPress
|
27 |
+
// Convert S3.php to use WP's native HTTP functions
|
28 |
+
// Ability to re-scan existing cloud storage
|
29 |
+
// Migrator - search+replace the database
|
30 |
// Make mcrypt warning on dropbox more prominent - one customer missed it
|
31 |
// Store meta-data on which version of UD the backup was made with (will help if we ever introduce quirks that need ironing)
|
32 |
// Test restoration when uploads dir is /assets/ (e.g. with Shoestrap theme)
|
33 |
// Send the user an email upon their first backup with tips on what to do (e.g. support/improve) (include legacy check to not bug existing users)
|
34 |
//Allow use of /usr/bin/zip - since this can escape from PHP's memory limit. Can still batch as we do so, in order to monitor/measure progress
|
35 |
+
// Database decrypter
|
36 |
+
// Easier download of 'in progress' backup logs (not just last completed)
|
37 |
//Do an automated test periodically for the success of loop-back connections
|
38 |
//When a manual backup is run, use a timer to update the 'Download backups and logs' section, just like 'Last finished backup run'. Beware of over-writing anything that's in there from a resumable downloader.
|
39 |
//Change DB encryption to not require whole gzip in memory (twice)
|
46 |
// Should we resume if the only errors were upon deletion (i.e. the backup itself was fine?) Presently we do, but it displays errors for the user to confuse them. Perhaps better to make pruning a separate scheuled task??
|
47 |
// Warn the user if their zip-file creation is slooowww...
|
48 |
// Create a "Want Support?" button/console, that leads them through what is needed, and performs some basic tests...
|
49 |
+
// Chunking + resuming on SFTP
|
|
|
50 |
// Add-on to manage all your backups from a single dashboard
|
51 |
// Make disk space check more intelligent (currently hard-coded at 35Mb)
|
52 |
// Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install - some kind of single-use code which a remote UpdraftPlus can use to authenticate
|
53 |
// Multiple jobs
|
|
|
54 |
// Allow connecting to remote storage, scanning + populating backup history from it
|
55 |
// GoogleDrive in-dashboard download resumption loads the whole archive into memory - should instead either chunk or directly stream fo the file handle
|
56 |
// Multisite add-on should allow restoring of each blog individually
|
60 |
// Remove the recurrence of admin notices when settings are saved due to _wp_referer
|
61 |
|
62 |
Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
|
|
|
63 |
// New sub-module to verify that the backups are there, independently of backup thread
|
64 |
*/
|
65 |
|
66 |
/* Portions copyright 2010 Paul Kehrer
|
67 |
Portions copyright 2011-13 David Anderson
|
68 |
Other portions copyright as indicated authors in the relevant files
|
|
|
69 |
|
70 |
This program is free software; you can redistribute it and/or modify
|
71 |
it under the terms of the GNU General Public License as published by
|
82 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
83 |
*/
|
84 |
|
|
|
|
|
|
|
85 |
define('UPDRAFTPLUS_DIR', dirname(__FILE__));
|
86 |
define('UPDRAFTPLUS_URL', plugins_url('', __FILE__));
|
87 |
define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php,backup,backups');
|
91 |
|
92 |
// Load add-ons
|
93 |
if (is_file(UPDRAFTPLUS_DIR.'/premium.php')) require_once(UPDRAFTPLUS_DIR.'/premium.php');
|
94 |
+
if (is_file(UPDRAFTPLUS_DIR.'/autoload.php')) require_once(UPDRAFTPLUS_DIR.'/autoload.php');
|
95 |
|
96 |
if ($dir_handle = opendir(UPDRAFTPLUS_DIR.'/addons')) {
|
97 |
while ($e = readdir($dir_handle)) {
|
106 |
|
107 |
if (!$updraftplus->memory_check(192)) {
|
108 |
// Experience appears to show that the memory limit is only likely to be hit (unless it is very low) by single files that are larger than available memory (when compressed)
|
109 |
+
@ini_set('memory_limit', WP_MAX_MEMORY_LIMIT); //up the memory limit to the maximum WordPress is allowing for large backup files
|
110 |
}
|
111 |
|
112 |
if (!class_exists('UpdraftPlus_Options')) require_once(UPDRAFTPLUS_DIR.'/options.php');
|
147 |
var $current_resumption;
|
148 |
var $newresumption_scheduled = false;
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
function __construct() {
|
151 |
|
152 |
// Initialisation actions - takes place on plugin load
|
160 |
}
|
161 |
|
162 |
# Create admin page
|
163 |
+
add_action('init', array($this, 'handle_url_actions'));
|
164 |
+
// Run earlier than default - hence earlier than other components
|
165 |
+
add_action('admin_init', array($this,'admin_init'), 9);
|
166 |
+
// admin_menu runs earlier, and we need it because options.php wants to use $updraftplus_admin before admin_init happens
|
167 |
+
add_action('admin_menu', array($this,'admin_init'), 9);
|
168 |
add_action('updraft_backup', array($this,'backup_files'));
|
169 |
add_action('updraft_backup_database', array($this,'backup_database'));
|
170 |
+
# backup_all is used by the manual "Backup Now" button
|
171 |
add_action('updraft_backup_all', array($this,'backup_all'));
|
172 |
# this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
|
173 |
add_action('updraft_backup_resume', array($this,'backup_resume'), 10, 3);
|
|
|
|
|
174 |
# http://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
|
175 |
add_filter('cron_schedules', array($this,'modify_cron_schedules'));
|
|
|
|
|
176 |
add_action('plugins_loaded', array($this, 'load_translations'));
|
177 |
|
178 |
+
register_deactivation_hook(__FILE__, array($this, 'deactivation'));
|
179 |
|
180 |
}
|
181 |
|
182 |
+
function admin_init() {
|
183 |
+
// We are in the admin area: now load all that code
|
184 |
+
global $updraftplus_admin;
|
185 |
+
if (empty($updraftplus_admin)) require_once(UPDRAFTPLUS_DIR.'/admin.php');
|
186 |
+
|
187 |
+
if (isset($_GET['wpnonce']) && isset($_GET['page']) && isset($_GET['action']) && $_GET['page'] == 'updraftplus' && $_GET['action'] == 'downloadlatestmodlog' && wp_verify_nonce($_GET['wpnonce'], 'updraftplus_download')) {
|
188 |
+
|
189 |
+
$updraft_dir = $this->backups_dir_location();
|
190 |
+
|
191 |
+
$log_file = '';
|
192 |
+
$mod_time = 0;
|
193 |
+
|
194 |
+
if ($handle = opendir($updraft_dir)) {
|
195 |
+
while (false !== ($entry = readdir($handle))) {
|
196 |
+
// The latter match is for files created internally by zipArchive::addFile
|
197 |
+
if (preg_match('/^log\.[a-z0-9]+\.txt$/i', $entry)) {
|
198 |
+
$mtime = filemtime($updraft_dir.'/'.$entry);
|
199 |
+
if ($mtime > $mod_time) {
|
200 |
+
$mod_time = $mtime;
|
201 |
+
$log_file = $updraft_dir.'/'.$entry;
|
202 |
+
}
|
203 |
+
}
|
204 |
+
}
|
205 |
+
@closedir($handle);
|
206 |
+
}
|
207 |
+
|
208 |
+
if ($mod_time >0) {
|
209 |
+
if (is_readable($log_file)) {
|
210 |
+
header('Content-type: text/plain');
|
211 |
+
readfile($log_file);
|
212 |
+
exit;
|
213 |
+
} else {
|
214 |
+
add_action('admin_notices', array($this,'show_admin_warning_unreadablelog') );
|
215 |
+
}
|
216 |
+
} else {
|
217 |
+
add_action('admin_notices', array($this,'show_admin_warning_nolog') );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
}
|
222 |
+
|
223 |
+
function add_curl_capath($handle) {
|
224 |
+
if (!UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) curl_setopt($handle, CURLOPT_CAINFO, UPDRAFTPLUS_DIR.'/includes/cacert.pem' );
|
225 |
}
|
226 |
|
227 |
// Handle actions passed on to method plugins; e.g. Google OAuth 2.0 - ?page=updraftplus&action=updraftmethod-googledrive-auth
|
228 |
// Also handle action=downloadlog
|
229 |
function handle_url_actions() {
|
230 |
+
|
231 |
// First, basic security check: must be an admin page, with ability to manage options, with the right parameters
|
232 |
if ( UpdraftPlus_Options::user_can_manage() && isset( $_GET['page'] ) && $_GET['page'] == 'updraftplus' && isset($_GET['action']) ) {
|
233 |
if (preg_match("/^updraftmethod-([a-z]+)-([a-z]+)$/", $_GET['action'], $matches) && file_exists(UPDRAFTPLUS_DIR.'/methods/'.$matches[1].'.php')) {
|
235 |
require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
236 |
$call_class = "UpdraftPlus_BackupModule_".$method;
|
237 |
$call_method = "action_".$matches[2];
|
238 |
+
|
239 |
+
add_action('http_api_curl', array($this, 'add_curl_capath'));
|
240 |
if (method_exists($call_class, $call_method)) call_user_func(array($call_class,$call_method));
|
241 |
+
remove_action('http_api_curl', array($this, 'add_curl_capath'));
|
242 |
+
|
243 |
} elseif ($_GET['action'] == 'downloadlog' && isset($_GET['updraftplus_backup_nonce']) && preg_match("/^[0-9a-f]{12}$/",$_GET['updraftplus_backup_nonce'])) {
|
244 |
+
// No WordPress nonce is needed here or for the next, since the backup is already nonce-based
|
245 |
$updraft_dir = $this->backups_dir_location();
|
246 |
$log_file = $updraft_dir.'/log.'.$_GET['updraftplus_backup_nonce'].'.txt';
|
247 |
if (is_readable($log_file)) {
|
251 |
} else {
|
252 |
add_action('admin_notices', array($this,'show_admin_warning_unreadablelog') );
|
253 |
}
|
254 |
+
} elseif ($_GET['action'] == 'downloadfile' && isset($_GET['updraftplus_file']) && preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i', $_GET['updraftplus_file'])) {
|
255 |
+
$updraft_dir = $this->backups_dir_location();
|
256 |
+
$spool_file = $updraft_dir.'/'.$_GET['updraftplus_file'];
|
257 |
+
if (is_readable($spool_file)) {
|
258 |
+
$dkey = (isset($_GET['decrypt_key'])) ? $_GET['decrypt_key'] : "";
|
259 |
+
$this->spool_file('db', $spool_file, $dkey);
|
260 |
+
exit;
|
261 |
+
} else {
|
262 |
+
add_action('admin_notices', array($this,'show_admin_warning_unreadablefile') );
|
263 |
+
}
|
264 |
}
|
265 |
}
|
266 |
}
|
267 |
|
268 |
+
function show_admin_warning_unreadablelog() {
|
269 |
+
global $updraftplus_admin;
|
270 |
+
$updraftplus_admin->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> '.__('The log file could not be read.','updraftplus'));
|
271 |
+
}
|
272 |
+
|
273 |
+
function show_admin_warning_nolog() {
|
274 |
+
global $updraftplus_admin;
|
275 |
+
$updraftplus_admin->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> '.__('No log files were found.','updraftplus'));
|
276 |
+
}
|
277 |
+
|
278 |
+
function show_admin_warning_unreadablefile() {
|
279 |
+
global $updraftplus_admin;
|
280 |
+
$updraftplus_admin->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> '.__('The given file could not be read.','updraftplus'));
|
281 |
+
}
|
282 |
+
|
283 |
+
function load_translations() {
|
284 |
+
// Tell WordPress where to find the translations
|
285 |
+
load_plugin_textdomain('updraftplus', false, basename(dirname(__FILE__)).'/languages');
|
286 |
+
}
|
287 |
+
|
288 |
// Cleans up temporary files found in the updraft directory
|
289 |
function clean_temporary_files() {
|
290 |
$updraft_dir = $this->backups_dir_location();
|
301 |
}
|
302 |
}
|
303 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
function backup_time_nonce() {
|
305 |
$this->backup_time = time();
|
306 |
$nonce = substr(md5(time().rand()), 20);
|
318 |
$this->opened_log_time = microtime(true);
|
319 |
$this->log('Opened log file at time: '.date('r'));
|
320 |
global $wp_version;
|
321 |
+
$logline = "UpdraftPlus: ".$this->version." WP: ".$wp_version." PHP: ".phpversion()." (".php_uname().") Server: ".$_SERVER["SERVER_SOFTWARE"]." max_execution_time: ".@ini_get("max_execution_time")." memory_limit: ".ini_get('memory_limit')." ZipArchive::addFile : ";
|
322 |
|
323 |
// method_exists causes some faulty PHP installations to segfault, leading to support requests
|
324 |
if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
|
360 |
// i.e. Max 109 runs = 545 minutes = 9 hrs 05
|
361 |
// If they get 2 minutes on each run, and the file is 1Gb, then that equals 10.2Mb/120s = minimum 87Kb/s upload speed required
|
362 |
|
363 |
+
if ($percent > ( $this->current_resumption - 9)) {
|
364 |
$this->something_useful_happened();
|
365 |
}
|
366 |
}
|
367 |
|
368 |
+
function something_useful_happened() {
|
369 |
+
|
370 |
+
// First, update the record of maximum detected runtime on each run
|
371 |
+
$time_passed = $this->jobdata_get('run_times');
|
372 |
+
if (!is_array($time_passed)) $time_passed = array();
|
373 |
+
$time_passed[$this->current_resumption] = microtime(true)-$this->opened_log_time;
|
374 |
+
$this->jobdata_set('run_times', $time_passed);
|
375 |
+
|
376 |
+
if ($this->current_resumption >= 9 && $this->newresumption_scheduled == false) {
|
377 |
+
$this->log("This is resumption ".$this->current_resumption.", but meaningful activity is still taking place; so a new one will be scheduled");
|
378 |
+
$resume_interval = $this->jobdata_get('resume_interval');
|
379 |
+
if (!is_numeric($resume_interval) || $resume_interval<$this->minimum_resume_interval()) { $resume_interval = $this->minimum_resume_interval(); }
|
380 |
+
$schedule_for = time()+$resume_interval;
|
381 |
+
$this->newresumption_scheduled = $schedule_for;
|
382 |
+
wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
|
383 |
+
} else {
|
384 |
+
$this->reschedule_if_needed();
|
385 |
+
}
|
386 |
+
}
|
387 |
+
|
388 |
function minimum_resume_interval() {
|
389 |
// Bringing this down brings in more risk of undetectable overlaps than is worth it
|
390 |
return 300;
|
415 |
|
416 |
$arr = apply_filters('updraft_backupable_file_entities', $arr, $full_info);
|
417 |
|
418 |
+
// We always then add 'others' on to the end
|
419 |
if ($include_others) {
|
420 |
if ($full_info) {
|
421 |
$arr['others'] = array('path' => WP_CONTENT_DIR, 'description' => __('Others','updraftplus'));
|
430 |
|
431 |
function backup_resume($resumption_no, $bnonce) {
|
432 |
|
433 |
+
// 15 minutes
|
434 |
+
@set_time_limit(900);
|
435 |
+
|
436 |
@ignore_user_abort(true);
|
437 |
// This is scheduled for 5 minutes after a backup job starts
|
438 |
|
439 |
// Restore state
|
440 |
+
$resumption_extralog = '';
|
441 |
if ($resumption_no > 0) {
|
442 |
$this->nonce = $bnonce;
|
443 |
$this->backup_time = $this->jobdata_get('backup_time');
|
444 |
$this->logfile_open($bnonce);
|
445 |
+
|
446 |
+
$time_passed = $this->jobdata_get('run_times');
|
447 |
+
if (!is_array($time_passed)) $time_passed = array();
|
448 |
+
|
449 |
+
$prev_resumption = $resumption_no - 1;
|
450 |
+
if (isset($time_passed[$prev_resumption])) $resumption_extralog = ", previous check-in=".round($time_passed[$prev_resumption], 1)."s";
|
451 |
+
|
452 |
}
|
453 |
|
454 |
$btime = $this->backup_time;
|
460 |
$time_ago = time()-$btime;
|
461 |
|
462 |
$this->current_resumption = $resumption_no;
|
463 |
+
$this->log("Backup run: resumption=$resumption_no, nonce=$bnonce, begun at=$btime (${time_ago}s ago), job type=$job_type".$resumption_extralog);
|
464 |
|
465 |
// Schedule again, to run in 5 minutes again, in case we again fail
|
466 |
// The actual interval can be increased (for future resumptions) by other code, if it detects apparent overlapping
|
467 |
$resume_interval = $this->jobdata_get('resume_interval');
|
468 |
if (!is_numeric($resume_interval) || $resume_interval<$this->minimum_resume_interval()) $resume_interval = $this->minimum_resume_interval();
|
469 |
|
470 |
+
// We just do this once, as we don't want to be in permanent conflict with the overlap detector
|
471 |
+
if ($resumption_no == 8) {
|
472 |
+
$max_time = 0;
|
473 |
+
// $time_passed is set earlier
|
474 |
+
$timings_string = "";
|
475 |
+
$run_times_known=0;
|
476 |
+
for ($i=0; $i<=7; $i++) {
|
477 |
+
$timings_string .= "$i:";
|
478 |
+
if (isset($time_passed[$i])) {
|
479 |
+
$timings_string .= round($time_passed[$i], 1).' ';
|
480 |
+
$run_times_known++;
|
481 |
+
if ($time_passed[$i] > $max_time) $max_time = round($time_passed[$i]);
|
482 |
+
} else {
|
483 |
+
$timings_string .= '? ';
|
484 |
+
}
|
485 |
+
}
|
486 |
+
$this->log("Time passed on previous resumptions: $timings_string (known: $run_times_known, max: $max_time)");
|
487 |
+
if ($run_times_known >= 6 && ($max_time + 35 < $resume_interval)) {
|
488 |
+
$resume_interval = round($max_time + 35);
|
489 |
+
$this->log("Based on the available data, we are bringing the resumption interval down to: $resume_interval seconds");
|
490 |
+
$this->jobdata_set('resume_interval', $resume_interval);
|
491 |
+
}
|
492 |
+
}
|
493 |
+
|
494 |
// A different argument than before is needed otherwise the event is ignored
|
495 |
$next_resumption = $resumption_no+1;
|
496 |
if ($next_resumption < 10) {
|
499 |
wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($next_resumption, $bnonce));
|
500 |
$this->newresumption_scheduled = $schedule_for;
|
501 |
} else {
|
502 |
+
$this->log(sprintf('The current run is resumption number %d - will not schedule a further attempt until we see something useful happening', $resumption_no));
|
503 |
}
|
504 |
|
505 |
// Sanity check
|
506 |
if (empty($this->backup_time)) {
|
507 |
+
$this->log('Abort this run: the backup_time parameter appears to be empty (this is usually caused by resuming an already-complete backup, or by your site having a faulty object cache active (e.g. W3 Total Cache\'s object cache))');
|
508 |
return false;
|
509 |
}
|
510 |
|
641 |
set_transient("updraft_jobdata_".$this->nonce, $this->jobdata, 14400);
|
642 |
}
|
643 |
|
|
|
644 |
function jobdata_get($key) {
|
645 |
if (!is_array($this->jobdata)) {
|
646 |
$this->jobdata = get_transient("updraft_jobdata_".$this->nonce);
|
677 |
function boot_backup($backup_files, $backup_database) {
|
678 |
|
679 |
@ignore_user_abort(true);
|
680 |
+
// 15 minutes
|
681 |
+
@set_time_limit(900);
|
682 |
|
683 |
//generate backup information
|
684 |
$this->backup_time_nonce();
|
692 |
|
693 |
// Some house-cleaning
|
694 |
$this->clean_temporary_files();
|
695 |
+
do_action('updraftplus_boot_backup');
|
696 |
|
697 |
// Log some information that may be helpful
|
698 |
$this->log("Tasks: Backup files: $backup_files (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval', 'unset').") Backup DB: $backup_database (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval_database', 'unset').")");
|
789 |
// Make sure that the final status is shown
|
790 |
if (empty($this->errors)) {
|
791 |
$send_an_email = true;
|
792 |
+
$final_message = __("The backup apparently succeeded and is now complete",'updraftplus');
|
793 |
} elseif ($this->newresumption_scheduled == false) {
|
794 |
$send_an_email = true;
|
795 |
+
$final_message = __("The backup attempt has finished, apparently unsuccessfully",'updraftplus');
|
796 |
} else {
|
797 |
// There are errors, but a resumption will be attempted
|
798 |
+
$final_message = __("The backup has not finished; a resumption is scheduled within 5 minutes",'updraftplus');
|
799 |
}
|
800 |
|
801 |
// Now over-ride the decision to send an email, if needed
|
882 |
@set_time_limit(900);
|
883 |
|
884 |
$method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
|
885 |
+
add_action('http_api_curl', array($this, 'add_curl_capath'));
|
886 |
if (file_exists($method_include)) require_once($method_include);
|
887 |
+
remove_action('http_api_curl', array($this, 'add_curl_capath'));
|
888 |
|
889 |
if ($service == "none") {
|
890 |
$this->log("No remote despatch: user chose no remote backup service");
|
1056 |
$this->newresumption_scheduled = $schedule_for;
|
1057 |
}
|
1058 |
|
1059 |
+
function increase_resume_and_reschedule($howmuch = 120, $force_schedule = false) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1060 |
|
1061 |
+
$resume_interval = $this->jobdata_get('resume_interval');
|
1062 |
+
if (!is_numeric($resume_interval) || $resume_interval < $this->minimum_resume_interval()) $resume_interval = $this->minimum_resume_interval();
|
1063 |
|
1064 |
+
if (empty($this->newresumption_scheduled) && $force_schedule) {
|
1065 |
+
$this->log("A new resumption will be scheduled to prevent the job ending");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1066 |
}
|
1067 |
|
1068 |
+
if (!empty($this->newresumption_scheduled) || $force_schedule) $this->reschedule($resume_interval+$howmuch);
|
1069 |
+
$this->jobdata_set('resume_interval', $resume_interval+$howmuch);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1070 |
|
1071 |
+
$this->log("To decrease the likelihood of overlaps, increasing resumption interval to: $resume_interval + $howmuch = ".($resume_interval+$howmuch));
|
1072 |
}
|
1073 |
|
1074 |
// For detecting another run, and aborting if one was found
|
1077 |
$time_mod = (int)@filemtime($file);
|
1078 |
$time_now = time();
|
1079 |
if ($time_mod>100 && ($time_now-$time_mod)<30) {
|
1080 |
+
$this->terminate_due_to_activity($file, $time_now, $time_mod);
|
|
|
|
|
1081 |
}
|
1082 |
}
|
1083 |
}
|
1094 |
return array();
|
1095 |
}
|
1096 |
|
1097 |
+
// Bring in all the zip routines
|
1098 |
+
require_once(UPDRAFTPLUS_DIR.'/backup.php');
|
1099 |
+
global $updraftplus_backup;
|
1100 |
+
|
1101 |
//get the blog name and rip out all non-alphanumeric chars other than _
|
1102 |
$blog_name = str_replace(' ','_',substr(get_bloginfo(), 0, 96));
|
1103 |
$blog_name = preg_replace('/[^A-Za-z0-9_]/','', $blog_name);
|
1112 |
# Plugins, themes, uploads
|
1113 |
foreach ($possible_backups as $youwhat => $whichdir) {
|
1114 |
|
1115 |
+
// TODO: Should store what is wanted in the job description
|
1116 |
+
if (UpdraftPlus_Options::get_updraft_option("updraft_include_$youwhat", apply_filters("updraftplus_defaultoption_include_$youwhat", true))) {
|
1117 |
|
1118 |
$zip_file = $updraft_dir.'/'.$backup_file_basename.'-'.$youwhat.'.zip';
|
1119 |
|
1123 |
$backup_array[$youwhat] = $backup_file_basename.'-'.$youwhat.'.zip';
|
1124 |
if (file_exists($zip_file)) $backup_array[$youwhat.'-size'] = filesize($zip_file);
|
1125 |
} else {
|
1126 |
+
# Apply a filter to allow add-ons to provide their own method for creating a zip of the entity
|
1127 |
+
$created = apply_filters('updraftplus_backup_makezip_'.$youwhat, $whichdir, $backup_file_basename);
|
1128 |
+
# If the filter did not lead to something being created, then use the default method
|
1129 |
+
if ($created == $whichdir) {
|
1130 |
+
$created = $updraftplus_backup->create_zip($whichdir, $youwhat, $updraft_dir, $backup_file_basename);
|
1131 |
+
}
|
1132 |
if ($created) {
|
1133 |
$backup_array[$youwhat] = $created;
|
1134 |
$backup_array[$youwhat.'-size'] = filesize($updraft_dir.'/'.$created);
|
1160 |
A string containing a list of filename or dirname separated by a comma.
|
1161 |
*/
|
1162 |
|
1163 |
+
# Create an array of directories to be skipped
|
|
|
|
|
1164 |
$others_skip = preg_split("/,/",UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude', UPDRAFT_DEFAULT_OTHERS_EXCLUDE));
|
1165 |
# Make the values into the keys
|
1166 |
$others_skip = array_flip($others_skip);
|
1167 |
|
1168 |
+
$possible_backups_dirs = array_flip($possible_backups);
|
1169 |
+
|
1170 |
+
$other_dirlist = $this->compile_folder_list_for_backup(WP_CONTENT_DIR, $possible_backups_dirs, $others_skip);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1171 |
|
1172 |
if (count($other_dirlist)>0) {
|
1173 |
+
$created = $updraftplus_backup->create_zip($other_dirlist, 'others', $updraft_dir, $backup_file_basename);
|
1174 |
if ($created) {
|
1175 |
$backup_array['others'] = $created;
|
1176 |
$backup_array['others-size'] = filesize($updraft_dir.'/'.$created);
|
1178 |
} else {
|
1179 |
$this->log("No backup of other directories: there was nothing found to back up");
|
1180 |
}
|
1181 |
+
|
1182 |
# If we are not already finished
|
1183 |
}
|
1184 |
} else {
|
1187 |
return $backup_array;
|
1188 |
}
|
1189 |
|
1190 |
+
// avoid_these_dirs and skip_these_dirs ultimately do the same thing; but avoid_these_dirs takes full paths whereas skip_these_dirs takes basenames; and they are logged differently (avoid is potentially dangerous; skip is just a preference). They are allowed to overlap.
|
1191 |
+
function compile_folder_list_for_backup($backup_from_inside_dir, $avoid_these_dirs, $skip_these_dirs) {
|
1192 |
+
|
1193 |
+
$dirlist = array();
|
1194 |
+
|
1195 |
+
$this->log('Looking for candidates to back up in: '.$backup_from_inside_dir);
|
1196 |
+
|
1197 |
+
$updraft_dir = $this->backups_dir_location();
|
1198 |
+
if ($handle = opendir($backup_from_inside_dir)) {
|
1199 |
+
|
1200 |
+
while (false !== ($entry = readdir($handle))) {
|
1201 |
+
$candidate = $backup_from_inside_dir.'/'.$entry;
|
1202 |
+
if ($entry != "." && $entry != "..") {
|
1203 |
+
if (isset($avoid_these_dirs[$candidate])) {
|
1204 |
+
$this->log("finding files: $entry: skipping: this is the ".$avoid_these_dirs[$candidate]." directory");
|
1205 |
+
} elseif ($candidate == $updraft_dir) {
|
1206 |
+
$this->log("finding files: $entry: skipping: this is the updraft directory");
|
1207 |
+
} elseif (isset($skip_these_dirs[$entry])) {
|
1208 |
+
$this->log("finding files: $entry: skipping: excluded by options");
|
1209 |
+
} else {
|
1210 |
+
$this->log("finding files: $entry: adding to list");
|
1211 |
+
array_push($dirlist, $candidate);
|
1212 |
+
}
|
1213 |
+
}
|
1214 |
+
}
|
1215 |
+
@closedir($handle);
|
1216 |
+
} else {
|
1217 |
+
$this->log('ERROR: Could not read the directory: '.$backup_from_inside_dir);
|
1218 |
+
$this->error(__('Could not read the directory', 'updraftplus').': '.$backup_from_inside_dir);
|
1219 |
+
}
|
1220 |
+
|
1221 |
+
return $dirlist;
|
1222 |
+
|
1223 |
+
}
|
1224 |
+
|
1225 |
function save_backup_history($backup_array) {
|
1226 |
if(is_array($backup_array)) {
|
1227 |
$backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
|
1269 |
|
1270 |
//Begin new backup of MySql
|
1271 |
$this->stow("# " . 'WordPress MySQL database backup' . "\n");
|
1272 |
+
$this->stow("# " . 'Created by UpdraftPlus (http://updraftplus.com)' . "\n");
|
1273 |
$this->stow("#\n");
|
1274 |
$this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
|
1275 |
$this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
|
1359 |
$time_now = time();
|
1360 |
$time_mod = (int)@filemtime($backup_final_file_name);
|
1361 |
if (file_exists($backup_final_file_name) && $time_mod>100 && ($time_now-$time_mod)<20) {
|
1362 |
+
$this->terminate_due_to_activity($backup_final_file_name, $time_now, $time_mod);
|
|
|
|
|
|
|
1363 |
} elseif (file_exists($backup_final_file_name)) {
|
1364 |
$this->log("The final database file ($backup_final_file_name) exists, but was apparently not modified within the last 20 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod)."). Thus we assume that another UpdraftPlus terminated; thus we will continue.");
|
1365 |
}
|
1404 |
|
1405 |
} //wp_db_backup
|
1406 |
|
1407 |
+
function terminate_due_to_activity($file, $time_now, $time_mod) {
|
1408 |
+
$file_size = filesize($file);
|
1409 |
+
$this->log("Terminate: the final database file ($file) exists, and was modified within the last 20 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=$file_size). This likely means that another UpdraftPlus run is at work; so we will exit.");
|
1410 |
+
$this->increase_resume_and_reschedule(120, true);
|
1411 |
+
die;
|
1412 |
+
}
|
1413 |
+
|
1414 |
/**
|
1415 |
* Taken partially from phpMyAdmin and partially from
|
1416 |
* Alain Wolf, Zurich - Switzerland
|
1460 |
$this->stow($create_table[0][1] . ' ;');
|
1461 |
|
1462 |
if (false === $table_structure) {
|
1463 |
+
$err_msg = sprintf('Error getting table structure of %s', $table);
|
|
|
1464 |
$this->stow("#\n# $err_msg\n#\n");
|
1465 |
}
|
1466 |
|
1467 |
// Comment in SQL-file
|
1468 |
+
$this->stow("\n\n#\n# " . sprintf('Data contents of table %s',$this->backquote($table)) . "\n#\n");
|
1469 |
}
|
1470 |
|
1471 |
// In UpdraftPlus, segment is always 'none'
|
1491 |
|
1492 |
do {
|
1493 |
if ( !@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == "off") @set_time_limit(15*60);
|
1494 |
+
|
1495 |
$table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
|
1496 |
+
$entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES ';
|
1497 |
// \x08\\x09, not required
|
1498 |
$search = array("\x00", "\x0a", "\x0d", "\x1a");
|
1499 |
$replace = array('\0', '\n', '\r', '\Z');
|
1500 |
if($table_data) {
|
1501 |
+
$thisentry = "";
|
1502 |
foreach ($table_data as $row) {
|
1503 |
$total_rows++;
|
1504 |
$values = array();
|
1512 |
$values[] = "'" . str_replace($search, $replace, str_replace('\'', '\\\'', str_replace('\\', '\\\\', $value))) . "'";
|
1513 |
}
|
1514 |
}
|
1515 |
+
if ($thisentry) $thisentry .= ",\n ";
|
1516 |
+
$thisentry .= '('.implode(', ', $values).')';
|
1517 |
+
// Flush every 512Kb
|
1518 |
+
if (strlen($thisentry) > 524288) {
|
1519 |
+
$this->stow(" \n".$entries.$thisentry.';');
|
1520 |
+
$thisentry = "";
|
1521 |
+
}
|
1522 |
+
|
1523 |
}
|
1524 |
+
if ($thisentry) $this->stow(" \n".$entries.$thisentry.';');
|
1525 |
$row_start += $row_inc;
|
1526 |
}
|
1527 |
} while((count($table_data) > 0) and ($segment=='none'));
|
1587 |
|
1588 |
/*END OF WP-DB-BACKUP BLOCK */
|
1589 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1590 |
/*
|
1591 |
this function is both the backup scheduler and ostensibly a filter callback for saving the option.
|
1592 |
it is called in the register_setting for the updraft_interval, which means when the admin settings
|
1611 |
return wp_filter_nohtml_kses($interval);
|
1612 |
}
|
1613 |
|
1614 |
+
function deactivation () {
|
1615 |
+
wp_clear_scheduled_hook('updraftplus_weekly_ping');
|
1616 |
+
}
|
1617 |
+
|
1618 |
// Acts as a WordPress options filter
|
1619 |
function googledrive_clientid_checkchange($client_id) {
|
1620 |
+
if (UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid') != $client_id) {
|
1621 |
require_once(UPDRAFTPLUS_DIR.'/methods/googledrive.php');
|
1622 |
+
add_action('http_api_curl', array($this, 'add_curl_capath'));
|
1623 |
UpdraftPlus_BackupModule_googledrive::gdrive_auth_revoke(true);
|
1624 |
+
remove_action('http_api_curl', array($this, 'add_curl_capath'));
|
1625 |
+
|
1626 |
}
|
1627 |
return $client_id;
|
1628 |
}
|
1655 |
return $schedules;
|
1656 |
}
|
1657 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1658 |
function backups_dir_location() {
|
1659 |
|
1660 |
if (!empty($this->backup_dir)) return $this->backup_dir;
|
1682 |
return $updraft_dir;
|
1683 |
}
|
1684 |
|
1685 |
+
function spool_file($type, $fullpath, $encryption = "") {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1686 |
|
1687 |
+
@set_time_limit(900);
|
|
|
|
|
1688 |
|
1689 |
if (file_exists($fullpath)) {
|
1690 |
|
1695 |
$filearr = explode('.',$file);
|
1696 |
// //we've only got zip and gz...for now
|
1697 |
$file_ext = array_pop($filearr);
|
|
|
|
|
|
|
|
|
|
|
|
|
1698 |
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
|
1699 |
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
|
1700 |
header("Content-Length: $len;");
|
1701 |
+
|
1702 |
if ($file_ext == 'crypt') {
|
1703 |
+
if ($encryption == "") $encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
|
|
|
|
|
|
|
|
|
|
|
|
|
1704 |
if ($encryption == "") {
|
1705 |
+
header('Content-type: text/plain');
|
1706 |
+
_e("Decryption failed. The database file is encrypted, but you have no encryption key entered.",'updraftplus');
|
1707 |
$this->error('Decryption of database failed: the database file is encrypted, but you have no encryption key entered.');
|
1708 |
} else {
|
1709 |
+
require_once(UPDRAFTPLUS_DIR.'/includes/phpseclib/Crypt/Rijndael.php');
|
1710 |
$rijndael = new Crypt_Rijndael();
|
1711 |
$rijndael->setKey($encryption);
|
1712 |
+
$ciphertext = $rijndael->decrypt(file_get_contents($fullpath));
|
1713 |
+
if ($ciphertext) {
|
1714 |
+
header('Content-type: application/x-gzip');
|
1715 |
+
header("Content-Disposition: attachment; filename=\"".substr($file,0,-6)."\";");
|
1716 |
+
print $ciphertext;
|
1717 |
+
} else {
|
1718 |
+
header('Content-type: text/plain');
|
1719 |
+
echo __("Decryption failed. The most likely cause is that you used the wrong key.",'updraftplus')." ".__('The decryption key used:','updraftplus').' '.$encryption;
|
1720 |
+
|
1721 |
}
|
|
|
|
|
1722 |
}
|
1723 |
} else {
|
1724 |
+
if ($file_ext == 'zip') {
|
1725 |
+
header('Content-type: application/zip');
|
1726 |
+
} else {
|
1727 |
+
header('Content-type: application/x-gzip');
|
1728 |
+
}
|
1729 |
+
header("Content-Disposition: attachment; filename=\"$file\";");
|
1730 |
readfile($fullpath);
|
1731 |
}
|
1732 |
// $this->delete_local($file);
|
1735 |
}
|
1736 |
}
|
1737 |
|
1738 |
+
function retain_range($input) {
|
1739 |
+
$input = (int)$input;
|
1740 |
+
return ($input > 0 && $input < 3650) ? $input : 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1741 |
}
|
1742 |
|
1743 |
function memory_check_current() {
|
1759 |
return $memory_limit;
|
1760 |
}
|
1761 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1762 |
function memory_check($memory) {
|
1763 |
$memory_limit = $this->memory_check_current();
|
1764 |
return ($memory_limit >= $memory)?true:false;
|
1765 |
}
|
1766 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1767 |
function url_start($urls,$url) {
|
1768 |
return ($urls) ? '<a href="http://'.$url.'">' : "";
|
1769 |
}
|
1783 |
if (defined('WPLANG') && strlen(WPLANG)>0 && !is_file(UPDRAFTPLUS_DIR.'/languages/updraftplus-'.WPLANG.
|
1784 |
'.mo')) return __('Can you translate? Want to improve UpdraftPlus for speakers of your language?','updraftplus').$this->url_start($urls,'updraftplus.com/translate/')."Please go here for instructions - it is easy.".$this->url_end($urls,'updraftplus.com/translate/');
|
1785 |
|
1786 |
+
return __('Find UpdraftPlus useful?','updraftplus').' '.$this->url_start($urls,'david.dw-perspective.org.uk/donate').__("Please make a donation", 'updraftplus').$this->url_end($urls,'david.dw-perspective.org.uk/donate');
|
1787 |
case 2:
|
1788 |
return $this->url_start($urls,'wordshell.net')."Check out WordShell".$this->url_end($urls,'www.wordshell.net')." - manage WordPress from the command line - huge time-saver";
|
1789 |
break;
|
1812 |
}
|
1813 |
}
|
1814 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1815 |
}
|
1816 |
|
1817 |
|