diff --git a/README.md b/README.md
new file mode 100644
index 00000000..2c46c71f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,167 @@
+# WP Offload S3 #
+**Contributors:** bradt
+**Donate link:** https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC
+**Tags:** uploads, amazon, s3, mirror, admin, media, cdn, cloudfront
+**Requires at least:** 3.5
+**Tested up to:** 4.2.2
+**Stable tag:** 0.9
+**License:** GPLv3
+
+Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
+
+## Description ##
+
+This plugin automatically copies images, videos, documents, and any other media added through WordPress' media uploader to [Amazon Simple Storage Service](http://aws.amazon.com/s3/) (S3). It then automatically replaces the URL to each media file with their respective S3 URL or, if you have configured [Amazon CloudFront](http://aws.amazon.com/cloudfront/), the respective CloudFront URL. Image thumbnails are also copied to S3 and delivered through S3/CloudFront.
+
+Uploading files *directly* to your S3 account is not currently supported by this plugin. They are uploaded to your server first, then copied to S3. There is an option to automatically remove the files from your server once they are copied to S3 however.
+
+If you're adding this plugin to a site that's been around for a while, your existing media files will not be copied or served from S3. Only newly uploaded files will be copied and served from S3.
+
+**Pro Version**
+
+We’re working on a pro version that will include the following features:
+
+* Copy existing Media Library to S3
+* Serve theme JS & CSS from S3/CloudFront
+* WooCommerce & EDD integration
+* Awesome email support
+
+[Sign up for news about the pro version](https://confirmsubscription.com/h/t/295CA85AEB94E879)
+
+[Request features, report bugs, and submit pull requests on Github](https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront/issues)
+
+*This plugin has been completely rewritten, but was originally a fork of
+[Amazon S3 for WordPress with CloudFront](http://wordpress.org/extend/plugins/tantan-s3-cloudfront/)
+which is a fork of [Amazon S3 for WordPress](http://wordpress.org/extend/plugins/tantan-s3/), also known as tantan-s3.*
+
+## Installation ##
+
+1. Install the required [Amazon Web Services plugin](http://wordpress.org/extend/plugins/amazon-web-services/) using WordPress' built-in installer
+2. Follow the instructions to setup your AWS access keys
+3. Install this plugin using WordPress' built-in installer
+4. Access the *S3 and CloudFront* option under *AWS* and configure
+
+## Screenshots ##
+
+### 1. Choosing/creating a bucket ###
+![Choosing/creating a bucket](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-s3/assets/screenshot-1.png)
+
+### 2. Settings screen ###
+![Settings screen](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-s3/assets/screenshot-2.png)
+
+
+## Upgrade Notice ##
+
+### 0.6 ###
+This version requires PHP 5.3.3+ and the Amazon Web Services plugin
+
+### 0.6.1 ###
+This version requires PHP 5.3.3+ and the Amazon Web Services plugin
+
+### 0.6.2 ###
+This version requires PHP 5.3.3+ and the Amazon Web Services plugin
+
+## Changelog ##
+
+### 0.9 - 2015-07-08 ###
+* New: Plugin rebranded to WP Offload S3
+* New: Support tab added to _Offload S3_ screen containing diagnostic information
+* New: Compatibility with the [Media Replace](https://wordpress.org/plugins/enable-media-replace/) plugin
+* New: Select bucket region when creating a new bucket
+* New: Toggle switches redesigned
+* Improvement: Compatibility with release candidate of Pro plugin
+* Improvement: Example IAM policy more secure
+* Improvement: Set default bucket region using the `AS3CF_REGION` constant
+* Improvement: Added `as3cf_object_meta` filter for developers
+* Improvement: Bucket selection moved to modal window
+* Improvement: Don't allow bucket names to contain invalid characters on creation
+* Improvement: More verbose error messages on bucket selection
+* Improvement: Settings link added to plugin row on _Plugins_ screen
+* Improvement: Object versioning enabled by default
+* Improvement: Uninstall routines added
+* Improvement: JavaScript coding standards
+* Improvement: Cache result when checking S3 bucket permissions
+* Bug fix: Bucket region errors result in blank WP Offload S3 screen
+* Bug fix: Editing an image when _Remove Files From Server_ option is enabled results in error
+* Bug fix: Metadata upgrade procedure triggered on new installs
+* Bug fix: File URLs when uploaded to a subdirectory result in incorrect S3 URLs
+* Bug fix: Errors logged when trying to delete non-existent HiDPI images
+* Bug fix: SignatureDoesNotMatch errors on regions with v4 authentication
+* Bug fix: Customizer background image not editable
+* Bug fix: Error when creating buckets with US Standard region
+* Bug fix: Notices appearing incorrectly on some admin screens
+* Bug fix: Subsite upload paths repeated on multisite installs
+* Bug fix: Handle multisite installs where `BLOG_ID_CURRENT_SITE` is not 1
+
+### 0.8.2 - 2015-01-31 ###
+* New: Input bucket in settings to avoid listing all buckets
+* New: Specify bucket with 'AS3CF_BUCKET' constant
+* Improvement: Compatibility with beta release of Pro plugin
+* Bug Fix: Incorrect file prefix in S3 permission check
+
+### 0.8.1 - 2015-01-19 ###
+* Bug Fix: Permission problems on installs running on EC2s
+* Bug Fix: Blank settings page due to WP_Error on S3 permission check
+* Bug Fix: Warning: strtolower() expects parameter 1 to be string, object given
+* Bug Fix: Region post meta update running on subsites of Multisite installs
+
+### 0.8 - 2015-01-10 ###
+* New: Redesigned settings UI
+* Improvement: SSL setting can be fully controlled, HTTPS for urls always, based on request or never
+* Improvement: Download files from S3 that are not found on server when running Regenerate Thumbnails plugin
+* Improvement: When calling `get_attached_file()` and file is missing from server, return S3 URL
+* Improvement: Code cleanup to WordPress coding standards
+* Bug Fix: Files for all subsites going into the same S3 folder on multisite installs setup prior to WP 3.5
+* Bug Fix: 'attempting to access local file system' error for some installs
+
+### 0.7.2 - 2014-12-11 ###
+* Bug: Some buckets in the EU region causing permission and HTTP errors
+* Bug: Undefined variable: message in view/error.php also causing white screens
+
+### 0.7.1 - 2014-12-05 ###
+* Bug: Read-only error on settings page sometimes false positive
+
+### 0.7 - 2014-12-04 ###
+* New: Proper S3 region subdomain in URLs for buckets not in the US Standard region (e.g. https://s3-us-west-2.amazonaws.com/...)
+* New: Update all existing attachment meta with bucket region (automatically runs in the background)
+* New: Get secure URL for different image sizes (iamzozo)
+* New: S3 bucket can be set with constant in wp-config.php (dberube)
+* New: Filter for allowing/disallowing file types: `as3cf_allowed_mime_types`
+* New: Filter to cancel upload to S3 for any reason: `as3cf_pre_update_attachment_metadata`
+* New: Sidebar with email opt-in
+* Improvement: Show warning when S3 policy is read-only
+* Improvement: Tooltip added to clarify option
+* Improvement: Move object versioning option to make it clear it does not require CloudFront
+* Improvement: By default only allow file types in `get_allowed_mime_types()` to be uploaded to S3
+* Improvement: Compatibility with WPML Media plugin
+* Bug Fix: Edited images not removed on S3 when restoring image and IMAGE_EDIT_OVERWRITE true
+* Bug Fix: File names with certain characters broken not working
+* Bug Fix: Edited image uploaded to incorrect month folder
+* Bug Fix: When creating a new bucket the bucket select box appears empty on success
+* Bug Fix: SSL not working in regions other than US Standard
+* Bug Fix: 'Error uploading' and 'Error removing local file' messages when editing an image
+* Bug Fix: Upload and delete failing when bucket is non-US-region and bucket name contains dot
+* Bug Fix: S3 file overwritten when file with same name uploaded and local file removed (dataferret)
+* Bug Fix: Manually resized images not uploaded (gmauricio)
+
+### 0.6.1 - 2013-09-21 ###
+* WP.org download of Amazon Web Services plugin is giving a 404 Not Found, so directing people to download from Github instead
+
+### 0.6 - 2013-09-20 ###
+* Complete rewrite
+* Now requires PHP 5.3.3+
+* Now requires the [Amazon Web Services plugin](http://wordpress.org/extend/plugins/amazon-web-services/) which contains the latest PHP libraries from Amazon
+* Now works with multisite
+* New Option: Custom S3 object path
+* New Option: Always serve files over https (SSL)
+* New Option: Enable object versioning by appending a timestamp to the S3 file path
+* New Option: Remove uploaded file from local filesystem once it has been copied to S3
+* New Option: Copy any HiDPI (@2x) images to S3 (works with WP Retina 2x plugin)
+
+### 0.5 - 2013-01-29 ###
+* Forked [Amazon S3 for WordPress with CloudFront](http://wordpress.org/extend/plugins/tantan-s3-cloudfront/)
+* Cleaned up the UI to fit with today's WP UI
+* Fixed issues causing error messages when WP_DEBUG is on
+* [Delete files on S3 when deleting WP attachment](https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront/commit/e777cd49a4b6999f999bd969241fb24cbbcece60)
+* [Added filter to the get_attachment_url function](https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront/commit/bbe1aed5c2ae900e9ba1b16ba6806c28ab8e2f1c)
+* [Added function to get a temporary, secure download URL for private files](https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront/commit/11f46ec2714d34907009e37ad3b97f4421aefed3)
diff --git a/assets/.jshintrc b/assets/.jshintrc
deleted file mode 100644
index 35162bb7..00000000
--- a/assets/.jshintrc
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "boss": true,
- "browser": true,
- "curly": true,
- "devel": true,
- "eqeqeq": true,
- "eqnull": true,
- "es3": false,
- "immed": true,
- "jquery": true,
- "latedef": true,
- "maxerr": 10000,
- "newcap": true,
- "noarg": true,
- "sub": true,
- "undef": true,
- "globals": {
- "ajaxurl": true,
- "as3cf_i18n": true
- }
-}
\ No newline at end of file
diff --git a/assets/Gruntfile.js b/assets/Gruntfile.js
deleted file mode 100644
index 7013d6cc..00000000
--- a/assets/Gruntfile.js
+++ /dev/null
@@ -1,47 +0,0 @@
-module.exports = function(grunt) {
-
- grunt.initConfig({
- pkg: grunt.file.readJSON('package.json'),
- jshint: {
- all: [
- 'js/*.js',
- '!js/*.min.js'
- ],
- options: {
- jshintrc: '.jshintrc',
- force: true
- }
- },
- uglify: {
- build: {
- files: {
- 'js/script.min.js': 'js/script.js'
- }
- }
- },
- compass: {
- dist: {
- options: {
- }
- }
- },
- watch: {
- js: {
- files: ['js/*.js', '!js/*.min.js'],
- tasks: ['uglify']
- },
- sass: {
- files: ['sass/*'],
- tasks: ['compass']
- }
- }
- });
-
- grunt.loadNpmTasks('grunt-contrib-jshint');
- grunt.loadNpmTasks('grunt-contrib-uglify');
- grunt.loadNpmTasks('grunt-contrib-watch');
- grunt.loadNpmTasks('grunt-contrib-compass');
-
- grunt.registerTask('default', ['jshint','uglify','compass']);
-
-};
diff --git a/assets/config.rb b/assets/config.rb
deleted file mode 100644
index f286c0f4..00000000
--- a/assets/config.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# Require any additional compass plugins here.
-
-# Set this to the root of your project when deployed:
-http_path = "/"
-css_dir = "css"
-sass_dir = "sass"
-images_dir = "img"
-javascripts_dir = "js"
-
-# You can select your preferred output style here (can be overridden via the command line):
-# output_style = :expanded or :nested or :compact or :compressed
-output_style = :compressed
-
-# To enable relative paths to assets via compass helper functions. Uncomment:
-# relative_assets = true
-
-# To disable debugging comments that display the original location of your selectors. Uncomment:
-line_comments = false
-
-
-# If you prefer the indented syntax, you might want to regenerate this
-# project again passing --syntax sass, or you can uncomment this:
-# preferred_syntax = :sass
-# and then run:
-# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
diff --git a/assets/css/modal.css b/assets/css/modal.css
new file mode 100644
index 00000000..e5df3aa4
--- /dev/null
+++ b/assets/css/modal.css
@@ -0,0 +1 @@
+#as3cf-overlay{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,0.5);overflow:hidden;overflow-y:auto;z-index:999999}#as3cf-modal{display:none;position:relative;width:600px;margin:100px auto;padding:30px;background-color:#eee;box-shadow:0 0 10px rgba(0,0,0,0.5);font-size:14px;overflow:hidden;z-index:100000}#as3cf-modal .close-as3cf-modal{color:#999;cursor:pointer;font-family:"Times New Roman", serif;font-size:26px;font-weight:200;position:absolute;right:18px;top:18px}#as3cf-modal .close-as3cf-modal:hover{color:#666}#as3cf-modal h3{margin:0 0 20px;font-weight:normal;line-height:1}#as3cf-modal .error,#as3cf-modal .notice,#as3cf-modal .updated{margin:0 0 20px}#as3cf-modal .actions{margin:20px -30px -30px;padding:20px 30px;border-top:none;background-color:#e3e3e3;overflow:hidden}#as3cf-modal .actions .right{margin-left:15px}#as3cf-modal .actions .right:last-of-type{margin-left:0}#as3cf-modal .actions button{min-width:90px}body.as3cf-modal-open{overflow:hidden;padding-right:15px}
diff --git a/assets/css/styles.css b/assets/css/styles.css
index 0892879b..172164ec 100644
--- a/assets/css/styles.css
+++ b/assets/css/styles.css
@@ -1 +1 @@
-.aws-main .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.aws-main .error pre code{padding:0;background:none}.aws-main .as3cf-notice,.aws-main .error{max-width:935px}.aws-main .updated{display:none}.aws-main .updated.as3cf-notice,.aws-main .updated.show{display:block}.as3cf-settings{position:relative;width:650px;min-height:800px}.as3cf-settings .as3cf-main-settings{display:none}.as3cf-settings .as3cf-main-settings p{font-size:13px}.as3cf-settings .as3cf-main-settings p a{color:#444}.as3cf-settings.as3cf-has-bucket .as3cf-bucket-select{display:none}.as3cf-settings.as3cf-has-bucket .as3cf-main-settings{display:block}.as3cf-settings .object-prefix-desc em{white-space:nowrap}.as3cf-settings .as3cf-url-preview-wrap{background:#ffffff;text-align:center;padding:20px 20px 10px;max-width:610px;width:100%}.as3cf-settings .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:5px;overflow-x:scroll;padding-bottom:15px}.as3cf-settings .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-settings .as3cf-ssl p.info{margin-top:10px;padding:0}.as3cf-settings .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-settings .as3cf-radio-group label.disabled,.as3cf-settings .as3cf-radio-group label.disabled p{color:#bbbbbb;cursor:default}.as3cf-settings .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-settings .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-settings .as3cf-switch{position:relative}.as3cf-settings .as3cf-switch.disabled span{cursor:default;margin:1px 0 0 0}.as3cf-settings .as3cf-switch.disabled span.checked{background:#F1F1F1;border:1px solid #dddddd;color:#a3a3a3}.as3cf-settings .as3cf-switch span{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;-webkit-border-radius:2px;font-weight:bold;padding:4px 8px;background:#F1F1F1;border:1px solid #dddddd;color:#CCCCCC;margin:1px -1px 0;z-index:1}.as3cf-settings .as3cf-switch span.checked{background:#ffffff;border-color:#E4E4E4;color:#373737;padding:5px 10px;margin:0;z-index:2}.as3cf-settings .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-settings .as3cf-setting.hide{display:none}.as3cf-settings .as3cf-bucket-actions{position:absolute;right:0;top:2px}.as3cf-settings .as3cf-bucket-actions .as3cf-cancel-bucket-select-wrap{display:none}.as3cf-settings .as3cf-bucket-actions .as3cf-cancel-bucket-select-wrap:after{content:" | "}.as3cf-settings .as3cf-bucket-select.manual .as3cf-manual-bucket-toggle,.as3cf-settings .as3cf-bucket-select.manual .as3cf-refresh-buckets,.as3cf-settings .as3cf-bucket-select.manual .as3cf-bucket-list-wrapper{display:none}.as3cf-settings .as3cf-bucket-select.manual .as3cf-bucket-list-toggle,.as3cf-settings .as3cf-bucket-select.manual .as3cf-manual-save-bucket-wrapper{display:block}.as3cf-settings .as3cf-bucket-select.manual .as3cf-cancel-bucket-select-wrap:after{content:""}.as3cf-settings .as3cf-bucket-select .as3cf-manual-bucket-toggle,.as3cf-settings .as3cf-bucket-select .as3cf-bucket-list-wrapper{display:block}.as3cf-settings .as3cf-bucket-select .as3cf-refresh-buckets{display:inline}.as3cf-settings .as3cf-bucket-select .as3cf-bucket-list-toggle,.as3cf-settings .as3cf-bucket-select .as3cf-manual-save-bucket-wrapper{display:none}.as3cf-settings .as3cf-bucket-list-wrapper{background:#fff;padding:15px 20px;margin-bottom:2em}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list{max-height:300px;overflow:auto;margin:0}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list li{font-size:14px;padding:10px 0}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a:hover,.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a.selected{color:#0074A2}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a.selected{font-weight:bold}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a .bucket{float:left;clear:both}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a .bucket .dashicons{margin-right:5px}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a .spinner{float:left;background-size:15px 15px}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list.saving{opacity:0.5}.as3cf-settings input[type="text"].as3cf-bucket-name{width:80%}.as3cf-settings select.bucket{margin-bottom:5px;width:380px}.as3cf-settings .form-table td{padding-left:0;padding-right:0}.as3cf-settings .form-table td:first-child{vertical-align:top;min-width:120px}.as3cf-settings .form-table h3{font-weight:normal;text-transform:uppercase;margin:0}.as3cf-settings .form-table h4{margin:0}.as3cf-settings .form-table .as3cf-border-bottom td{border-bottom:1px solid #ddd}.as3cf-settings .as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-settings .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-settings .tooltip:before,.as3cf-settings .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-settings .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-settings .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-settings .tooltip:hover:before,.as3cf-settings .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-banner img{display:block}.as3cf-sidebar{position:absolute;top:17px;right:-312px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe ul{margin-left:20px;list-style-type:disc}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.as3cf-sidebar .as3cf-banner{background-image:url(../img/snail@2x.jpg);background-size:292px 165px;width:292px;height:165px;display:block}.as3cf-sidebar .as3cf-banner img{display:none}}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto;margin-top:50px}}
+.aws-main.wrap>h2{float:left}.aws-main.wrap .as3cf-notice,.aws-main.wrap .as3cf-updated,.aws-main.wrap .as3cf-error{margin-bottom:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.aws-main.wrap .as3cf-error.fatal{clear:both;float:left}.aws-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:0;width:650px;margin-top:10px;padding-left:5px;padding-right:0}.aws-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.aws-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.aws-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.aws-main.wrap .error pre code{padding:0;background:none}.aws-main.wrap[data-tab="support"] .as3cf-notice,.aws-main.wrap[data-tab="support"] .error,.aws-main.wrap[data-tab="support"] .updated,.aws-main.wrap[data-tab="support"] .updated.show{display:none}.aws-main.wrap[data-tab="support"] .fatal .error,.aws-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.aws-main.wrap .as3cf-notice,.aws-main.wrap .error,.aws-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.aws-main.wrap .as3cf-updated{display:none}.aws-main.wrap .as3cf-updated.as3cf-notice,.aws-main.wrap .as3cf-updated.show{display:block}.as3cf-tab .as3cf-main-settings{display:none}.as3cf-tab .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-main-settings{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-bucket-container{display:none}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-ssl p.info{margin-top:10px;padding:0}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbbbbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;-webkit-border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;-webkit-border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab h3{font-weight:normal;text-transform:uppercase;margin:15px 0}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}#tab-media{display:block}#tab-media .as3cf-main-settings{display:none}#tab-media .as3cf-bucket-container{display:block}#tab-media.as3cf-has-bucket .as3cf-main-settings{display:block}#tab-media.as3cf-has-bucket .as3cf-bucket-container{display:none}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{box-sizing:border-box;width:100%}.as3cf-bucket-container select{box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .as3cf-invalid-bucket-name{font-size:12px;color:#a00}.as3cf-bucket-container .bucket-actions{margin:15px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-bucket-container .bucket-actions button,.as3cf-bucket-container .bucket-actions .right{float:right;margin-right:0}.as3cf-bucket-container .bucket-actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-bucket-container .bucket-actions .bucket-action-cancel{color:#a00;text-decoration:none}.as3cf-bucket-container .bucket-actions .bucket-action-cancel:hover{color:red}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074A2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074A2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}.as3cf-bucket-container .as3cf-bucket-select,.as3cf-bucket-container .as3cf-bucket-create{display:none}.as3cf-bucket-container .bucket-actions.select{display:none}.as3cf-tab{display:none}#tab-media{display:block}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:25px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe ul{margin-left:20px;list-style-type:disc}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.as3cf-sidebar .as3cf-banner{background-image:url(../img/snail@2x.jpg);background-size:292px 165px;width:292px;height:165px;display:block}.as3cf-sidebar .as3cf-banner img{display:none}}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto;margin-top:50px}}.as3cf-banner img{display:block}.aws-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}
diff --git a/assets/js/modal.js b/assets/js/modal.js
new file mode 100644
index 00000000..fbb800bf
--- /dev/null
+++ b/assets/js/modal.js
@@ -0,0 +1,199 @@
+var as3cfModal = (function ( $ ) {
+
+ var modal = {
+ prefix: 'as3cf'
+ };
+
+ var modals = {};
+
+ /**
+ * Target to key
+ *
+ * @param string target
+ *
+ * @return string
+ */
+ function targetToKey( target ) {
+ return target.replace( /[^a-z]/g, '' );
+ }
+
+ /**
+ * Open modal
+ *
+ * @param string target
+ * @param function callback
+ */
+ modal.open = function ( target, callback ) {
+ var key = targetToKey( target );
+
+ // Overlay
+ $( 'body' ).append( '
', $error_msg );
- }
-}
\ No newline at end of file
diff --git a/classes/as3cf-plugin-compatibility.php b/classes/as3cf-plugin-compatibility.php
new file mode 100644
index 00000000..bbb4f054
--- /dev/null
+++ b/classes/as3cf-plugin-compatibility.php
@@ -0,0 +1,229 @@
+as3cf = $as3cf;
+
+ $this->compatibility_init();
+ }
+
+ /**
+ * Register the compatibility hooks
+ */
+ function compatibility_init() {
+ /*
+ * WP_Image_Editor
+ * /wp-includes/class-wp-image-editor.php
+ */
+ add_action( 'as3cf_upload_attachment_pre_remove', array( $this, 'image_editor_remove_files' ), 10, 4 );
+ add_filter( 'as3cf_get_attached_file', array( $this, 'image_editor_download_file' ), 10, 4 );
+
+ /*
+ * WP_Customize_Control
+ * /wp-includes/class-wp-customize_control.php
+ */
+ add_filter( 'attachment_url_to_postid', array( $this, 'customizer_background_image' ), 10, 2 );
+
+ /*
+ * Regenerate Thumbnails
+ * https://wordpress.org/plugins/regenerate-thumbnails/
+ */
+ add_filter( 'as3cf_get_attached_file', array( $this, 'regenerate_thumbnails_download_file' ), 10, 4 );
+ }
+
+ /**
+ * Allow the WordPress Image Editor to remove edited version of images
+ * if the original image is being restored and 'IMAGE_EDIT_OVERWRITE' is set
+ *
+ * @param int $post_id
+ * @param array $s3object
+ * @param string $prefix
+ * @param array $args
+ */
+ function image_editor_remove_files( $post_id, $s3object, $prefix, $args ) {
+ if ( isset( $_POST['do'] ) && 'restore' == $_POST['do'] && defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
+ $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
+ $this->as3cf->remove_attachment_files_from_s3( $post_id, $s3object, $meta['file'] );
+ }
+ }
+
+ /**
+ * Allow the WordPress Image Editor to edit files that have been copied to S3
+ * but removed from the local server, by copying them back temporarily
+ *
+ * @param string $url
+ * @param string $file
+ * @param int $attachment_id
+ * @param array $s3_object
+ *
+ * @return string
+ */
+ function image_editor_download_file( $url, $file, $attachment_id, $s3_object ) {
+ if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
+ return $url;
+ }
+
+ // When the image-editor restores the original it requests the edited image,
+ // but we actually need to copy back the original image at this point
+ // for the restore to be successful and edited images to be deleted from S3
+ // via image_editor_remove_files()
+ if ( isset( $_POST['do'] ) && 'restore' == $_POST['do'] ) {
+ $backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
+ $original_filename = $backup_sizes['full-orig']['file'];
+
+ $orig_s3 = $s3_object;
+ $orig_s3['key'] = dirname( $s3_object['key'] ) . '/' . $original_filename;
+ $orig_file = dirname( $file ) . '/' . $original_filename;
+
+ // Copy the original file back to the server for the restore process
+ $this->copy_s3_file_to_server( $orig_s3, $orig_file );
+
+ // Copy the edited file back to the server as well, it will be cleaned up later
+ if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
+ // Return the file if successfully downloaded from S3
+ return $file;
+ };
+ }
+
+ // must be the image-editor process
+ if ( isset( $_POST['action'] ) && 'image-editor' == sanitize_key( $_POST['action'] ) ) { // input var okay
+ $callers = debug_backtrace();
+ foreach ( $callers as $caller ) {
+ if ( isset( $caller['function'] ) && '_load_image_to_edit_path' == $caller['function'] ) {
+ // check this has been called by '_load_image_to_edit_path' so as only to copy back once
+ if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
+ // Return the file if successfully downloaded from S3
+ return $file;
+ };
+ }
+ }
+ }
+
+ return $url;
+ }
+
+ /**
+ * Show the correct background image in the customizer
+ *
+ * @param int|null $post_id
+ * @param string $url
+ *
+ * @return int|null
+ */
+ function customizer_background_image( $post_id, $url ) {
+ if ( ! is_null( $post_id ) ) {
+ return $post_id;
+ }
+ $url = parse_url( $url );
+
+ if ( ! isset( $url['path'] ) ) {
+ return $post_id; // URL path can't be determined
+ }
+
+ $key1 = ltrim( $url['path'], '/' );
+ $length1 = strlen( $key1 );
+
+ // URLs may contain the bucket name within the path, therefore we must
+ // also perform the search with the first path segment removed
+ $parts = explode( '/', $key1 );
+ unset( $parts[0] );
+
+ $key2 = implode( '/', $parts );
+ $length2 = strlen( $key2 );
+
+ global $wpdb;
+ $sql = "
+ SELECT `post_id`
+ FROM `{$wpdb->prefix}postmeta`
+ WHERE `{$wpdb->prefix}postmeta`.`meta_key` = 'amazonS3_info'
+ AND ( `{$wpdb->prefix}postmeta`.`meta_value` LIKE '%s:3:\"key\";s:{$length1}:\"{$key1}\";%'
+ OR `{$wpdb->prefix}postmeta`.`meta_value` LIKE '%s:3:\"key\";s:{$length2}:\"{$key2}\";%' )
+ ";
+
+ if ( $id = $wpdb->get_var( $sql ) ) {
+ return $id;
+ }
+
+ return $post_id; // No attachment found on S3
+ }
+
+ /**
+ * Allow the Regenerate Thumbnails plugin to copy the S3 file back to the local
+ * server when the file is missing on the server via get_attached_file
+ *
+ * @param string $url
+ * @param string $file
+ * @param int $attachment_id
+ * @param array $s3_object
+ *
+ * @return string
+ */
+ function regenerate_thumbnails_download_file( $url, $file, $attachment_id, $s3_object ) {
+ if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
+ return $url;
+ }
+
+ if ( isset( $_POST['action'] ) && 'regeneratethumbnail' == sanitize_key( $_POST['action'] ) ) { // input var okay
+ if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
+ // Return the file if successfully downloaded from S3
+ return $file;
+ };
+ }
+
+ return $url;
+ }
+
+ /**
+ * Download a file from S3 if the file does not exist locally and places it where
+ * the attachment's file should be.
+ *
+ * @param array $s3_object
+ * @param string $file
+ *
+ * @return string|bool File if downloaded, false on failure
+ */
+ protected function copy_s3_file_to_server( $s3_object, $file ) {
+ try {
+ $this->as3cf->get_s3client( $s3_object['region'], true )->getObject(
+ array(
+ 'Bucket' => $s3_object['bucket'],
+ 'Key' => $s3_object['key'],
+ 'SaveAs' => $file,
+ )
+ );
+ } catch ( Exception $e ) {
+ error_log( sprintf( __( 'There was an error attempting to download the file %s from S3: %s', 'as3cf' ), $s3_object['key'], $e->getMessage() ) );
+
+ return false;
+ }
+
+ return $file;
+ }
+}
\ No newline at end of file
diff --git a/classes/as3cf-upgrade.php b/classes/as3cf-upgrade.php
index fc72e251..ccca87b5 100644
--- a/classes/as3cf-upgrade.php
+++ b/classes/as3cf-upgrade.php
@@ -77,24 +77,33 @@ function maybe_init_upgrade() {
return;
}
+ // Do we actually have S3 meta data without regions to update?
+ // No need to bother for fresh sites, or media not uploaded to S3
+ if ( 0 == $this->count_all_attachments_without_region() ) {
+ $this->as3cf->set_setting( 'post_meta_version', 1 );
+ $this->as3cf->save_settings();
+
+ return;
+ }
+
// Initialize the upgrade
$this->save_session( array( 'status' => self::STATUS_RUNNING ) );
- $this->schedule_event();
+ $this->as3cf->schedule_event( self::CRON_HOOK, self::CRON_SCHEDULE_KEY );
}
/**
* Adds notices about issues with upgrades allowing user to restart them
*/
function maybe_display_notices() {
- $action_url = self_admin_url( 'admin.php?page=' . $this->as3cf->get_plugin_slug() . '&action=restart_update_meta_with_region' );
- $msg_type = 'notice';
+ $action_url = $this->as3cf->get_plugin_page_url( array( 'action' => 'restart_update_meta_with_region' ), 'self' );
+ $msg_type = 'notice-info';
switch ( $this->get_upgrade_status() ) {
case self::STATUS_RUNNING :
$msg = sprintf( __( 'Running Metadata Update — We’re going through all the Media Library items uploaded to S3 and updating the metadata with the bucket region it is served from. This will allow us to serve your files from the proper S3 region subdomain (e.g. s3-us-west-2.amazonaws.com). This will be done quietly in the background, processing a small batch of Media Library items every %d minutes. There should be no noticeable impact on your server’s performance.', 'as3cf' ), $this->cron_interval_in_minutes );
$action_text = __( 'Pause Update', 'as3cf' );
- $action_url = self_admin_url( 'admin.php?page=' . $this->as3cf->get_plugin_slug() . '&action=pause_update_meta_with_region' );
+ $action_url = $this->as3cf->get_plugin_page_url( array( 'action' => 'pause_update_meta_with_region' ), 'self' );
break;
case self::STATUS_PAUSED :
$msg = __( 'Metadata Update Paused — Updating Media Library metadata has been paused.', 'as3cf' );
@@ -111,7 +120,12 @@ function maybe_display_notices() {
$msg .= ' ' . $action_text . '';
- $this->as3cf->render_view( $msg_type, array( 'message' => $msg ) );
+ $args = array(
+ 'message' => $msg,
+ 'type' => $msg_type,
+ );
+
+ $this->as3cf->render_view( 'notice', $args );
}
function maybe_handle_action() {
@@ -130,7 +144,7 @@ function maybe_handle_action() {
*/
function action_restart_update_meta_with_region() {
$this->change_status_request( self::STATUS_RUNNING );
- $this->schedule_event();
+ $this->as3cf->schedule_event( self::CRON_HOOK, self::CRON_SCHEDULE_KEY );
}
/**
@@ -151,7 +165,8 @@ function change_status_request( $status ) {
$session['status'] = $status;
$this->save_session( $session );
- wp_redirect( self_admin_url( 'admin.php?page=' . $this->as3cf->get_plugin_slug() ) );
+ $url = $this->as3cf->get_plugin_page_url( array(), 'self' );
+ wp_redirect( $url );
}
/**
@@ -170,63 +185,29 @@ function cron_schedules( $schedules ) {
return $schedules;
}
-
- /**
- * Wrapper for scheduling the cron job
- */
- function schedule_event() {
- if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
- wp_schedule_event( current_time( 'timestamp' ), self::CRON_SCHEDULE_KEY, self::CRON_HOOK );
- }
- }
-
- /**
- * Wrapper for clearing scheduled events for a specific cron job
- */
- function clear_scheduled_event() {
- $timestamp = wp_next_scheduled( self::CRON_HOOK );
- if ( $timestamp ) {
- wp_unschedule_event( $timestamp, self::CRON_HOOK );
- }
- }
-
+
/**
* Cron jon to update the region of the bucket in s3 metadata
*/
function cron_update_meta_with_region() {
// Check if the cron should even be running
if ( $this->as3cf->get_setting( 'post_meta_version', 0 ) > 0 || $this->get_upgrade_status() != self::STATUS_RUNNING ) {
- $this->clear_scheduled_event();
+ $this->as3cf->clear_scheduled_event( self::CRON_HOOK );
return;
}
- global $wpdb;
- $prefix = $wpdb->prefix;
-
// set the batch size limit for the query
$limit = apply_filters( 'as3cf_update_meta_with_region_batch_size', 500 );
$all_limit = $limit;
- $table_prefixes = array();
$session = $this->get_session();
// find the blog IDs that have been processed so we can skip them
$processed_blog_ids = isset( $session['processed_blog_ids'] ) ? $session['processed_blog_ids'] : array();
$error_count = isset( $session['error_count'] ) ? $session['error_count'] : 0;
- if ( ! in_array( 1, $processed_blog_ids ) ) {
- $table_prefixes[1] = $prefix;
- }
-
- if ( is_multisite() ) {
- $blog_ids = $this->as3cf->get_blog_ids();
- foreach ( $blog_ids as $blog_id ) {
- if ( in_array( $blog_id, $processed_blog_ids ) ) {
- continue;
- }
- $table_prefixes[ $blog_id ] = $prefix . $blog_id . '_';
- }
- }
+ // get the table prefixes for all the blogs
+ $table_prefixes = $this->get_all_blog_table_prefixes( $processed_blog_ids );
$all_attachments = array();
$all_count = 0;
@@ -254,7 +235,7 @@ function cron_update_meta_with_region() {
$this->as3cf->set_setting( 'post_meta_version', 1 );
$this->as3cf->remove_setting( 'update_meta_with_region_session' );
$this->as3cf->save_settings();
- $this->clear_scheduled_event();
+ $this->as3cf->clear_scheduled_event( self::CRON_HOOK );
return;
}
@@ -268,7 +249,7 @@ function cron_update_meta_with_region() {
// loop through and update s3 meta with region
foreach ( $all_attachments as $blog_id => $attachments ) {
- if ( 1 != $blog_id && is_multisite() ) {
+ if ( is_multisite() && ! $this->as3cf->is_current_blog( $blog_id ) ) {
switch_to_blog( $blog_id );
}
@@ -299,7 +280,7 @@ function cron_update_meta_with_region() {
}
}
- if ( 1 != $blog_id && is_multisite() ) {
+ if ( is_multisite() && ! $this->as3cf->is_current_blog( $blog_id ) ) {
restore_current_blog();
}
}
@@ -310,7 +291,26 @@ function cron_update_meta_with_region() {
$this->save_session( $session );
}
- /*
+ /**
+ * Get a count of all attachments without region in their S3 metadata
+ * for the whole site
+ *
+ * @return int
+ */
+ function count_all_attachments_without_region() {
+ // get the table prefixes for all the blogs
+ $table_prefixes = $this->get_all_blog_table_prefixes();
+ $all_count = 0;
+
+ foreach ( $table_prefixes as $blog_id => $table_prefix ) {
+ $count = $this->count_attachments_without_region( $table_prefix );
+ $all_count += $count;
+ }
+
+ return $all_count;
+ }
+
+ /**
* Get the current status of the upgrade
* See STATUS_* constants in the class declaration above.
*/
@@ -324,7 +324,7 @@ function get_upgrade_status() {
return $session['status'];
}
- /*
+ /**
* Retrieve session data from plugin settings
*
* @return array
@@ -333,7 +333,7 @@ function get_session() {
return $this->as3cf->get_setting( 'update_meta_with_region_session', array() );
}
- /*
+ /**
* Store data to be used between requests in plugin settings
*
* @param $session array of session data to store
@@ -344,23 +344,90 @@ function save_session( $session ) {
}
/**
- * Get all attachments that don't have region in their S3 meta
+ * Get all the table prefixes for the blogs in the site. MS compatible
*
- * @param unknown $prefix
- * @param unknown $limit
+ * @param array $exclude_blog_ids blog ids to exclude
+ *
+ * @return array associative array with blog ID as key, prefix as value
+ */
+ function get_all_blog_table_prefixes( $exclude_blog_ids = array() ) {
+ global $wpdb;
+ $prefix = $wpdb->prefix;
+
+ $table_prefixes = array();
+
+ if ( ! in_array( 1, $exclude_blog_ids ) ) {
+ $table_prefixes[1] = $prefix;
+ }
+
+ if ( is_multisite() ) {
+ $blog_ids = $this->as3cf->get_blog_ids();
+ foreach ( $blog_ids as $blog_id ) {
+ if ( in_array( $blog_id, $exclude_blog_ids ) ) {
+ continue;
+ }
+ $table_prefixes[ $blog_id ] = $wpdb->get_blog_prefix( $blog_id );
+ }
+ }
+
+ return $table_prefixes;
+ }
+
+ /**
+ * Get all attachments that don't have region in their S3 meta data for a blog
+ *
+ * @param string $prefix
+ * @param int $limit
*
* @return mixed
*/
function get_attachments_without_region( $prefix, $limit ) {
+ $attachments = $this->get_attachments_without_region_results( $prefix, false, $limit );
+
+ return $attachments;
+ }
+
+ /**
+ * Get a count of attachments that don't have region in their S3 meta data for a blog
+ * @param $prefix
+ *
+ * @return int
+ */
+ function count_attachments_without_region( $prefix ) {
+ $count = $this->get_attachments_without_region_results( $prefix, true );
+
+ return $count;
+ }
+
+ /**
+ * Wrapper for database call to get attachments without region
+ *
+ * @param string $prefix
+ * @param bool $count return count of attachments
+ * @param null|int $limit
+ *
+ * @return mixed
+ */
+ function get_attachments_without_region_results( $prefix, $count = false, $limit = null ) {
global $wpdb;
- $sql = $wpdb->prepare(
- "SELECT `post_id` as `ID`, `meta_value` AS 's3object'
- FROM `{$prefix}postmeta`
+
+ $sql = " FROM `{$prefix}postmeta`
WHERE `meta_key` = 'amazonS3_info'
- AND `meta_value` NOT LIKE '%%\"region\"%%'
- LIMIT %d",
- $limit
- );
+ AND `meta_value` NOT LIKE '%%\"region\"%%'";
+
+ if ( $count ) {
+ $sql = 'SELECT COUNT(*)' . $sql;
+
+ return $wpdb->get_var( $sql );
+ }
+
+ $sql = "SELECT `post_id` as `ID`, `meta_value` AS 's3object'" . $sql;
+
+ if ( ! is_null( $limit ) ) {
+ $sql .= ' LIMIT %d';
+
+ $sql = $wpdb->prepare( $sql, $limit );
+ }
return $wpdb->get_results( $sql, OBJECT );
}
diff --git a/classes/wp-aws-compatibility-check.php b/classes/wp-aws-compatibility-check.php
new file mode 100644
index 00000000..4dd8f449
--- /dev/null
+++ b/classes/wp-aws-compatibility-check.php
@@ -0,0 +1,424 @@
+plugin_name = $plugin_name;
+ $this->plugin_slug = $plugin_slug;
+ $this->plugin_file_path = $plugin_file_path;
+ $this->parent_plugin_name = $parent_plugin_name;
+ $this->parent_plugin_slug = $parent_plugin_slug;
+ $this->parent_plugin_required_version = $parent_plugin_required_version;
+ $this->parent_plugin_filename = $parent_plugin_filename;
+ $this->deactivate_if_not_compatible = $deactivate_if_not_compatible;
+ $this->parent_plugin_url = $parent_plugin_url;
+
+ add_action( 'admin_notices', array( $this, 'hook_admin_notices' ) );
+ add_action( 'network_admin_notices', array( $this, 'hook_admin_notices' ) );
+ }
+
+ /**
+ * Is the plugin compatible?
+ *
+ * @return bool
+ */
+ function is_compatible() {
+ $compatible = $this->get_error_msg() ? false : true;
+
+ $GLOBALS['aws_meta'][ $this->plugin_slug ]['compatible'] = $compatible;
+
+ return $compatible;
+ }
+
+ /**
+ * Get the basename for the plugin
+ *
+ * @return string
+ */
+ function get_plugin_basename() {
+ return plugin_basename( $this->plugin_file_path );
+ }
+
+ /**
+ * Get the name of the parent plugin
+ *
+ * @return string
+ */
+ function get_parent_plugin_name() {
+ if ( $this->parent_plugin_name ) {
+ return $this->parent_plugin_name;
+ }
+
+ return '';
+ }
+
+ /**
+ * Get the class of the parent plugin
+ *
+ * @return mixed|string
+ */
+ function get_parent_plugin_class() {
+ if ( $this->parent_plugin_slug ) {
+ $class = ucwords( str_replace( '-', ' ', $this->parent_plugin_slug ) );
+
+ return str_replace( ' ', '_', $class );
+ }
+
+ return '';
+ }
+
+ /**
+ * Get the filename of the main parent plugin file
+ *
+ * @return string
+ */
+ function get_parent_plugin_filename() {
+ if ( ! is_null( $this->parent_plugin_slug ) ) {
+ $filename = $this->parent_plugin_slug;
+ if ( ! is_null( $this->parent_plugin_filename ) ) {
+ $filename = basename( $this->parent_plugin_filename, '.php' );
+ }
+
+ return $filename . '.php';
+ }
+
+ return '';
+ }
+
+ /**
+ * Get the basename of the parent plugin {slug}/{slug}.php
+ *
+ * @return string
+ */
+ function get_parent_plugin_basename() {
+ if ( ! is_null( $this->parent_plugin_slug ) ) {
+ $file_name = $this->get_parent_plugin_filename();
+
+ return $this->parent_plugin_slug . '/' . $file_name;
+ }
+
+ return '';
+ }
+
+ /**
+ * Get the URL for the parent plugin. Defaults to a wordpress.org URL.
+ *
+ * @return null|string
+ */
+ function get_parent_plugin_url() {
+ if ( ! is_null( $this->parent_plugin_slug ) ) {
+ $url = 'http://wordpress.org/extend/plugins/' . $this->parent_plugin_slug . '/';
+ if ( ! is_null( $this->parent_plugin_url ) ) {
+ $url = $this->parent_plugin_url;
+ }
+
+ return $url;
+ }
+
+ return '';
+ }
+
+ /**
+ * Generate a URL to perform core actions on for a plugin
+ *
+ * @param string $action Such as activate, deactivate, install, upgrade
+ * @param string|null $basename
+ *
+ * @return string
+ */
+ function get_plugin_action_url( $action, $basename = null ) {
+ if ( is_null( $basename ) ) {
+ $basename = $this->get_plugin_basename();
+ }
+
+ $nonce_action = $action . '-plugin_' . $basename;
+ $page = 'plugins';
+
+ if ( in_array( $action, array( 'upgrade', 'install' ) ) ) {
+ $page = 'update';
+ $action .= '-plugin';
+ }
+
+ $url = wp_nonce_url( network_admin_url( $page . '.php?action=' . $action . '&plugin=' . $basename ), $nonce_action );
+
+ return $url;
+ }
+
+ /**
+ * Set the error message to be returned for the admin notice
+ *
+ * @param string $message
+ *
+ * @return string
+ */
+ function set_error_msg( $message ) {
+ // Replace the space between the last two words with to prevent typographic widows
+ $message = preg_replace( '/\s([\w]+[.,!\:;\\"-?]{0,1})$/', ' \\1', $message, 1 );
+
+ $this->error_message = $message;
+
+ return $this->error_message;
+ }
+
+ /**
+ * Check if the parent plugin is active and enabled, ie. not disabled due to
+ * compatibility issues up the chain.
+ *
+ * @return bool
+ */
+ function is_parent_plugin_enabled() {
+ $class = $this->get_parent_plugin_class();
+ if ( ! class_exists( $class ) ) {
+ // Class not even loaded
+ return false;
+ }
+
+ // call_user_func overcomes parse errors on PHP versions < 5.3
+ if ( method_exists( $class, 'is_compatible' ) && ! call_user_func( array( $class, 'is_compatible' ) ) ) {
+ // The plugin is active but not compatible
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the compatibility error message
+ *
+ * @return string|void
+ */
+ function get_error_msg() {
+ if ( is_null( $this->parent_plugin_slug ) ) {
+ return false;
+ }
+
+ if ( ! is_null( $this->error_message ) ) {
+ return $this->error_message;
+ }
+
+ $plugin_basename = $this->get_plugin_basename();
+ $parent_basename = $this->get_parent_plugin_basename();
+ $parent_plugin_link_html = sprintf( '%s', $this->get_parent_plugin_url(), $this->get_parent_plugin_name() );
+
+ $deactivate_url = $this->get_plugin_action_url( 'deactivate', $plugin_basename );
+ $deactivate_link = sprintf( '%s', $deactivate_url, __( 'deactivate', 'as3cf' ) );
+ $hide_notice_msg = ' ' . sprintf( __( 'You can %s the %s plugin to get rid of this notice.', 'as3cf' ), $deactivate_link, $this->plugin_name ) . '';
+
+ if ( ! $this->is_parent_plugin_enabled() ) {
+ $msg = sprintf( __( '%s has been disabled as it requires the %s plugin.', 'as3cf' ), $this->plugin_name, $parent_plugin_link_html );
+
+ if ( file_exists( WP_PLUGIN_DIR . '/' . $parent_basename ) ) {
+ if ( isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['compatible'] ) && ! $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['compatible'] ) {
+ $msg = rtrim( $msg, '.' ) . ', ' . __( 'which is currently disabled.', 'as3cf' );
+ } else {
+ $msg .= ' ' . __( 'It appears to be installed already.', 'as3cf' );
+ $activate_url = $this->get_plugin_action_url( 'activate', $parent_basename );
+ $msg .= ' ' . _x( 'Activate it now.', 'Activate plugin', 'as3cf' ) . '';
+ }
+ } else {
+ $install_url = 'https://deliciousbrains.com/my-account/';
+ if ( is_null( $this->parent_plugin_url ) ) {
+ $install_url = $this->get_plugin_action_url( 'install', $this->parent_plugin_slug );
+ }
+ $msg .= ' ' . sprintf( __( 'Install and activate it.', 'as3cf' ), $install_url );
+ }
+
+ $msg .= $hide_notice_msg;
+
+ return $this->set_error_msg( $msg );
+ }
+
+ $current_parent_plugin_version = isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['version'] ) ? $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['version'] : 0;
+
+ if ( ! version_compare( $current_parent_plugin_version, $this->parent_plugin_required_version, '>=' ) ) {
+ $msg = sprintf( __( '%s has been disabled as it requires version %s or later of the %s plugin.', 'as3cf' ), $this->plugin_name, $this->parent_plugin_required_version, $parent_plugin_link_html );
+
+ if ( $current_parent_plugin_version ) {
+ $msg .= ' ' . sprintf( __( 'You currently have version %s installed.', 'as3cf' ), $current_parent_plugin_version );
+ }
+
+ global $as3cfpro;
+ if ( ! empty( $as3cfpro ) && $as3cfpro->get_plugin_slug() === $this->parent_plugin_slug ) {
+ // Don't show update link for addons of a licensed plugin where the license is invalid
+ if ( ! $as3cfpro->is_valid_licence() ) {
+ $msg .= ' ' . sprintf( __( 'A valid license for %s is required to update.', 'as3cf' ), $this->get_parent_plugin_name() );
+ $msg .= $hide_notice_msg;
+
+ return $this->set_error_msg( $msg );
+ }
+ }
+
+ $update_url = $this->get_plugin_action_url( 'upgrade', $parent_basename );
+ $msg .= ' ' . __( 'Update to the latest version', 'as3cf' ) . '';
+
+ $msg .= $hide_notice_msg;
+
+ return $this->set_error_msg( $msg );
+ }
+
+ if ( ! isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['supported_addon_versions'] ) ) {
+ return false;
+ }
+
+ if ( ! isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['supported_addon_versions'][ $this->plugin_slug ] ) ) {
+ $msg = sprintf( __( '%1$s has been disabled because it is not a supported addon of the %2$s plugin.', 'as3cf' ), $this->plugin_name, $this->get_parent_plugin_name() );
+
+ return $this->set_error_msg( $msg );
+ }
+
+ $this_plugin_version_required = $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['supported_addon_versions'][ $this->plugin_slug ];
+ $this_plugin_version = $GLOBALS['aws_meta'][ $this->plugin_slug ]['version'];
+
+ if ( ! version_compare( $this_plugin_version, $this_plugin_version_required, '>=' ) ) {
+ $msg = sprintf( __( '%1$s has been disabled because it will not work with the version of the %2$s plugin installed. %1$s %3$s or later is required.', 'as3cf' ), $this->plugin_name, $this->get_parent_plugin_name(), $this_plugin_version_required );
+
+ $update_url = $this->get_plugin_action_url( 'upgrade', $plugin_basename );
+ $msg .= ' ' . sprintf( __( 'Update %s to the latest version', 'as3cf' ), $this->plugin_name ) . '';
+
+ $msg .= $hide_notice_msg;
+
+ return $this->set_error_msg( $msg );
+ }
+
+ return false;
+ }
+
+ /**
+ * Check plugin capabilities for a user
+ *
+ * @return bool
+ */
+ function check_capabilities() {
+ if ( is_multisite() ) {
+ if ( ! current_user_can( 'manage_network_plugins' ) ) {
+ return false; // Don't allow if the user can't manage network plugins
+ }
+ } else {
+ // Don't allow if user doesn't have plugin management privileges
+ $caps = array( 'activate_plugins', 'update_plugins', 'install_plugins' );
+ foreach ( $caps as $cap ) {
+ if ( ! current_user_can( $cap ) ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Display compatibility notices to users who can manage plugins
+ */
+ function hook_admin_notices() {
+ if ( ! $this->check_capabilities() ){
+ return;
+ }
+
+ $this->get_admin_notice();
+ }
+
+ /**
+ * Get the admin notice to be displayed
+ */
+ function get_admin_notice() {
+ $error_msg = $this->get_error_msg();
+
+ if ( ! $error_msg ) {
+ return;
+ }
+
+ if ( $this->deactivate_if_not_compatible ) {
+ $deactivated_msg = sprintf( __( 'The %s plugin has been deactivated.', 'as3cf' ), $this->plugin_name );
+
+ $error_msg = $deactivated_msg . ' ' . $error_msg;
+ $this->render_notice( $error_msg );
+
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
+ deactivate_plugins( $this->plugin_file_path );
+ } else {
+ $this->render_notice( $error_msg );
+ }
+ }
+
+ /**
+ * Render the notice HTML
+ *
+ * @param string $message
+ */
+ function render_notice( $message ) {
+ printf( '
%s
', $message );
+ }
+ }
+}
\ No newline at end of file
diff --git a/classes/wp-aws-uninstall.php b/classes/wp-aws-uninstall.php
new file mode 100644
index 00000000..8555ef4f
--- /dev/null
+++ b/classes/wp-aws-uninstall.php
@@ -0,0 +1,181 @@
+options = $options;
+ $this->postmeta = $postmeta;
+ $this->crons = $crons;
+ $this->transients = $transients;
+
+ $this->set_blog_ids();
+
+ $this->delete_options();
+ $this->delete_postmeta();
+ $this->clear_crons();
+ $this->delete_transients();
+ }
+
+ /**
+ * Set the blog id(s) for a site
+ */
+ private function set_blog_ids() {
+ $blog_ids[] = 1;
+ if ( function_exists( 'is_multisite' ) && is_multisite() ) {
+ $args = array(
+ 'limit' => false,
+ 'spam' => 0,
+ 'deleted' => 0,
+ 'archived' => 0,
+ );
+ $blogs = wp_get_sites( $args );
+ $blog_ids = wp_list_pluck( $blogs, 'blog_id' );
+ }
+
+ $this->blog_ids = $blog_ids;
+ }
+
+ /**
+ * Check and ensure a property has been filled with an array
+ *
+ * @param string $property
+ *
+ * @return bool
+ */
+ private function check_property( $property ) {
+ if ( empty( $this->$property ) ) {
+ return false;
+ }
+
+ if ( ! is_array( $this->$property ) ) {
+ // Convert any strings to an array
+ $this->$property = array( $this->$property );
+ }
+
+ return true;
+ }
+
+ /**
+ * Delete site wide options
+ */
+ public function delete_options() {
+ if ( ! $this->check_property( 'options' ) ) {
+ return;
+ }
+
+ foreach ( $this->options as $option ) {
+ delete_site_option( $option );
+ }
+ }
+
+ /**
+ * Delete post meta data for all blogs
+ */
+ public function delete_postmeta() {
+ if ( ! $this->check_property( 'postmeta' ) ) {
+ return;
+ }
+
+ global $wpdb;
+
+ foreach ( $this->blog_ids as $blog_id ) {
+ $prefix = $wpdb->get_blog_prefix( $blog_id );
+
+ foreach ( $this->postmeta as $postmeta ) {
+ $sql = $wpdb->prepare( "DELETE FROM {$prefix}postmeta WHERE meta_key = %s", $postmeta );
+ $wpdb->query( $sql );
+ }
+ }
+ }
+
+ /**
+ * Clear any scheduled cron jobs
+ */
+ public function clear_crons() {
+ if ( ! $this->check_property( 'crons' ) ) {
+ return;
+ }
+
+ foreach ( $this->crons as $cron ) {
+ $timestamp = wp_next_scheduled( $cron );
+ if ( $timestamp ) {
+ wp_unschedule_event( $timestamp, $cron );
+ }
+ }
+ }
+
+ /**
+ * Delete site wide transients
+ */
+ public function delete_transients() {
+ if ( ! $this->check_property( 'transients' ) ) {
+ return;
+ }
+
+ foreach ( $this->transients as $transient ) {
+ delete_site_transient( $transient );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/include/functions.php b/include/functions.php
index 9af9885e..6049df96 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -11,4 +11,4 @@ function as3cf_get_secure_attachment_url( $post_id, $expires = 900, $size = null
global $as3cf;
return $as3cf->get_secure_attachment_url( $post_id, $expires, $size );
-}
+}
\ No newline at end of file
diff --git a/languages/amazon-s3-and-cloudfront-en.pot b/languages/amazon-s3-and-cloudfront-en.pot
new file mode 100644
index 00000000..46d553a1
--- /dev/null
+++ b/languages/amazon-s3-and-cloudfront-en.pot
@@ -0,0 +1,580 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: amazon-s3-and-cloudfront\n"
+"Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
+"POT-Creation-Date: 2015-07-08 12:57-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:79
+msgid "Offload S3"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:80
+msgid "S3 and CloudFront"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:568
+#, php-format
+msgid "File %s does not exist"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:577
+#, php-format
+msgid "Mime type %s is not allowed"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:653
+#, php-format
+msgid "Error uploading %s to S3: %s"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1251
+msgid "Cheatin’ eh?"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1255
+msgid "You do not have sufficient permissions to access this page."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1261
+msgid "No bucket name provided."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1518
+#, php-format
+msgid "There was an error attempting to get the region of the bucket %s: %s"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1635
+msgid ""
+"This is a test file to check if the user has write permission to S3. Delete "
+"me if found."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1667
+#, php-format
+msgid ""
+"There was an error attempting to check the permissions of the bucket %s: %s"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1730
+msgid "Error creating bucket: "
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1731
+msgid "Bucket name too short."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1732
+msgid "Bucket name too long."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1733
+msgid ""
+"Invalid character. Bucket names can contain lowercase letters, numbers, "
+"periods and hyphens."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1734
+msgid "Error saving bucket: "
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1735
+msgid "Error fetching buckets: "
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1736
+msgid "Error getting URL preview: "
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1737
+msgid "The changes you made will be lost if you navigate away from this page"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1795
+msgid "Cheatin' eh?"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1898
+msgctxt "Show the media library tab"
+msgid "Media Library"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:1899
+msgctxt "Show the support tab"
+msgid "Support"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php:2035
+#, php-format
+msgid "The file %s has been given %s permissions on Amazon S3."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-plugin-compatibility.php:222
+#, php-format
+msgid "There was an error attempting to download the file %s from S3: %s"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:104
+#, php-format
+msgid ""
+"Running Metadata Update — We’re going through "
+"all the Media Library items uploaded to S3 and updating the metadata with "
+"the bucket region it is served from. This will allow us to serve your files "
+"from the proper S3 region subdomain (e."
+"g. s3-us-west-2.amazonaws.com). This will be done quietly in the "
+"background, processing a small batch of Media Library items every %d "
+"minutes. There should be no noticeable impact on your server’s "
+"performance."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:105
+msgid "Pause Update"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:109
+msgid ""
+"Metadata Update Paused — Updating Media Library "
+"metadata has been paused."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:110
+msgid "Restart Update"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:113
+msgid ""
+"Error Updating Metadata — We ran into some errors "
+"attempting to update the metadata for all your Media Library items that have "
+"been uploaded to S3. Please check your error log for details."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:114
+msgid "Try Run It Again"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/as3cf-upgrade.php:183
+#, php-format
+msgid "Every %d Minutes"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:276
+msgid "deactivate"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:277
+#, php-format
+msgid "You can %s the %s plugin to get rid of this notice."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:280
+#, php-format
+msgid "%s has been disabled as it requires the %s plugin."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:284
+msgid "which is currently disabled."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:286
+msgid "It appears to be installed already."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:288
+msgctxt "Activate plugin"
+msgid "Activate it now."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:295
+#, php-format
+msgid "Install and activate it."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:306
+#, php-format
+msgid ""
+"%s has been disabled as it requires version %s or later of the %s plugin."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:309
+#, php-format
+msgid "You currently have version %s installed."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:316
+#, php-format
+msgid "A valid license for %s is required to update."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:324
+msgid "Update to the latest version"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:336
+#, php-format
+msgid ""
+"%1$s has been disabled because it is not a supported addon of the %2$s "
+"plugin."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:345
+#, php-format
+msgid ""
+"%1$s has been disabled because it will not work with the version of the %2$s "
+"plugin installed. %1$s %3$s or later is required."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:348
+#, php-format
+msgid "Update %s to the latest version"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/classes/wp-aws-compatibility-check.php:403
+#, php-format
+msgid "The %s plugin has been deactivated."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:3
+msgid "Change bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:3
+msgid "What bucket would you like to use?"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:5
+msgid "Existing bucket name"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:7
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:12
+msgid "Saving..."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:7
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:12
+msgid "Save Bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:8
+msgid "Browse existing buckets"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:9
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:26
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:31
+msgid "Create new bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:13
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:21
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:61
+msgid "Cancel"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:18
+msgid "Select bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:19
+msgid "Loading..."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:22
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:27
+msgid "Refresh"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:25
+msgid "Enter bucket name"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:37
+msgid "Bucket Name:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:40
+msgid "Bucket Name"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:47
+msgid "Region:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:60
+msgid "Creating..."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-select.php:60
+msgid "Create New Bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-setting.php:7
+msgid "Bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/bucket-setting.php:11
+msgid "Change"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/debug-info.php:2
+msgid "Diagnostic Info"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/debug-info.php:11
+msgctxt "Download to your computer"
+msgid "Download"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/domain-setting.php:5
+msgid "Domain:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/domain-setting.php:23
+msgid "Bucket name as subdomain"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/domain-setting.php:28
+msgid "Bucket name in path"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/domain-setting.php:33
+msgid "Bucket name as domain"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/domain-setting.php:38
+msgid "CloudFront or custom domain"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/error-access.php:4
+msgid "Access Denied to Bucket"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/error-access.php:6
+#, php-format
+msgid ""
+"This could indicate your S3 policy is Read-Only. You need to go to Identity and Access Management in your AWS console and manage the "
+"policy for the user you're using for this plugin. Your policy should look "
+"something like the following:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:10
+msgid "Settings saved."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:44
+msgid "Enable/Disable the Plugin"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:51
+msgid "Copy Files to S3"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:52
+msgid ""
+"When a file is uploaded to the Media Library, copy it to S3. Existing files "
+"are not copied to S3."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:60
+msgid "Rewrite File URLs"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:61
+msgid ""
+"For Media Library files that have been copied to S3, rewrite the URLs so "
+"that they are served from S3/CloudFront instead of your server."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:65
+msgid "Configure File URLs"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:83
+msgid "Path"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:85
+msgid "By default the path is the same as your local WordPress files:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:98
+msgid "Year/Month"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:100
+msgid "Add the Year/Month in the URL."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:106
+msgid "SSL:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:114
+msgid "Same as request"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:115
+msgid "When the request is https://, use https:// for the file URL as well."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:119
+msgid "Always SSL"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:120
+msgid "Forces https:// to be used."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:121
+msgid ""
+"You cannot use the \"Bucket as a subdomain\" domain option when using SSL."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:125
+msgid "Always non-SSL"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:126
+msgid "Forces http:// to be used."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:132
+msgid "Advanced Options"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:139
+msgid "Remove Files From Server"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:140
+msgid "Once a file has been copied to S3, remove it from the local server."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:148
+msgid "Object Versioning"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:150
+msgid ""
+"Append a timestamp to the S3 file path. Recommended when using CloudFront so "
+"you don't have to worry about cache invalidation."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:152
+#: builds/amazon-s3-and-cloudfront/view/settings.php:165
+msgid "More info"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:162
+msgid "Far Future Expiration Header"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:163
+msgid ""
+"Implements a \"Never Expire\" caching policy for browsers by setting an "
+"Expires header for 10 years in the future. Should be used in conjunction "
+"with object versioning above."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:175
+msgid "Copy HiDPI (@2x) Images"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:176
+#, php-format
+msgid ""
+"When uploading a file to S3, checks if there's a file of the same name with "
+"an @2x suffix and copies it to S3 as well. Works with the WP "
+"Retina 2x plugin."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/settings.php:182
+msgid "Save Changes"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:6
+msgid "Pro Version?"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:11
+msgid ""
+"We're working on a pro version that will include the following features:"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:15
+msgid "Copy existing Media Library to S3"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:16
+msgid "Serve theme JS & CSS from S3/CloudFront"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:17
+msgid ""
+"WooCommerce & EDD integration"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:18
+msgid "Awesome email support"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:22
+msgid "Your Email"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:26
+msgid "First Name"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:30
+msgid "Last Name"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:37
+msgid "Send me news about a pro version"
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/sidebar.php:41
+msgid ""
+"We promise we will not use your email for anything else and you can "
+"unsubscribe with 1-click anytime."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/wordpress-org-support.php:2
+msgid "As this is a free plugin, we do not provide support."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/wordpress-org-support.php:4
+#, php-format
+msgid ""
+"You may ask the WordPress community for help by posting to the WordPress.org support forum. Response time can range from a few days "
+"to a few weeks and will likely be from a non-developer."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/wordpress-org-support.php:6
+#, php-format
+msgid ""
+"If you want a timely response via email from a developer "
+"who works on this plugin, upgrade and send us an email."
+msgstr ""
+
+#: builds/amazon-s3-and-cloudfront/view/wordpress-org-support.php:8
+#, php-format
+msgid ""
+"If you've found a bug, please submit an issue on GitHub."
+msgstr ""
diff --git a/languages/amazon-s3-and-cloudfront.pot b/languages/amazon-s3-and-cloudfront.pot
deleted file mode 100644
index 4afa8181..00000000
--- a/languages/amazon-s3-and-cloudfront.pot
+++ /dev/null
@@ -1,457 +0,0 @@
-msgid ""
-msgstr ""
-"Project-Id-Version: Amazon S3 and CloudFront\n"
-"POT-Creation-Date: 2015-01-29 12:40-0000\n"
-"PO-Revision-Date: 2015-01-29 12:40-0000\n"
-"Last-Translator: Delicious Brains \n"
-"Language-Team: Delicious Brains \n"
-"Language: en\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.7\n"
-"X-Poedit-Basepath: ..\n"
-"X-Poedit-SourceCharset: UTF-8\n"
-"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
-"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
-"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Poedit-SearchPath-0: .\n"
-"X-Poedit-SearchPathExcluded-0: vendor\n"
-"X-Poedit-SearchPathExcluded-1: assets\n"
-
-#: classes/amazon-s3-and-cloudfront.php:38
-msgid "Amazon S3 and CloudFront"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:39
-msgid "S3 and CloudFront"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:370
-#, php-format
-msgid "Mime type %s is not allowed"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:457
-#, php-format
-msgid "Error uploading %s to S3: %s"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:961
-msgid "There was an error attempting to access the file system"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1001
-msgid "Cheatin’ eh?"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1005
-msgid "You do not have sufficient permissions to access this page."
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1011
-msgid "No bucket name provided."
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1037
-#: classes/amazon-s3-and-cloudfront.php:1070
-#: classes/amazon-s3-and-cloudfront.php:1129
-msgid "Failed to retrieve bucket region."
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1179
-#, php-format
-msgid "There was an error attempting to get the region of the bucket %s: %s"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1291
-msgid ""
-"This is a test file to check if the user has write permission to S3. Delete "
-"me if found."
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1336
-msgid "Bucket Name:"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1337
-msgid "Error creating bucket: "
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1340
-msgid "Error fetching buckets: "
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1342
-msgid "Error saving bucket: "
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1345
-msgid "Error getting URL preview: "
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1346
-msgid "The changes you made will be lost if you navigate away from this page"
-msgstr ""
-
-#: classes/amazon-s3-and-cloudfront.php:1358
-msgid "Cheatin' eh?"
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:25
-msgid ""
-"You can deactivate the Amazon S3 and CloudFront plugin to get rid of this "
-"notice."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:28
-#, php-format
-msgid ""
-"Amazon S3 and CloudFront has been disabled as it requires the Amazon Web Services "
-"plugin."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:31
-msgid "It appears to be installed already."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:33
-msgctxt "Activate plugin"
-msgid "Activate it now"
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:37
-#, php-format
-msgid "Install it and activate."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:48
-#, php-format
-msgid ""
-"Amazon S3 and CloudFront has been disabled as it requires version %s or "
-"later of the Amazon "
-"Web Services plugin."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:51
-#, php-format
-msgid "You currently have version %s installed."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:55
-msgid "Update to the latest version"
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:66
-#, php-format
-msgid ""
-"Amazon S3 and CloudFront has been disabled because it will not work with the "
-"version of the Amazon Web Services plugin installed. Amazon "
-"S3 and CloudFront %s or later is required."
-msgstr ""
-
-#: classes/as3cf-compatibility-check.php:70
-msgid "Update Amazon S3 and CloudFront to the latest version"
-msgstr ""
-
-#: classes/as3cf-upgrade.php:95
-#, php-format
-msgid ""
-"Running Metadata Update — We’re going through "
-"all the Media Library items uploaded to S3 and updating the metadata with "
-"the bucket region it is served from. This will allow us to serve your files "
-"from the proper S3 region subdomain (e."
-"g. s3-us-west-2.amazonaws.com). This will be done quietly in the "
-"background, processing a small batch of Media Library items every %d "
-"minutes. There should be no noticeable impact on your server’s "
-"performance."
-msgstr ""
-
-#: classes/as3cf-upgrade.php:96
-msgid "Pause Update"
-msgstr ""
-
-#: classes/as3cf-upgrade.php:100
-msgid ""
-"Metadata Update Paused — Updating Media Library "
-"metadata has been paused."
-msgstr ""
-
-#: classes/as3cf-upgrade.php:101
-msgid "Restart Update"
-msgstr ""
-
-#: classes/as3cf-upgrade.php:104
-msgid ""
-"Error Updating Metadata — We ran into some errors "
-"attempting to update the metadata for all your Media Library items that have "
-"been uploaded to S3. Please check your error log for details."
-msgstr ""
-
-#: classes/as3cf-upgrade.php:105
-msgid "Try Run It Again"
-msgstr ""
-
-#: classes/as3cf-upgrade.php:168
-#, php-format
-msgid "Every %d Minutes"
-msgstr ""
-
-#: view/settings.php:19
-msgid "Settings saved."
-msgstr ""
-
-#: view/settings.php:35
-msgid "S3 Policy is Read-Only"
-msgstr ""
-
-#: view/settings.php:37
-#, php-format
-msgid ""
-"You need to go to Identity and Access Management in your "
-"AWS console and manage the policy for the user you're using for this plugin. "
-"Your policy should look something like the following:"
-msgstr ""
-
-#: view/settings.php:52
-msgid "Select an existing S3 bucket to use:"
-msgstr ""
-
-#: view/settings.php:55
-msgid "Cancel"
-msgstr ""
-
-#: view/settings.php:57
-msgid "Refresh"
-msgstr ""
-
-#: view/settings.php:60
-msgid ""
-"You can enter a bucket manually to avoid listing the buckets available. This "
-"can be helpful if you have an IAM policy that does not allow bucket listing "
-"or you have a large amount of buckets to load."
-msgstr ""
-
-#: view/settings.php:63
-msgid "Enter Bucket"
-msgstr ""
-
-#: view/settings.php:64
-msgid "Select Bucket"
-msgstr ""
-
-#: view/settings.php:68 view/settings.php:79
-msgid "Bucket Name"
-msgstr ""
-
-#: view/settings.php:69
-msgid "Saving..."
-msgstr ""
-
-#: view/settings.php:69
-msgid "Save"
-msgstr ""
-
-#: view/settings.php:73
-msgid "Loading..."
-msgstr ""
-
-#: view/settings.php:76
-msgid "Or create a new bucket:"
-msgstr ""
-
-#: view/settings.php:80
-msgid "Creating..."
-msgstr ""
-
-#: view/settings.php:80
-msgid "Create"
-msgstr ""
-
-#: view/settings.php:91
-msgid "Bucket"
-msgstr ""
-
-#: view/settings.php:95
-msgid "Change"
-msgstr ""
-
-#: view/settings.php:102
-msgid "Enable/Disable the Plugin"
-msgstr ""
-
-#: view/settings.php:109
-msgid "Copy Files to S3"
-msgstr ""
-
-#: view/settings.php:110
-msgid ""
-"When a file is uploaded to the Media Library, copy it to S3. Existing files "
-"are not copied to S3."
-msgstr ""
-
-#: view/settings.php:118
-msgid "Rewrite File URLs"
-msgstr ""
-
-#: view/settings.php:119
-msgid ""
-"For Media Library files that have been copied to S3, rewrite the URLs so "
-"that they are served from S3/CloudFront instead of your server."
-msgstr ""
-
-#: view/settings.php:123
-msgid "Configure File URLs"
-msgstr ""
-
-#: view/settings.php:137
-msgid "Domain:"
-msgstr ""
-
-#: view/settings.php:183
-msgid "Path"
-msgstr ""
-
-#: view/settings.php:185
-msgid "By default the path is the same as your local WordPress files:"
-msgstr ""
-
-#: view/settings.php:198
-msgid "Year/Month"
-msgstr ""
-
-#: view/settings.php:200
-msgid "Add the Year/Month in the URL."
-msgstr ""
-
-#: view/settings.php:206
-msgid "SSL"
-msgstr ""
-
-#: view/settings.php:214
-msgid "Same as request"
-msgstr ""
-
-#: view/settings.php:215
-msgid "When the request is https://, use https:// for the file URL as well."
-msgstr ""
-
-#: view/settings.php:219
-msgid "Always SSL"
-msgstr ""
-
-#: view/settings.php:220
-msgid "Forces https:// to be used."
-msgstr ""
-
-#: view/settings.php:221
-msgid ""
-"You cannot use the \"Bucket as a subdomain\" domain option when using SSL."
-msgstr ""
-
-#: view/settings.php:225
-msgid "Always non-SSL"
-msgstr ""
-
-#: view/settings.php:226
-msgid "Forces http:// to be used."
-msgstr ""
-
-#: view/settings.php:232
-msgid "Advanced Options"
-msgstr ""
-
-#: view/settings.php:239
-msgid "Remove Files From Server"
-msgstr ""
-
-#: view/settings.php:240
-msgid "Once a file has been copied to S3, remove it from the local server."
-msgstr ""
-
-#: view/settings.php:248
-msgid "Object Versioning"
-msgstr ""
-
-#: view/settings.php:250
-msgid ""
-"Append a timestamp to the S3 file path. Recommended when using CloudFront so "
-"you don't have to worry about cache invalidation."
-msgstr ""
-
-#: view/settings.php:252 view/settings.php:265
-msgid "More info"
-msgstr ""
-
-#: view/settings.php:262
-msgid "Far Future Expiration Header"
-msgstr ""
-
-#: view/settings.php:263
-msgid ""
-"Implements a \"Never Expire\" caching policy for browsers by setting an "
-"Expires header for 10 years in the future. Should be used in conjunction "
-"with object versioning above."
-msgstr ""
-
-#: view/settings.php:275
-msgid "Copy HiDPI (@2x) Images"
-msgstr ""
-
-#: view/settings.php:276
-#, php-format
-msgid ""
-"When uploading a file to S3, checks if there's a file of the same name with "
-"an @2x suffix and copies it to S3 as well. Works with the WP "
-"Retina 2x plugin."
-msgstr ""
-
-#: view/settings.php:282
-msgid "Save Changes"
-msgstr ""
-
-#: view/sidebar.php:6
-msgid "Pro Version?"
-msgstr ""
-
-#: view/sidebar.php:11
-msgid ""
-"We're working on a pro version that will include the following features:"
-msgstr ""
-
-#: view/sidebar.php:15
-msgid "Copy existing Media Library to S3"
-msgstr ""
-
-#: view/sidebar.php:16
-msgid "Serve theme JS & CSS from S3/CloudFront"
-msgstr ""
-
-#: view/sidebar.php:17
-msgid ""
-"WooCommerce & EDD integration"
-msgstr ""
-
-#: view/sidebar.php:18
-msgid "Awesome email support"
-msgstr ""
-
-#: view/sidebar.php:22
-msgid "Your Name"
-msgstr ""
-
-#: view/sidebar.php:26
-msgid "Your Email"
-msgstr ""
-
-#: view/sidebar.php:30
-msgid "Send me news about a pro version"
-msgstr ""
-
-#: view/sidebar.php:34
-msgid ""
-"We promise we will not use your email for anything else and you can "
-"unsubscribe with 1-click anytime."
-msgstr ""
diff --git a/readme.txt b/readme.txt
index 8dd543f5..3eae192b 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,10 +1,10 @@
-=== Amazon S3 and Cloudfront ===
+=== WP Offload S3 ===
Contributors: bradt
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC
Tags: uploads, amazon, s3, mirror, admin, media, cdn, cloudfront
Requires at least: 3.5
-Tested up to: 4.1
-Stable tag: 0.8.2
+Tested up to: 4.2.2
+Stable tag: 0.9
License: GPLv3
Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
@@ -59,6 +59,36 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
== Changelog ==
+= 0.9 - 2015-07-08 =
+* New: Plugin rebranded to WP Offload S3
+* New: Support tab added to _Offload S3_ screen containing diagnostic information
+* New: Compatibility with the [Media Replace](https://wordpress.org/plugins/enable-media-replace/) plugin
+* New: Select bucket region when creating a new bucket
+* New: Toggle switches redesigned
+* Improvement: Compatibility with release candidate of Pro plugin
+* Improvement: Example IAM policy more secure
+* Improvement: Set default bucket region using the `AS3CF_REGION` constant
+* Improvement: Added `as3cf_object_meta` filter for developers
+* Improvement: Bucket selection moved to modal window
+* Improvement: Don't allow bucket names to contain invalid characters on creation
+* Improvement: More verbose error messages on bucket selection
+* Improvement: Settings link added to plugin row on _Plugins_ screen
+* Improvement: Object versioning enabled by default
+* Improvement: Uninstall routines added
+* Improvement: JavaScript coding standards
+* Improvement: Cache result when checking S3 bucket permissions
+* Bug fix: Bucket region errors result in blank WP Offload S3 screen
+* Bug fix: Editing an image when _Remove Files From Server_ option is enabled results in error
+* Bug fix: Metadata upgrade procedure triggered on new installs
+* Bug fix: File URLs when uploaded to a subdirectory result in incorrect S3 URLs
+* Bug fix: Errors logged when trying to delete non-existent HiDPI images
+* Bug fix: SignatureDoesNotMatch errors on regions with v4 authentication
+* Bug fix: Customizer background image not editable
+* Bug fix: Error when creating buckets with US Standard region
+* Bug fix: Notices appearing incorrectly on some admin screens
+* Bug fix: Subsite upload paths repeated on multisite installs
+* Bug fix: Handle multisite installs where `BLOG_ID_CURRENT_SITE` is not 1
+
= 0.8.2 - 2015-01-31 =
* New: Input bucket in settings to avoid listing all buckets
* New: Specify bucket with 'AS3CF_BUCKET' constant
diff --git a/uninstall.php b/uninstall.php
new file mode 100644
index 00000000..126de7ff
--- /dev/null
+++ b/uninstall.php
@@ -0,0 +1,27 @@
+">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/view/bucket-setting.php b/view/bucket-setting.php
new file mode 100644
index 00000000..eba4e9f6
--- /dev/null
+++ b/view/bucket-setting.php
@@ -0,0 +1,28 @@
+
+
+
\ No newline at end of file
diff --git a/view/domain-setting.php b/view/domain-setting.php
new file mode 100644
index 00000000..3cdd9391
--- /dev/null
+++ b/view/domain-setting.php
@@ -0,0 +1,45 @@
+
+
\ No newline at end of file
diff --git a/view/error-access.php b/view/error-access.php
new file mode 100644
index 00000000..db27daa6
--- /dev/null
+++ b/view/error-access.php
@@ -0,0 +1,25 @@
+
+
+
+
+ —
+ Identity and Access Management in your AWS console and manage the policy for the user you\'re using for this plugin. Your policy should look something like the following:', 'as3cf' ), 'https://console.aws.amazon.com/iam/home' ); ?>
+
\ No newline at end of file
diff --git a/view/error-fatal.php b/view/error-fatal.php
index 40a1c28a..1db162fe 100644
--- a/view/error-fatal.php
+++ b/view/error-fatal.php
@@ -1,5 +1,5 @@
-
\ No newline at end of file
diff --git a/view/settings-tabs.php b/view/settings-tabs.php
new file mode 100644
index 00000000..f48f89ea
--- /dev/null
+++ b/view/settings-tabs.php
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/view/settings.php b/view/settings.php
index af45364a..c1f6bb46 100644
--- a/view/settings.php
+++ b/view/settings.php
@@ -1,104 +1,46 @@
get_setting( 'bucket' ); ?>
-
-
-
-
-
-
-
-
-
-
+$prefix = $this->get_plugin_prefix_slug();
+?>
+
+
+
+
+
+get_setting( 'bucket' ); ?>
+
+
-
+
+
check_write_permission();
- // catch any file system issues
-if ( is_wp_error( $can_write ) ) {
- $this->render_view( 'error-fatal', array( 'message' => $can_write->get_error_message() ) );
- $can_write = true;
-}
-// display a error message if the user does not have write permission to S3
-?>
-
-
-
-
- —
- Identity and Access Management in your AWS console and manage the policy for the user you\'re using for this plugin. Your policy should look something like the following:', 'as3cf' ), 'https://console.aws.amazon.com/iam/home' ); ?>
-
\ No newline at end of file
+
+
+is_pro() ) {
+ $this->render_view( 'sidebar' );
+}
+?>
\ No newline at end of file
diff --git a/view/sidebar.php b/view/sidebar.php
index 440392d9..d2ec8269 100644
--- a/view/sidebar.php
+++ b/view/sidebar.php
@@ -2,7 +2,7 @@
-