WP Offload S3 Lite - Version 1.1.6

Version Description

= 1.1 = This is a major change, which ensures S3 URLs are no longer saved in post content. Instead, local URLs are filtered on page generation and replaced with the S3 version. If you depend on the S3 URLs being stored in post content you will need to make modifications to support this version.

= 0.6 = This version requires PHP 5.3.3+ and the Amazon Web Services plugin

Download this release

Release Info

Developer deliciousbrains
Plugin Icon 128x128 WP Offload S3 Lite
Version 1.1.6
Comparing to
See all releases

Code changes from version 1.1.5 to 1.1.6

README.md CHANGED
@@ -2,8 +2,8 @@
2
  **Contributors:** bradt, deliciousbrains
3
  **Tags:** uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
4
  **Requires at least:** 4.4
5
- **Tested up to:** 4.7.1
6
- **Stable tag:** 1.1.5
7
  **License:** GPLv3
8
 
9
  Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
@@ -69,6 +69,17 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
69
 
70
  ## Changelog ##
71
 
 
 
 
 
 
 
 
 
 
 
 
72
  ### WP Offload S3 Lite 1.1.5 - 2017-01-12 ###
73
  * Improvement: Filter custom CSS - S3 URLs will no longer be saved to the database
74
  * Bug fix: PDF previews have incorrect MIME type
2
  **Contributors:** bradt, deliciousbrains
3
  **Tags:** uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
4
  **Requires at least:** 4.4
5
+ **Tested up to:** 4.7.3
6
+ **Stable tag:** 1.1.6
7
  **License:** GPLv3
8
 
9
  Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
69
 
70
  ## Changelog ##
71
 
72
+ ### WP Offload S3 Lite 1.1.6 - 2017-03-13 ###
73
+ * New: Compatibility with [Advanced Custom Fields](https://wordpress.org/plugins/advanced-custom-fields/)
74
+ * New: `as3cf_filter_post_local_to_s3` and `as3cf_filter_post_s3_to_local` filters added for filtering S3 URLs in custom content
75
+ * Improvement: Ensure files uploaded using `media_handle_sideload` have unique filename on S3 when 'Remove Files From Server' enabled
76
+ * Bug fix: Files uploaded to S3 with empty filenames when the filename started with non-latin characters
77
+ * Bug fix: Audio files with private ACL not working with WordPress's default media player
78
+ * Bug fix: S3 API version not passed to S3 client
79
+ * Bug fix: Content added to text widgets via the Customizer not saved
80
+ * Bug fix: Original file not removed locally when cropped via the Customizer and 'Remove Files From Server' enabled
81
+ * Bug fix: Incorrect Media Library URLs saved to the database when WordPress installed in a subdirectory
82
+
83
  ### WP Offload S3 Lite 1.1.5 - 2017-01-12 ###
84
  * Improvement: Filter custom CSS - S3 URLs will no longer be saved to the database
85
  * Bug fix: PDF previews have incorrect MIME type
assets/js/media.js CHANGED
@@ -140,12 +140,15 @@ var test = {};
140
  },
141
 
142
  updateACL: function( response ) {
143
- if ( 'undefined' === typeof response.acl_display || 'undefined' === typeof response.title || 'undefined' === typeof response.acl ) {
144
  this.renderACLError();
145
 
146
  return;
147
  }
148
 
 
 
 
149
  var toggle = $( '#as3cfpro-toggle-acl' );
150
 
151
  $( '#as3cfpro-updating' ).remove();
140
  },
141
 
142
  updateACL: function( response ) {
143
+ if ( null == response.acl_display || null == response.title || null == response.acl || null == response.url ) {
144
  this.renderACLError();
145
 
146
  return;
147
  }
148
 
149
+ this.model.set( 'url', response.url );
150
+ this.render();
151
+
152
  var toggle = $( '#as3cfpro-toggle-acl' );
153
 
154
  $( '#as3cfpro-updating' ).remove();
assets/js/media.min.js CHANGED
@@ -1 +1 @@
1
- var test={};!function(a,b){var c=wp.media,d=c.view.Attachment.Details.TwoColumn;c.view.Attachment.Details.TwoColumn=d.extend({events:function(){return b.extend({},d.prototype.events,{"click .local-warning":"confirmS3Removal","click #as3cfpro-toggle-acl":"toggleACL"})},render:function(){this.fetchS3Details(this.model.get("id"))},fetchS3Details:function(a){wp.ajax.send("as3cf_get_attachment_s3_details",{data:{_nonce:as3cf_media.nonces.get_attachment_s3_details,id:a}}).done(b.bind(this.renderView,this))},renderView:function(a){d.prototype.render.apply(this),this.renderActionLinks(a),this.renderS3Details(a)},renderActionLinks:function(c){var d=c&&c.links||[],e=this.$el.find(".actions"),f=a("<div />",{"class":"s3-actions"}),g=[];b(d).each(function(a){g.push(a)}),f.append(g.join(" | ")),e.append(f)},renderS3Details:function(a){if(a&&a.s3object){var b=this.$el.find(".attachment-info .details"),c=this.generateDetails(a,["bucket","key","region","acl"]);b.append(c)}},generateDetails:function(a,c){var d="",e=b.template('<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>');return b(c).each(function(c){if(a.s3object[c]){var f=a.s3object[c];if("acl"===c&&(f=a.s3object[c].name,a.acl_toggle)){var g=b.template('<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>');f=g({title:a.s3object[c].title,acl:a.s3object[c].acl,value:f})}d+=e({key:c,label:as3cf_media.strings[c],value:f})}}),d},confirmS3Removal:function(a){if(!confirm(as3cfpro_media.strings.local_warning))return a.preventDefault(),a.stopImmediatePropagation(),!1},toggleACL:function(c){c.preventDefault();var d=a("#as3cfpro-toggle-acl"),e=d.attr("data-currentACL"),f=as3cfpro_media.settings.private_acl;d.hide(),d.after('<span id="as3cfpro-updating">'+as3cfpro_media.strings.updating_acl+"</span>"),e===as3cfpro_media.settings.private_acl&&(f=as3cfpro_media.settings.default_acl),wp.ajax.send("as3cfpro_update_acl",{data:{_nonce:as3cfpro_media.nonces.update_acl,id:this.model.get("id"),acl:f}}).done(b.bind(this.updateACL,this)).fail(b.bind(this.renderACLError,this))},renderACLError:function(){a("#as3cfpro-updating").remove(),a("#as3cfpro-toggle-acl").show(),alert(as3cfpro_media.strings.change_acl_error)},updateACL:function(b){if("undefined"==typeof b.acl_display||"undefined"==typeof b.title||"undefined"==typeof b.acl)return void this.renderACLError();var c=a("#as3cfpro-toggle-acl");a("#as3cfpro-updating").remove(),c.text(b.acl_display),c.attr("title",b.title),c.attr("data-currentACL",b.acl),c.show()}})}(jQuery,_);
1
+ var test={};!function(a,b){var c=wp.media,d=c.view.Attachment.Details.TwoColumn;c.view.Attachment.Details.TwoColumn=d.extend({events:function(){return b.extend({},d.prototype.events,{"click .local-warning":"confirmS3Removal","click #as3cfpro-toggle-acl":"toggleACL"})},render:function(){this.fetchS3Details(this.model.get("id"))},fetchS3Details:function(a){wp.ajax.send("as3cf_get_attachment_s3_details",{data:{_nonce:as3cf_media.nonces.get_attachment_s3_details,id:a}}).done(b.bind(this.renderView,this))},renderView:function(a){d.prototype.render.apply(this),this.renderActionLinks(a),this.renderS3Details(a)},renderActionLinks:function(c){var d=c&&c.links||[],e=this.$el.find(".actions"),f=a("<div />",{"class":"s3-actions"}),g=[];b(d).each(function(a){g.push(a)}),f.append(g.join(" | ")),e.append(f)},renderS3Details:function(a){if(a&&a.s3object){var b=this.$el.find(".attachment-info .details"),c=this.generateDetails(a,["bucket","key","region","acl"]);b.append(c)}},generateDetails:function(a,c){var d="",e=b.template('<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>');return b(c).each(function(c){if(a.s3object[c]){var f=a.s3object[c];if("acl"===c&&(f=a.s3object[c].name,a.acl_toggle)){var g=b.template('<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>');f=g({title:a.s3object[c].title,acl:a.s3object[c].acl,value:f})}d+=e({key:c,label:as3cf_media.strings[c],value:f})}}),d},confirmS3Removal:function(a){if(!confirm(as3cfpro_media.strings.local_warning))return a.preventDefault(),a.stopImmediatePropagation(),!1},toggleACL:function(c){c.preventDefault();var d=a("#as3cfpro-toggle-acl"),e=d.attr("data-currentACL"),f=as3cfpro_media.settings.private_acl;d.hide(),d.after('<span id="as3cfpro-updating">'+as3cfpro_media.strings.updating_acl+"</span>"),e===as3cfpro_media.settings.private_acl&&(f=as3cfpro_media.settings.default_acl),wp.ajax.send("as3cfpro_update_acl",{data:{_nonce:as3cfpro_media.nonces.update_acl,id:this.model.get("id"),acl:f}}).done(b.bind(this.updateACL,this)).fail(b.bind(this.renderACLError,this))},renderACLError:function(){a("#as3cfpro-updating").remove(),a("#as3cfpro-toggle-acl").show(),alert(as3cfpro_media.strings.change_acl_error)},updateACL:function(b){if(null==b.acl_display||null==b.title||null==b.acl||null==b.url)return void this.renderACLError();this.model.set("url",b.url),this.render();var c=a("#as3cfpro-toggle-acl");a("#as3cfpro-updating").remove(),c.text(b.acl_display),c.attr("title",b.title),c.attr("data-currentACL",b.acl),c.show()}})}(jQuery,_);
assets/js/modal.js CHANGED
@@ -2,7 +2,8 @@ var as3cfModal = (function( $ ) {
2
 
3
  var modal = {
4
  prefix: 'as3cf',
5
- loading: false
 
6
  };
7
 
8
  var modals = {};
@@ -54,7 +55,12 @@ var as3cfModal = (function( $ ) {
54
  var $overlay = $( '#as3cf-overlay' );
55
 
56
  // Modal container
57
- $overlay.append( '<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>' );
 
 
 
 
 
58
  var $modal = $( '#as3cf-modal' );
59
 
60
  if ( undefined === modals[ key ] ) {
@@ -88,7 +94,7 @@ var as3cfModal = (function( $ ) {
88
  * @param {function} callback
89
  */
90
  modal.close = function( callback ) {
91
- if ( modal.loading ) {
92
  return;
93
  }
94
 
@@ -110,12 +116,21 @@ var as3cfModal = (function( $ ) {
110
  /**
111
  * Set loading state
112
  *
113
- * @param {bool} state
114
  */
115
  modal.setLoadingState = function( state ) {
116
  modal.loading = state;
117
  };
118
 
 
 
 
 
 
 
 
 
 
119
  // Setup click handlers
120
  $( document ).ready( function() {
121
 
2
 
3
  var modal = {
4
  prefix: 'as3cf',
5
+ loading: false,
6
+ dismissible: true
7
  };
8
 
9
  var modals = {};
55
  var $overlay = $( '#as3cf-overlay' );
56
 
57
  // Modal container
58
+ if ( modal.dismissible ) {
59
+ $overlay.append( '<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>' );
60
+ } else {
61
+ $overlay.append( '<div id="as3cf-modal"></div>' );
62
+ }
63
+
64
  var $modal = $( '#as3cf-modal' );
65
 
66
  if ( undefined === modals[ key ] ) {
94
  * @param {function} callback
95
  */
96
  modal.close = function( callback ) {
97
+ if ( modal.loading || ! modal.dismissible ) {
98
  return;
99
  }
100
 
116
  /**
117
  * Set loading state
118
  *
119
+ * @param {boolean} state
120
  */
121
  modal.setLoadingState = function( state ) {
122
  modal.loading = state;
123
  };
124
 
125
+ /**
126
+ * Set dismissible state.
127
+ *
128
+ * @param {boolean} state
129
+ */
130
+ modal.setDismissibleState = function( state ) {
131
+ modal.dismissible = state;
132
+ };
133
+
134
  // Setup click handlers
135
  $( document ).ready( function() {
136
 
assets/js/modal.min.js CHANGED
@@ -1 +1 @@
1
- var as3cfModal=function(a){function b(a){return a.replace(/[^a-z]/g,"")}var c={prefix:"as3cf",loading:!1},d={};return c.exists=function(c){var e=b(c);return void 0!==d[e]||!!a(c).length},c.open=function(c,e,f){var g=b(c);a("body").append('<div id="as3cf-overlay"></div>');var h=a("#as3cf-overlay");h.append('<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>');var i=a("#as3cf-modal");if(void 0===d[g]){var j=a(c);d[g]=j.clone(!0).css("display","block"),j.remove()}i.data("as3cf-modal-target",c).append(d[g]),void 0!==f&&i.addClass(f),"function"==typeof e&&e(c),a("body").addClass("as3cf-modal-open"),h.fadeIn(150),i.fadeIn(150),a("body").trigger("as3cf-modal-open",[c])},c.close=function(b){if(!c.loading){var d=a("#as3cf-modal").data("as3cf-modal-target");a("#as3cf-overlay").fadeOut(150,function(){"function"==typeof b&&b(d),a("body").removeClass("as3cf-modal-open"),a(this).remove()}),a("body").trigger("as3cf-modal-close",[d])}},c.setLoadingState=function(a){c.loading=a},a(document).ready(function(){a("body").on("click","[data-as3cf-modal]",function(b){b.preventDefault(),c.open(a(this).data("as3cf-modal")+"."+c.prefix)}),a("body").on("click","#as3cf-overlay, .close-as3cf-modal",function(a){return a.preventDefault(),a.target===this&&void c.close()})}),c}(jQuery);
1
+ var as3cfModal=function(a){function b(a){return a.replace(/[^a-z]/g,"")}var c={prefix:"as3cf",loading:!1,dismissible:!0},d={};return c.exists=function(c){var e=b(c);return void 0!==d[e]||!!a(c).length},c.open=function(e,f,g){var h=b(e);a("body").append('<div id="as3cf-overlay"></div>');var i=a("#as3cf-overlay");c.dismissible?i.append('<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>'):i.append('<div id="as3cf-modal"></div>');var j=a("#as3cf-modal");if(void 0===d[h]){var k=a(e);d[h]=k.clone(!0).css("display","block"),k.remove()}j.data("as3cf-modal-target",e).append(d[h]),void 0!==g&&j.addClass(g),"function"==typeof f&&f(e),a("body").addClass("as3cf-modal-open"),i.fadeIn(150),j.fadeIn(150),a("body").trigger("as3cf-modal-open",[e])},c.close=function(b){if(!c.loading&&c.dismissible){var d=a("#as3cf-modal").data("as3cf-modal-target");a("#as3cf-overlay").fadeOut(150,function(){"function"==typeof b&&b(d),a("body").removeClass("as3cf-modal-open"),a(this).remove()}),a("body").trigger("as3cf-modal-close",[d])}},c.setLoadingState=function(a){c.loading=a},c.setDismissibleState=function(a){c.dismissible=a},a(document).ready(function(){a("body").on("click","[data-as3cf-modal]",function(b){b.preventDefault(),c.open(a(this).data("as3cf-modal")+"."+c.prefix)}),a("body").on("click","#as3cf-overlay, .close-as3cf-modal",function(a){return a.preventDefault(),a.target===this&&void c.close()})}),c}(jQuery);
classes/amazon-s3-and-cloudfront.php CHANGED
@@ -12,6 +12,11 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
12
  */
13
  private $s3client;
14
 
 
 
 
 
 
15
  /**
16
  * @var string
17
  */
@@ -76,6 +81,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
76
  const PRIVATE_ACL = 'private';
77
  const DEFAULT_EXPIRES = 900;
78
  const DEFAULT_REGION = 'us-east-1';
 
 
79
 
80
  const SETTINGS_KEY = 'tantan_wordpress_s3';
81
  const SETTINGS_CONSTANT = 'WPOS3_SETTINGS';
@@ -92,7 +99,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
92
 
93
  parent::__construct( $plugin_file_path );
94
 
95
- $this->aws = $aws;
96
  $this->notices = AS3CF_Notices::get_instance( $this );
97
 
98
  $this->init( $plugin_file_path );
@@ -140,12 +147,14 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
140
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
141
  add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 99, 6 );
142
  add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 99, 4 );
143
- add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js' ), 99, 3 );
144
  add_filter( 'image_get_intermediate_size', array( $this, 'maybe_encode_image_get_intermediate_size' ), 99, 3 );
145
  add_filter( 'get_attached_file', array( $this, 'get_attached_file' ), 10, 2 );
 
146
 
147
  // Communication with S3, plugin needs to be setup
148
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
 
149
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 110, 2 );
150
  add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
151
  add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
@@ -244,7 +253,10 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
244
  $settings = $this->get_settings();
245
 
246
  // If legacy setting set, migrate settings
247
- if ( isset( $settings['wp-uploads'] ) && $settings['wp-uploads'] && in_array( $key, array( 'copy-to-s3', 'serve-from-s3' ) ) ) {
 
 
 
248
  return '1';
249
  }
250
 
@@ -662,7 +674,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
662
  /**
663
  * Generate a preview of the URL of files uploaded to S3
664
  *
665
- * @param bool $escape
666
  * @param string $suffix
667
  *
668
  * @return string
@@ -763,7 +775,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
763
  * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
764
  * to cope with possible different regions
765
  */
766
- function remove_attachment_files_from_s3( $post_id, $s3object, $remove_backup_sizes = true, $log_error = false, $return_on_error = false, $force_new_s3_client = false ) {
767
  $prefix = $this->normalize_object_prefix( $s3object['key'] );
768
  $bucket = $s3object['bucket'];
769
  $region = $this->get_s3object_region( $s3object );
@@ -778,7 +790,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
778
 
779
  foreach ( $paths as $path ) {
780
  $objects_to_remove[] = array(
781
- 'Key' => $prefix . basename( $path ),
782
  );
783
  }
784
 
@@ -793,7 +805,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
793
  * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
794
  * to cope with possible different regions
795
  */
796
- function delete_attachment( $post_id, $force_new_s3_client = false ) {
797
  if ( ! $this->is_plugin_setup() ) {
798
  return;
799
  }
@@ -850,7 +862,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
850
  *
851
  * @return array|WP_Error $s3object|$meta If meta is supplied, return it. Else return S3 meta
852
  */
853
- function upload_attachment_to_s3( $post_id, $data = null, $file_path = null, $force_new_s3_client = false, $remove_local_files = true ) {
854
  $return_metadata = null;
855
  if ( is_null( $data ) ) {
856
  $data = wp_get_attachment_metadata( $post_id, true );
@@ -887,7 +899,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
887
  return $this->return_upload_error( $error_msg, $return_metadata );
888
  }
889
 
890
- $file_name = basename( $file_path );
891
  $type = get_post_mime_type( $post_id );
892
  $allowed_types = $this->get_allowed_mime_types();
893
 
@@ -1017,7 +1029,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1017
  $acl = apply_filters( 'as3cf_upload_acl_sizes', self::DEFAULT_ACL, $size, $post_id, $data );
1018
 
1019
  $additional_images[] = array(
1020
- 'Key' => $prefix . basename( $file_path ),
1021
  'SourceFile' => $file_path,
1022
  'ACL' => $acl,
1023
  'ContentType' => $this->get_mime_type( $file_path ),
@@ -1084,6 +1096,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1084
  update_post_meta( $post_id, 'amazonS3_info', $s3object );
1085
  }
1086
 
 
 
 
1087
  do_action( 'wpos3_post_upload_attachment', $post_id, $s3object );
1088
 
1089
  if ( ! is_null( $return_metadata ) ) {
@@ -1102,7 +1117,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1102
  * @return string
1103
  */
1104
  protected function get_mime_type( $file_path ) {
1105
- $file_type = wp_check_filetype_and_ext( $file_path, basename( $file_path ) );
1106
 
1107
  return $file_type['type'];
1108
  }
@@ -1195,20 +1210,6 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1195
  }
1196
  }
1197
 
1198
- /**
1199
- * Helper to apply a suffix to a file path
1200
- *
1201
- * @param string $file
1202
- * @param string $suffix
1203
- *
1204
- * @return string
1205
- */
1206
- function apply_file_suffix( $file, $suffix ) {
1207
- $pathinfo = pathinfo( $file );
1208
-
1209
- return $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $suffix . '.' . $pathinfo['extension'];
1210
- }
1211
-
1212
  /**
1213
  * Get the object versioning string prefix
1214
  *
@@ -1279,52 +1280,66 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1279
  }
1280
 
1281
  /**
1282
- * Create unique names for file to be uploaded to AWS
1283
- * This only applies when the remove local file option is enabled
1284
  *
1285
- * @param array $file An array of data for a single file.
1286
  *
1287
  * @return array $file The altered file array with AWS unique filename.
1288
  */
1289
- function wp_handle_upload_prefilter( $file ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1290
  if ( ! $this->get_setting( 'copy-to-s3' ) || ! $this->is_plugin_setup() ) {
1291
- return $file;
1292
  }
1293
 
1294
- $filename = $file['name'];
1295
-
1296
  // sanitize the file name before we begin processing
1297
  $filename = sanitize_file_name( $filename );
1298
 
1299
- // separate the filename into a name and extension
1300
- $info = pathinfo( $filename );
1301
- $ext = ! empty( $info['extension'] ) ? '.' . $info['extension'] : '';
1302
- $name = basename( $filename, $ext );
1303
 
1304
- // edge case: if file is named '.ext', treat as an empty name
1305
  if ( $name === $ext ) {
1306
  $name = '';
1307
  }
1308
 
1309
- // rebuild filename with lowercase extension as S3 will have converted extension on upload
1310
  $ext = strtolower( $ext );
1311
- $filename = $info['filename'] . $ext;
1312
  $time = current_time( 'mysql' );
1313
 
1314
- // Get time if uploaded in post screen
1315
- $post_id = filter_input( INPUT_POST, 'post_id', FILTER_VALIDATE_INT );
1316
- if ( isset( $post_id ) ) {
1317
  $time = $this->get_post_time( $post_id );
1318
  }
1319
 
1320
  if ( ! $this->does_file_exist( $filename, $time ) ) {
1321
- // File doesn't exist locally or on S3, return it
1322
- return $file;
1323
  }
1324
 
1325
- $file['name'] = $this->generate_unique_filename( $name, $ext, $time );
1326
 
1327
- return $file;
1328
  }
1329
 
1330
  /**
@@ -1414,7 +1429,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1414
  }
1415
 
1416
  $s3client = $this->get_s3client( $region );
1417
- $prefix = ltrim( trailingslashit( $this->get_object_prefix() ), '/' );
1418
  $prefix .= ltrim( trailingslashit( $this->get_dynamic_prefix( $time ) ), '/' );
1419
 
1420
  return $s3client->doesObjectExist( $bucket, $prefix . $filename );
@@ -1493,6 +1508,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1493
  if ( is_null( $expires ) ) {
1494
  $expires = self::DEFAULT_EXPIRES;
1495
  }
 
1496
  return $this->get_attachment_url( $post_id, $expires, $size, null, $headers, $skip_rewrite_check );
1497
  }
1498
 
@@ -1699,16 +1715,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1699
  return false;
1700
  }
1701
 
1702
- // Set correct domain on multisite subdomain installs
1703
- if ( is_multisite() ) {
1704
- $siteurl = trailingslashit( get_option( 'siteurl' ) );
1705
- $network_siteurl = trailingslashit( network_site_url() );
1706
-
1707
- if ( 0 !== strpos( $url, $siteurl ) ) {
1708
- // URL already using site URL, no replacement needed
1709
- $url = str_replace( $network_siteurl, $siteurl, $url );
1710
- }
1711
- }
1712
 
1713
  return $url;
1714
  }
@@ -1796,7 +1803,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1796
  if ( ! is_null( $expires ) && $this->is_plugin_setup() ) {
1797
  try {
1798
  $expires = time() + apply_filters( 'as3cf_expires', $expires );
1799
- $secure_url = $this->get_s3client( $region )->getObjectUrl( $s3object['bucket'], $s3object['key'], $expires, $headers );
 
1800
 
1801
  return apply_filters( 'as3cf_get_attachment_secure_url', $secure_url, $s3object, $post_id, $expires, $headers );
1802
  } catch ( Exception $e ) {
@@ -1992,7 +2000,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1992
  }
1993
 
1994
  $sizes = $meta['sizes'];
1995
- uasort( $sizes, function( $a, $b ) {
1996
  // Order by image area
1997
  return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
1998
  } );
@@ -2077,9 +2085,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2077
 
2078
  if ( isset( $url['query'] ) ) {
2079
  // Manually strip query string, as passing $url['path'] to basename results in corrupt � characters
2080
- $file_name = basename( str_replace( '?' . $url['query'], '', $file ) );
2081
  } else {
2082
- $file_name = basename( $file );
2083
  }
2084
 
2085
  if ( false !== strpos( $file_name, '%' ) ) {
@@ -2112,7 +2120,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2112
  return $file;
2113
  }
2114
 
2115
- $file_name = basename( $url['path'] );
2116
 
2117
  if ( false === strpos( $file_name, '%' ) ) {
2118
  // File name not encoded, return original
@@ -2128,7 +2136,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2128
  * Allow processes to update the file on S3 via update_attached_file()
2129
  *
2130
  * @param string $file
2131
- * @param int $attachment_id
2132
  *
2133
  * @return string
2134
  */
@@ -2175,8 +2183,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2175
  * @param array $return
2176
  */
2177
  function end_ajax( $return = array() ) {
2178
- echo json_encode( $return );
2179
- exit;
2180
  }
2181
 
2182
  function verify_ajax_request() {
@@ -2226,7 +2233,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2226
  $previous_manual_bucket_select = $this->get_setting( 'manual_bucket', false );
2227
 
2228
  $args = array(
2229
- '_nonce' => wp_create_nonce( 'as3cf-create-bucket' )
2230
  );
2231
 
2232
  $this->save_bucket_for_ajax( $bucket, $previous_manual_bucket_select, $region, $args );
@@ -2254,8 +2261,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2254
  }
2255
 
2256
  $this->get_s3client()->createBucket( $args );
2257
- }
2258
- catch ( Exception $e ) {
2259
  return new WP_Error( 'exception', $e->getMessage() );
2260
  }
2261
 
@@ -2395,7 +2401,13 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2395
  * @param Amazon_Web_Services $aws
2396
  */
2397
  function admin_menu( $aws ) {
2398
- $hook_suffix = $aws->add_page( $this->get_plugin_page_title(), $this->plugin_menu_title, 'manage_options', $this->plugin_slug, array( $this, 'render_page' ) );
 
 
 
 
 
 
2399
 
2400
  if ( false !== $hook_suffix ) {
2401
  $this->hook_suffix = $hook_suffix;
@@ -2414,13 +2426,13 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2414
  function get_s3client( $region = false, $force = false ) {
2415
  if ( is_null( $this->s3client ) || $force ) {
2416
 
 
 
 
 
2417
  if ( $region ) {
2418
- $args = array(
2419
- 'region' => $this->translate_region( $region ),
2420
- 'signature' => 'v4',
2421
- );
2422
- } else {
2423
- $args = array();
2424
  }
2425
 
2426
  $client = $this->aws->get_client()->get( 's3', $args );
@@ -2467,7 +2479,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2467
  *
2468
  *
2469
  * @param array $s3object
2470
- * @param int $post_id - if supplied will update the s3 meta if no region found
2471
  *
2472
  * @return string|WP_Error - region name
2473
  */
@@ -2542,8 +2554,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2542
  function get_buckets() {
2543
  try {
2544
  $result = $this->get_s3client()->listBuckets();
2545
- }
2546
- catch ( Exception $e ) {
2547
  return new WP_Error( 'exception', $e->getMessage() );
2548
  }
2549
 
@@ -2827,8 +2838,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2827
 
2828
  if ( is_wp_error( $aws_client ) ) {
2829
  $this->render_view( 'error-fatal', array( 'message' => $aws_client->get_error_message() ) );
2830
- }
2831
- else {
2832
  $this->render_view( 'settings-tabs' );
2833
  do_action( 'as3cf_pre_settings_render' );
2834
  $this->render_view( 'settings' );
@@ -2846,7 +2856,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2846
  function get_settings_tabs() {
2847
  $tabs = array(
2848
  'media' => _x( 'Media Library', 'Show the media library tab', 'amazon-s3-and-cloudfront' ),
2849
- 'support' => _x( 'Support', 'Show the support tab', 'amazon-s3-and-cloudfront' )
2850
  );
2851
 
2852
  return apply_filters( 'as3cf_settings_tabs', $tabs );
@@ -3060,7 +3070,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
3060
  * @param array $s3object
3061
  */
3062
  function make_acl_admin_notice( $s3object ) {
3063
- $filename = basename( $s3object['key'] );
3064
  $acl = ( isset( $s3object['acl'] ) ) ? $s3object['acl'] : self::DEFAULT_ACL;
3065
  $acl_name = $this->get_acl_display_name( $acl );
3066
  $text = sprintf( __( '<strong>WP Offload S3</strong> &mdash; The file %s has been given %s permissions on Amazon S3.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
@@ -3080,7 +3090,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
3080
  $gd_enabled = $this->gd_enabled();
3081
  $imagick_enabled = $this->imagick_enabled();
3082
 
3083
- if( ! $gd_enabled && ! $imagick_enabled ) {
3084
  $this->notices->add_notice(
3085
  __( '<strong>WP Offload S3 Requirement Missing</strong> &mdash; Looks like you don\'t have an image manipulation library installed on this server and configured with PHP. You may run into trouble if you try to edit images. Please setup GD or ImageMagick.', 'amazon-s3-and-cloudfront' ),
3086
  array( 'flash' => false, 'only_show_to_user' => false, 'only_show_in_settings' => true )
@@ -3703,7 +3713,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
3703
  return $paths;
3704
  }
3705
 
3706
- $file_name = basename( $file_path );
 
 
 
 
 
3707
 
3708
  // Thumb
3709
  if ( isset( $meta['thumb'] ) ) {
@@ -3807,7 +3822,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
3807
  * @return bool
3808
  */
3809
  public function memory_exceeded( $filter_name = null ) {
3810
- $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
3811
  $current_memory = memory_get_usage( true );
3812
  $return = false;
3813
 
@@ -3857,7 +3872,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
3857
  public function count_attachments( $prefix, $uploaded_to_s3 = null ) {
3858
  global $wpdb;
3859
 
3860
- $sql = "SELECT COUNT(*)
3861
  FROM `{$prefix}posts` p";
3862
 
3863
  $where = "WHERE p.post_type = 'attachment'";
@@ -3931,7 +3946,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
3931
  *
3932
  * @param string $code
3933
  * @param string $message
3934
- * @param mixed $data
3935
  *
3936
  * @return WP_Error
3937
  */
@@ -4111,7 +4126,14 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
4111
  * Add the S3 meta box to the attachment screen
4112
  */
4113
  public function attachment_s3_meta_box() {
4114
- add_meta_box( 's3-actions', __( 'Amazon S3', 'amazon-s3-and-cloudfront' ), array( $this, 'attachment_s3_actions_meta_box' ), 'attachment', 'side', 'core' );
 
 
 
 
 
 
 
4115
  }
4116
 
4117
  /**
@@ -4230,15 +4252,22 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
4230
  wp_enqueue_style( 'as3cf-media-styles', $src, array( 'as3cf-modal' ), $version );
4231
 
4232
  $src = plugins_url( 'assets/js/media' . $suffix . '.js', $this->plugin_file_path );
4233
- wp_enqueue_script( 'as3cf-media-script', $src, array( 'jquery', 'media-views', 'media-grid', 'wp-util' ), $version, true );
 
 
 
 
 
 
4234
 
4235
- wp_localize_script( 'as3cf-media-script',
 
4236
  'as3cf_media',
4237
  array(
4238
  'strings' => $this->get_media_action_strings(),
4239
  'nonces' => array(
4240
  'get_attachment_s3_details' => wp_create_nonce( 'get-attachment-s3-details' ),
4241
- )
4242
  )
4243
  );
4244
  }
@@ -4347,8 +4376,61 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
4347
  $url = preg_replace( '/^(\S+)-[0-9]{1,4}x[0-9]{1,4}(\.[a-zA-Z0-9\.]{2,})?/', '$1$2', $url );
4348
 
4349
  if ( $remove_extension ) {
4350
- $parts = pathinfo( $url );
4351
- $url = str_replace( '.' . $parts['extension'], '', $url );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4352
  }
4353
 
4354
  return $url;
12
  */
13
  private $s3client;
14
 
15
+ /**
16
+ * @var array
17
+ */
18
+ private $uploaded_post_ids = array();
19
+
20
  /**
21
  * @var string
22
  */
81
  const PRIVATE_ACL = 'private';
82
  const DEFAULT_EXPIRES = 900;
83
  const DEFAULT_REGION = 'us-east-1';
84
+ const AWS_SIGNATURE = 'v4';
85
+ const S3_API_VERSION = '2006-03-01';
86
 
87
  const SETTINGS_KEY = 'tantan_wordpress_s3';
88
  const SETTINGS_CONSTANT = 'WPOS3_SETTINGS';
99
 
100
  parent::__construct( $plugin_file_path );
101
 
102
+ $this->aws = $aws;
103
  $this->notices = AS3CF_Notices::get_instance( $this );
104
 
105
  $this->init( $plugin_file_path );
147
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
148
  add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 99, 6 );
149
  add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 99, 4 );
150
+ add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js', ), 99, 3 );
151
  add_filter( 'image_get_intermediate_size', array( $this, 'maybe_encode_image_get_intermediate_size' ), 99, 3 );
152
  add_filter( 'get_attached_file', array( $this, 'get_attached_file' ), 10, 2 );
153
+ add_filter( 'wp_audio_shortcode', array( $this, 'wp_audio_shortcode' ), 100, 5 );
154
 
155
  // Communication with S3, plugin needs to be setup
156
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
157
+ add_filter( 'wp_handle_sideload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
158
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 110, 2 );
159
  add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
160
  add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
253
  $settings = $this->get_settings();
254
 
255
  // If legacy setting set, migrate settings
256
+ if ( isset( $settings['wp-uploads'] ) &&
257
+ $settings['wp-uploads'] &&
258
+ in_array( $key, array( 'copy-to-s3', 'serve-from-s3', ) )
259
+ ) {
260
  return '1';
261
  }
262
 
674
  /**
675
  * Generate a preview of the URL of files uploaded to S3
676
  *
677
+ * @param bool $escape
678
  * @param string $suffix
679
  *
680
  * @return string
775
  * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
776
  * to cope with possible different regions
777
  */
778
+ function remove_attachment_files_from_s3( $post_id, $s3object, $remove_backup_sizes = true, $log_error = false, $return_on_error = false, $force_new_s3_client = false ) {
779
  $prefix = $this->normalize_object_prefix( $s3object['key'] );
780
  $bucket = $s3object['bucket'];
781
  $region = $this->get_s3object_region( $s3object );
790
 
791
  foreach ( $paths as $path ) {
792
  $objects_to_remove[] = array(
793
+ 'Key' => $prefix . wp_basename( $path ),
794
  );
795
  }
796
 
805
  * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
806
  * to cope with possible different regions
807
  */
808
+ function delete_attachment( $post_id, $force_new_s3_client = false ) {
809
  if ( ! $this->is_plugin_setup() ) {
810
  return;
811
  }
862
  *
863
  * @return array|WP_Error $s3object|$meta If meta is supplied, return it. Else return S3 meta
864
  */
865
+ public function upload_attachment_to_s3( $post_id, $data = null, $file_path = null, $force_new_s3_client = false, $remove_local_files = true ) {
866
  $return_metadata = null;
867
  if ( is_null( $data ) ) {
868
  $data = wp_get_attachment_metadata( $post_id, true );
899
  return $this->return_upload_error( $error_msg, $return_metadata );
900
  }
901
 
902
+ $file_name = wp_basename( $file_path );
903
  $type = get_post_mime_type( $post_id );
904
  $allowed_types = $this->get_allowed_mime_types();
905
 
1029
  $acl = apply_filters( 'as3cf_upload_acl_sizes', self::DEFAULT_ACL, $size, $post_id, $data );
1030
 
1031
  $additional_images[] = array(
1032
+ 'Key' => $prefix . wp_basename( $file_path ),
1033
  'SourceFile' => $file_path,
1034
  'ACL' => $acl,
1035
  'ContentType' => $this->get_mime_type( $file_path ),
1096
  update_post_meta( $post_id, 'amazonS3_info', $s3object );
1097
  }
1098
 
1099
+ // Keep track of attachments uploaded by this instance.
1100
+ $this->uploaded_post_ids[] = $post_id;
1101
+
1102
  do_action( 'wpos3_post_upload_attachment', $post_id, $s3object );
1103
 
1104
  if ( ! is_null( $return_metadata ) ) {
1117
  * @return string
1118
  */
1119
  protected function get_mime_type( $file_path ) {
1120
+ $file_type = wp_check_filetype_and_ext( $file_path, wp_basename( $file_path ) );
1121
 
1122
  return $file_type['type'];
1123
  }
1210
  }
1211
  }
1212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1213
  /**
1214
  * Get the object versioning string prefix
1215
  *
1280
  }
1281
 
1282
  /**
1283
+ * Filter file details before upload.
 
1284
  *
1285
+ * @param array $file An array of data for a single file.
1286
  *
1287
  * @return array $file The altered file array with AWS unique filename.
1288
  */
1289
+ public function wp_handle_upload_prefilter( $file ) {
1290
+ // Get Post ID if uploaded in post screen.
1291
+ $post_id = filter_input( INPUT_POST, 'post_id', FILTER_VALIDATE_INT );
1292
+
1293
+ $file['name'] = $this->filter_unique_filename( $file['name'], $post_id );
1294
+
1295
+ return $file;
1296
+ }
1297
+
1298
+ /**
1299
+ * Create unique names for file to be uploaded to AWS.
1300
+ * This only applies when the remove local file option is enabled.
1301
+ *
1302
+ * @param string $filename Unique file name.
1303
+ * @param int $post_id Attachment's parent Post ID.
1304
+ *
1305
+ * @return string
1306
+ */
1307
+ public function filter_unique_filename( $filename, $post_id = null ) {
1308
  if ( ! $this->get_setting( 'copy-to-s3' ) || ! $this->is_plugin_setup() ) {
1309
+ return $filename;
1310
  }
1311
 
 
 
1312
  // sanitize the file name before we begin processing
1313
  $filename = sanitize_file_name( $filename );
1314
 
1315
+ // Get base filename without extension.
1316
+ $ext = pathinfo( $filename, PATHINFO_EXTENSION );
1317
+ $ext = $ext ? ".$ext" : '';
1318
+ $name = wp_basename( $filename, $ext );
1319
 
1320
+ // Edge case: if file is named '.ext', treat as an empty name.
1321
  if ( $name === $ext ) {
1322
  $name = '';
1323
  }
1324
 
1325
+ // Rebuild filename with lowercase extension as S3 will have converted extension on upload.
1326
  $ext = strtolower( $ext );
1327
+ $filename = $name . $ext;
1328
  $time = current_time( 'mysql' );
1329
 
1330
+ // Get time if uploaded in post screen.
1331
+ if ( ! empty( $post_id ) ) {
 
1332
  $time = $this->get_post_time( $post_id );
1333
  }
1334
 
1335
  if ( ! $this->does_file_exist( $filename, $time ) ) {
1336
+ // File doesn't exist locally or on S3, return it.
1337
+ return $filename;
1338
  }
1339
 
1340
+ $filename = $this->generate_unique_filename( $name, $ext, $time );
1341
 
1342
+ return $filename;
1343
  }
1344
 
1345
  /**
1429
  }
1430
 
1431
  $s3client = $this->get_s3client( $region );
1432
+ $prefix = ltrim( trailingslashit( $this->get_object_prefix() ), '/' );
1433
  $prefix .= ltrim( trailingslashit( $this->get_dynamic_prefix( $time ) ), '/' );
1434
 
1435
  return $s3client->doesObjectExist( $bucket, $prefix . $filename );
1508
  if ( is_null( $expires ) ) {
1509
  $expires = self::DEFAULT_EXPIRES;
1510
  }
1511
+
1512
  return $this->get_attachment_url( $post_id, $expires, $size, null, $headers, $skip_rewrite_check );
1513
  }
1514
 
1715
  return false;
1716
  }
1717
 
1718
+ $url = $this->maybe_fix_local_subsite_url( $url );
 
 
 
 
 
 
 
 
 
1719
 
1720
  return $url;
1721
  }
1803
  if ( ! is_null( $expires ) && $this->is_plugin_setup() ) {
1804
  try {
1805
  $expires = time() + apply_filters( 'as3cf_expires', $expires );
1806
+ $secure_url = $this->get_s3client( $region )
1807
+ ->getObjectUrl( $s3object['bucket'], $s3object['key'], $expires, $headers );
1808
 
1809
  return apply_filters( 'as3cf_get_attachment_secure_url', $secure_url, $s3object, $post_id, $expires, $headers );
1810
  } catch ( Exception $e ) {
2000
  }
2001
 
2002
  $sizes = $meta['sizes'];
2003
+ uasort( $sizes, function ( $a, $b ) {
2004
  // Order by image area
2005
  return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
2006
  } );
2085
 
2086
  if ( isset( $url['query'] ) ) {
2087
  // Manually strip query string, as passing $url['path'] to basename results in corrupt � characters
2088
+ $file_name = wp_basename( str_replace( '?' . $url['query'], '', $file ) );
2089
  } else {
2090
+ $file_name = wp_basename( $file );
2091
  }
2092
 
2093
  if ( false !== strpos( $file_name, '%' ) ) {
2120
  return $file;
2121
  }
2122
 
2123
+ $file_name = wp_basename( $url['path'] );
2124
 
2125
  if ( false === strpos( $file_name, '%' ) ) {
2126
  // File name not encoded, return original
2136
  * Allow processes to update the file on S3 via update_attached_file()
2137
  *
2138
  * @param string $file
2139
+ * @param int $attachment_id
2140
  *
2141
  * @return string
2142
  */
2183
  * @param array $return
2184
  */
2185
  function end_ajax( $return = array() ) {
2186
+ wp_send_json( $return );
 
2187
  }
2188
 
2189
  function verify_ajax_request() {
2233
  $previous_manual_bucket_select = $this->get_setting( 'manual_bucket', false );
2234
 
2235
  $args = array(
2236
+ '_nonce' => wp_create_nonce( 'as3cf-create-bucket' ),
2237
  );
2238
 
2239
  $this->save_bucket_for_ajax( $bucket, $previous_manual_bucket_select, $region, $args );
2261
  }
2262
 
2263
  $this->get_s3client()->createBucket( $args );
2264
+ } catch ( Exception $e ) {
 
2265
  return new WP_Error( 'exception', $e->getMessage() );
2266
  }
2267
 
2401
  * @param Amazon_Web_Services $aws
2402
  */
2403
  function admin_menu( $aws ) {
2404
+ $hook_suffix = $aws->add_page(
2405
+ $this->get_plugin_page_title(),
2406
+ $this->plugin_menu_title,
2407
+ 'manage_options',
2408
+ $this->plugin_slug,
2409
+ array( $this, 'render_page' )
2410
+ );
2411
 
2412
  if ( false !== $hook_suffix ) {
2413
  $this->hook_suffix = $hook_suffix;
2426
  function get_s3client( $region = false, $force = false ) {
2427
  if ( is_null( $this->s3client ) || $force ) {
2428
 
2429
+ $args = array(
2430
+ 'version' => self::S3_API_VERSION,
2431
+ );
2432
+
2433
  if ( $region ) {
2434
+ $args['region'] = $this->translate_region( $region );
2435
+ $args['signature'] = self::AWS_SIGNATURE;
 
 
 
 
2436
  }
2437
 
2438
  $client = $this->aws->get_client()->get( 's3', $args );
2479
  *
2480
  *
2481
  * @param array $s3object
2482
+ * @param int $post_id - if supplied will update the s3 meta if no region found
2483
  *
2484
  * @return string|WP_Error - region name
2485
  */
2554
  function get_buckets() {
2555
  try {
2556
  $result = $this->get_s3client()->listBuckets();
2557
+ } catch ( Exception $e ) {
 
2558
  return new WP_Error( 'exception', $e->getMessage() );
2559
  }
2560
 
2838
 
2839
  if ( is_wp_error( $aws_client ) ) {
2840
  $this->render_view( 'error-fatal', array( 'message' => $aws_client->get_error_message() ) );
2841
+ } else {
 
2842
  $this->render_view( 'settings-tabs' );
2843
  do_action( 'as3cf_pre_settings_render' );
2844
  $this->render_view( 'settings' );
2856
  function get_settings_tabs() {
2857
  $tabs = array(
2858
  'media' => _x( 'Media Library', 'Show the media library tab', 'amazon-s3-and-cloudfront' ),
2859
+ 'support' => _x( 'Support', 'Show the support tab', 'amazon-s3-and-cloudfront' ),
2860
  );
2861
 
2862
  return apply_filters( 'as3cf_settings_tabs', $tabs );
3070
  * @param array $s3object
3071
  */
3072
  function make_acl_admin_notice( $s3object ) {
3073
+ $filename = wp_basename( $s3object['key'] );
3074
  $acl = ( isset( $s3object['acl'] ) ) ? $s3object['acl'] : self::DEFAULT_ACL;
3075
  $acl_name = $this->get_acl_display_name( $acl );
3076
  $text = sprintf( __( '<strong>WP Offload S3</strong> &mdash; The file %s has been given %s permissions on Amazon S3.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
3090
  $gd_enabled = $this->gd_enabled();
3091
  $imagick_enabled = $this->imagick_enabled();
3092
 
3093
+ if ( ! $gd_enabled && ! $imagick_enabled ) {
3094
  $this->notices->add_notice(
3095
  __( '<strong>WP Offload S3 Requirement Missing</strong> &mdash; Looks like you don\'t have an image manipulation library installed on this server and configured with PHP. You may run into trouble if you try to edit images. Please setup GD or ImageMagick.', 'amazon-s3-and-cloudfront' ),
3096
  array( 'flash' => false, 'only_show_to_user' => false, 'only_show_in_settings' => true )
3713
  return $paths;
3714
  }
3715
 
3716
+ $file_name = wp_basename( $file_path );
3717
+
3718
+ // If file edited, current file name might be different.
3719
+ if ( isset( $meta['file'] ) ) {
3720
+ $paths['file'] = str_replace( $file_name, wp_basename( $meta['file'] ), $file_path );
3721
+ }
3722
 
3723
  // Thumb
3724
  if ( isset( $meta['thumb'] ) ) {
3822
  * @return bool
3823
  */
3824
  public function memory_exceeded( $filter_name = null ) {
3825
+ $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
3826
  $current_memory = memory_get_usage( true );
3827
  $return = false;
3828
 
3872
  public function count_attachments( $prefix, $uploaded_to_s3 = null ) {
3873
  global $wpdb;
3874
 
3875
+ $sql = "SELECT COUNT(DISTINCT p.ID)
3876
  FROM `{$prefix}posts` p";
3877
 
3878
  $where = "WHERE p.post_type = 'attachment'";
3946
  *
3947
  * @param string $code
3948
  * @param string $message
3949
+ * @param mixed $data
3950
  *
3951
  * @return WP_Error
3952
  */
4126
  * Add the S3 meta box to the attachment screen
4127
  */
4128
  public function attachment_s3_meta_box() {
4129
+ add_meta_box(
4130
+ 's3-actions',
4131
+ __( 'Amazon S3', 'amazon-s3-and-cloudfront' ),
4132
+ array( $this, 'attachment_s3_actions_meta_box' ),
4133
+ 'attachment',
4134
+ 'side',
4135
+ 'core'
4136
+ );
4137
  }
4138
 
4139
  /**
4252
  wp_enqueue_style( 'as3cf-media-styles', $src, array( 'as3cf-modal' ), $version );
4253
 
4254
  $src = plugins_url( 'assets/js/media' . $suffix . '.js', $this->plugin_file_path );
4255
+ wp_enqueue_script(
4256
+ 'as3cf-media-script',
4257
+ $src,
4258
+ array( 'jquery', 'media-views', 'media-grid', 'wp-util' ),
4259
+ $version,
4260
+ true
4261
+ );
4262
 
4263
+ wp_localize_script(
4264
+ 'as3cf-media-script',
4265
  'as3cf_media',
4266
  array(
4267
  'strings' => $this->get_media_action_strings(),
4268
  'nonces' => array(
4269
  'get_attachment_s3_details' => wp_create_nonce( 'get-attachment-s3-details' ),
4270
+ ),
4271
  )
4272
  );
4273
  }
4376
  $url = preg_replace( '/^(\S+)-[0-9]{1,4}x[0-9]{1,4}(\.[a-zA-Z0-9\.]{2,})?/', '$1$2', $url );
4377
 
4378
  if ( $remove_extension ) {
4379
+ $ext = pathinfo( $url, PATHINFO_EXTENSION );
4380
+ $url = str_replace( ".$ext", '', $url );
4381
+ }
4382
+
4383
+ return $url;
4384
+ }
4385
+
4386
+ /**
4387
+ * Has the given attachment been uploaded by this instance?
4388
+ *
4389
+ * @param int $attachment_id
4390
+ *
4391
+ * @return bool
4392
+ */
4393
+ public function attachment_just_uploaded( $attachment_id ) {
4394
+ if ( is_int( $attachment_id ) && in_array( $attachment_id, $this->uploaded_post_ids ) ) {
4395
+ return true;
4396
+ }
4397
+
4398
+ return false;
4399
+ }
4400
+
4401
+ /**
4402
+ * Filters the audio shortcode output to remove "&_=NN" params from source.src as it breaks signed URLs.
4403
+ *
4404
+ * @param string $html Audio shortcode HTML output.
4405
+ * @param array $atts Array of audio shortcode attributes.
4406
+ * @param string $audio Audio file.
4407
+ * @param int $post_id Post ID.
4408
+ * @param string $library Media library used for the audio shortcode.
4409
+ *
4410
+ * @return string
4411
+ *
4412
+ * Note: Depends on 30377.4.diff from https://core.trac.wordpress.org/ticket/30377
4413
+ */
4414
+ public function wp_audio_shortcode( $html, $atts, $audio, $post_id, $library ) {
4415
+ $html = preg_replace( '/&#038;_=[0-9]+/', '', $html );
4416
+
4417
+ return $html;
4418
+ }
4419
+
4420
+ /**
4421
+ * Ensure local URL is correct for multisite's non-primary subsites.
4422
+ *
4423
+ * @param string $url
4424
+ *
4425
+ * @return string
4426
+ */
4427
+ public function maybe_fix_local_subsite_url( $url ) {
4428
+ $siteurl = trailingslashit( get_option( 'siteurl' ) );
4429
+
4430
+ if ( is_multisite() && ! $this->is_current_blog( get_current_blog_id() ) && 0 !== strpos( $url, $siteurl ) ) {
4431
+ // Replace network URL with subsite's URL.
4432
+ $network_siteurl = trailingslashit( network_site_url() );
4433
+ $url = str_replace( $network_siteurl, $siteurl, $url );
4434
  }
4435
 
4436
  return $url;
classes/as3cf-filter.php CHANGED
@@ -257,6 +257,8 @@ abstract class AS3CF_Filter {
257
  $urls = array();
258
 
259
  foreach ( $matches as $url ) {
 
 
260
  if ( ! $this->url_needs_replacing( $url ) ) {
261
  // URL already correct, skip
262
  continue;
@@ -269,9 +271,7 @@ abstract class AS3CF_Filter {
269
  continue;
270
  }
271
 
272
- $info = pathinfo( $parts['path'] );
273
-
274
- if ( ! isset( $info['extension'] ) ) {
275
  // URL doesn't have a file extension, continue
276
  continue;
277
  }
257
  $urls = array();
258
 
259
  foreach ( $matches as $url ) {
260
+ $url = preg_replace( '/[^a-zA-Z0-9]$/', '', $url );
261
+
262
  if ( ! $this->url_needs_replacing( $url ) ) {
263
  // URL already correct, skip
264
  continue;
271
  continue;
272
  }
273
 
274
+ if ( ! pathinfo( $parts['path'], PATHINFO_EXTENSION ) ) {
 
 
275
  // URL doesn't have a file extension, continue
276
  continue;
277
  }
classes/as3cf-plugin-compatibility.php CHANGED
@@ -93,6 +93,7 @@ class AS3CF_Plugin_Compatibility {
93
  add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'image_editor_remove_original_image' ), 10, 3 );
94
  add_filter( 'as3cf_get_attached_file', array( $this, 'customizer_crop_download_file' ), 10, 4 );
95
  add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'customizer_crop_remove_original_image' ), 10, 3 );
 
96
 
97
  /*
98
  * Regenerate Thumbnails
@@ -413,7 +414,7 @@ class AS3CF_Plugin_Compatibility {
413
  function get_original_image_file( $post_id, $file_path ) {
414
  // remove original main image after edit
415
  $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
416
- $original_file = trailingslashit( dirname( $file_path ) ) . basename( $meta['file'] );
417
  if ( file_exists( $original_file ) ) {
418
  return $original_file;
419
  }
@@ -552,11 +553,15 @@ class AS3CF_Plugin_Compatibility {
552
  *
553
  * @return string
554
  */
555
- function customizer_crop_download_file( $url, $file, $attachment_id, $s3_object ) {
556
  if ( false === $this->is_customizer_crop_action() ) {
557
  return $url;
558
  }
559
 
 
 
 
 
560
  if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
561
  // Return the file if successfully downloaded from S3
562
  return $file;
@@ -915,7 +920,7 @@ class AS3CF_Plugin_Compatibility {
915
  }
916
 
917
  foreach ( $sources as $width => $source ) {
918
- $filename = basename( $source['url'] );
919
  $size = $this->find_image_size_from_width( $image_meta['sizes'], $width, $filename );
920
  $s3_url = $this->as3cf->get_attachment_s3_url( $attachment_id, $s3object, null, $size, $image_meta );
921
 
@@ -948,4 +953,26 @@ class AS3CF_Plugin_Compatibility {
948
 
949
  return null;
950
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
951
  }
93
  add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'image_editor_remove_original_image' ), 10, 3 );
94
  add_filter( 'as3cf_get_attached_file', array( $this, 'customizer_crop_download_file' ), 10, 4 );
95
  add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'customizer_crop_remove_original_image' ), 10, 3 );
96
+ add_filter( 'wp_unique_filename', array( $this, 'customizer_crop_unique_filename' ), 10, 3 );
97
 
98
  /*
99
  * Regenerate Thumbnails
414
  function get_original_image_file( $post_id, $file_path ) {
415
  // remove original main image after edit
416
  $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
417
+ $original_file = trailingslashit( dirname( $file_path ) ) . wp_basename( $meta['file'] );
418
  if ( file_exists( $original_file ) ) {
419
  return $original_file;
420
  }
553
  *
554
  * @return string
555
  */
556
+ public function customizer_crop_download_file( $url, $file, $attachment_id, $s3_object ) {
557
  if ( false === $this->is_customizer_crop_action() ) {
558
  return $url;
559
  }
560
 
561
+ if ( $this->as3cf->attachment_just_uploaded( $attachment_id ) ) {
562
+ return $url;
563
+ }
564
+
565
  if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
566
  // Return the file if successfully downloaded from S3
567
  return $file;
920
  }
921
 
922
  foreach ( $sources as $width => $source ) {
923
+ $filename = wp_basename( $source['url'] );
924
  $size = $this->find_image_size_from_width( $image_meta['sizes'], $width, $filename );
925
  $s3_url = $this->as3cf->get_attachment_s3_url( $attachment_id, $s3object, null, $size, $image_meta );
926
 
953
 
954
  return null;
955
  }
956
+
957
+ /**
958
+ * Filters the result when generating a unique file name for a customizer crop.
959
+ *
960
+ * @param string $filename Unique file name.
961
+ * @param string $ext File extension, eg. ".png".
962
+ * @param string $dir Directory path.
963
+ *
964
+ * @return string
965
+ */
966
+ public function customizer_crop_unique_filename( $filename, $ext, $dir ) {
967
+ if ( false === $this->is_customizer_crop_action() ) {
968
+ return $filename;
969
+ }
970
+
971
+ // Get parent Post ID for cropped image.
972
+ $post_id = filter_input( INPUT_POST, 'id', FILTER_VALIDATE_INT );
973
+
974
+ $filename = $this->as3cf->filter_unique_filename( $filename, $post_id );
975
+
976
+ return $filename;
977
+ }
978
  }
classes/as3cf-upgrade-filter-post.php CHANGED
@@ -346,9 +346,9 @@ abstract class AS3CF_Upgrade_Filter_Post extends AS3CF_Upgrade {
346
  */
347
  protected function get_find_and_replace_urls( $file_path, $old_url, $new_url, $meta, $backups = '' ) {
348
  $url_pairs = array();
349
- $file_name = basename( $file_path );
350
- $old_file_name = basename( $old_url );
351
- $new_file_name = basename( $new_url );
352
 
353
  // Full size image
354
  $url_pairs[] = $this->add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name );
@@ -430,7 +430,7 @@ abstract class AS3CF_Upgrade_Filter_Post extends AS3CF_Upgrade {
430
  */
431
  protected function maybe_add_encoded_url_pairs( $url_pairs ) {
432
  foreach ( $url_pairs as $url_pair ) {
433
- $file_name = basename( $url_pair['old_url'] );
434
  $encoded_file_name = $this->as3cf->encode_filename_in_path( $file_name );
435
 
436
  if ( $file_name !== $encoded_file_name ) {
346
  */
347
  protected function get_find_and_replace_urls( $file_path, $old_url, $new_url, $meta, $backups = '' ) {
348
  $url_pairs = array();
349
+ $file_name = wp_basename( $file_path );
350
+ $old_file_name = wp_basename( $old_url );
351
+ $new_file_name = wp_basename( $new_url );
352
 
353
  // Full size image
354
  $url_pairs[] = $this->add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name );
430
  */
431
  protected function maybe_add_encoded_url_pairs( $url_pairs ) {
432
  foreach ( $url_pairs as $url_pair ) {
433
+ $file_name = wp_basename( $url_pair['old_url'] );
434
  $encoded_file_name = $this->as3cf->encode_filename_in_path( $file_name );
435
 
436
  if ( $file_name !== $encoded_file_name ) {
classes/filters/as3cf-local-to-s3.php CHANGED
@@ -20,6 +20,7 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
20
  add_filter( 'the_excerpt', array( $this, 'filter_post' ), 100 );
21
  add_filter( 'content_edit_pre', array( $this, 'filter_post' ) );
22
  add_filter( 'excerpt_edit_pre', array( $this, 'filter_post' ) );
 
23
  // Widgets
24
  add_filter( 'widget_text', array( $this, 'filter_widget' ) );
25
  add_filter( 'widget_form_callback', array( $this, 'filter_widget_form' ), 10, 2 );
@@ -140,7 +141,8 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
140
  */
141
  protected function url_needs_replacing( $url ) {
142
  $uploads = wp_upload_dir();
143
- $base_url = $this->as3cf->remove_scheme( $uploads['baseurl'] );
 
144
 
145
  if ( false !== strpos( $url, $base_url ) ) {
146
  // Local URL, perform replacement
20
  add_filter( 'the_excerpt', array( $this, 'filter_post' ), 100 );
21
  add_filter( 'content_edit_pre', array( $this, 'filter_post' ) );
22
  add_filter( 'excerpt_edit_pre', array( $this, 'filter_post' ) );
23
+ add_filter( 'as3cf_filter_post_local_to_s3', array( $this, 'filter_post' ) );
24
  // Widgets
25
  add_filter( 'widget_text', array( $this, 'filter_widget' ) );
26
  add_filter( 'widget_form_callback', array( $this, 'filter_widget_form' ), 10, 2 );
141
  */
142
  protected function url_needs_replacing( $url ) {
143
  $uploads = wp_upload_dir();
144
+ $base_url = $this->as3cf->maybe_fix_local_subsite_url( $uploads['baseurl'] );
145
+ $base_url = $this->as3cf->remove_scheme( $base_url );
146
 
147
  if ( false !== strpos( $url, $base_url ) ) {
148
  // Local URL, perform replacement
classes/filters/as3cf-s3-to-local.php CHANGED
@@ -16,6 +16,7 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
16
  // Posts
17
  add_filter( 'content_save_pre', array( $this, 'filter_post' ) );
18
  add_filter( 'excerpt_save_pre', array( $this, 'filter_post' ) );
 
19
  // Widgets
20
  add_filter( 'widget_update_callback', array( $this, 'filter_widget_update' ), 10, 4 );
21
  }
@@ -54,6 +55,12 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
54
  $to_cache = array();
55
  $instance['text'] = $this->process_content( $instance['text'], $cache, $to_cache );
56
 
 
 
 
 
 
 
57
  $this->maybe_update_option_cache( $to_cache );
58
 
59
  return $instance;
16
  // Posts
17
  add_filter( 'content_save_pre', array( $this, 'filter_post' ) );
18
  add_filter( 'excerpt_save_pre', array( $this, 'filter_post' ) );
19
+ add_filter( 'as3cf_filter_post_s3_to_local', array( $this, 'filter_post' ) );
20
  // Widgets
21
  add_filter( 'widget_update_callback', array( $this, 'filter_widget_update' ), 10, 4 );
22
  }
55
  $to_cache = array();
56
  $instance['text'] = $this->process_content( $instance['text'], $cache, $to_cache );
57
 
58
+ // Editing Text Widget in Customizer throws an error if more than one option record is updated.
59
+ // Therefore cache updating has to wait until render or edit via Appearance menu.
60
+ if ( isset( $_POST['wp_customize'] ) && 'on' === $_POST['wp_customize'] ) {
61
+ return $instance;
62
+ }
63
+
64
  $this->maybe_update_option_cache( $to_cache );
65
 
66
  return $instance;
classes/upgrades/as3cf-file-sizes.php CHANGED
@@ -75,11 +75,11 @@ class AS3CF_Upgrade_File_Sizes extends AS3CF_Upgrade {
75
  $s3client = $this->as3cf->get_s3client( $region, true );
76
  $main_file = $s3object['key'];
77
 
78
- $path_parts = pathinfo( $main_file );
79
  $prefix = trailingslashit( dirname( $s3object['key'] ) );
80
 
81
  // Used to search S3 for all files related to an attachment
82
- $search_prefix = $prefix . basename( $main_file, '.' . $path_parts['extension'] );
83
 
84
  $args = array(
85
  'Bucket' => $s3object['bucket'],
75
  $s3client = $this->as3cf->get_s3client( $region, true );
76
  $main_file = $s3object['key'];
77
 
78
+ $ext = pathinfo( $main_file, PATHINFO_EXTENSION );
79
  $prefix = trailingslashit( dirname( $s3object['key'] ) );
80
 
81
  // Used to search S3 for all files related to an attachment
82
+ $search_prefix = $prefix . wp_basename( $main_file, ".$ext" );
83
 
84
  $args = array(
85
  'Bucket' => $s3object['bucket'],
languages/amazon-s3-and-cloudfront-en.pot CHANGED
@@ -8,7 +8,7 @@ msgid ""
8
  msgstr ""
9
  "Project-Id-Version: amazon-s3-and-cloudfront\n"
10
  "Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
11
- "POT-Creation-Date: 2017-01-12 08:46-0500\n"
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,135 +17,135 @@ msgstr ""
17
  "Content-Type: text/plain; charset=UTF-8\n"
18
  "Content-Transfer-Encoding: 8bit\n"
19
 
20
- #: classes/amazon-s3-and-cloudfront.php:108
21
  msgid "Offload S3 Lite"
22
  msgstr ""
23
 
24
- #: classes/amazon-s3-and-cloudfront.php:109
25
  msgid "S3 and CloudFront"
26
  msgstr ""
27
 
28
- #: classes/amazon-s3-and-cloudfront.php:215
29
  #: view/bucket-setting.php:18
30
  msgid "defined in wp-config.php"
31
  msgstr ""
32
 
33
- #: classes/amazon-s3-and-cloudfront.php:874
34
  msgid "Upload aborted by filter 'as3cf_pre_upload_attachment'"
35
  msgstr ""
36
 
37
- #: classes/amazon-s3-and-cloudfront.php:885
38
  #, php-format
39
  msgid "File %s does not exist"
40
  msgstr ""
41
 
42
- #: classes/amazon-s3-and-cloudfront.php:896
43
  #, php-format
44
  msgid "Mime type %s is not allowed"
45
  msgstr ""
46
 
47
- #: classes/amazon-s3-and-cloudfront.php:981
48
  #, php-format
49
  msgid "Error uploading %s to S3: %s"
50
  msgstr ""
51
 
52
- #: classes/amazon-s3-and-cloudfront.php:2184
53
  msgid "Cheatin&#8217; eh?"
54
  msgstr ""
55
 
56
- #: classes/amazon-s3-and-cloudfront.php:2188
57
  msgid "You do not have sufficient permissions to access this page."
58
  msgstr ""
59
 
60
- #: classes/amazon-s3-and-cloudfront.php:2194
61
  msgid "No bucket name provided."
62
  msgstr ""
63
 
64
- #: classes/amazon-s3-and-cloudfront.php:2453
65
  msgid "Error Getting Bucket Region"
66
  msgstr ""
67
 
68
- #: classes/amazon-s3-and-cloudfront.php:2454
69
  #, php-format
70
  msgid "There was an error attempting to get the region of the bucket %s: %s"
71
  msgstr ""
72
 
73
- #: classes/amazon-s3-and-cloudfront.php:2574
74
  msgid ""
75
  "This is a test file to check if the user has write permission to S3. Delete "
76
  "me if found."
77
  msgstr ""
78
 
79
- #: classes/amazon-s3-and-cloudfront.php:2606
80
  #, php-format
81
  msgid ""
82
  "There was an error attempting to check the permissions of the bucket %s: %s"
83
  msgstr ""
84
 
85
- #: classes/amazon-s3-and-cloudfront.php:2663
86
  msgid "Error creating bucket"
87
  msgstr ""
88
 
89
- #: classes/amazon-s3-and-cloudfront.php:2664
90
  msgid "Bucket name too short."
91
  msgstr ""
92
 
93
- #: classes/amazon-s3-and-cloudfront.php:2665
94
  msgid "Bucket name too long."
95
  msgstr ""
96
 
97
- #: classes/amazon-s3-and-cloudfront.php:2666
98
  msgid ""
99
  "Invalid character. Bucket names can contain lowercase letters, numbers, "
100
  "periods and hyphens."
101
  msgstr ""
102
 
103
- #: classes/amazon-s3-and-cloudfront.php:2667
104
  msgid "Error saving bucket"
105
  msgstr ""
106
 
107
- #: classes/amazon-s3-and-cloudfront.php:2668
108
  msgid "Error fetching buckets"
109
  msgstr ""
110
 
111
- #: classes/amazon-s3-and-cloudfront.php:2669
112
  msgid "Error getting URL preview: "
113
  msgstr ""
114
 
115
- #: classes/amazon-s3-and-cloudfront.php:2670
116
  msgid "The changes you made will be lost if you navigate away from this page"
117
  msgstr ""
118
 
119
- #: classes/amazon-s3-and-cloudfront.php:2671
120
  msgid "Getting diagnostic info..."
121
  msgstr ""
122
 
123
- #: classes/amazon-s3-and-cloudfront.php:2672
124
  msgid "Error getting diagnostic info: "
125
  msgstr ""
126
 
127
- #: classes/amazon-s3-and-cloudfront.php:2740
128
  msgid "Cheatin' eh?"
129
  msgstr ""
130
 
131
- #: classes/amazon-s3-and-cloudfront.php:2848
132
  msgctxt "Show the media library tab"
133
  msgid "Media Library"
134
  msgstr ""
135
 
136
- #: classes/amazon-s3-and-cloudfront.php:2849
137
  msgctxt "Show the support tab"
138
  msgid "Support"
139
  msgstr ""
140
 
141
- #: classes/amazon-s3-and-cloudfront.php:3066
142
  #, php-format
143
  msgid ""
144
  "<strong>WP Offload S3</strong> &mdash; The file %s has been given %s "
145
  "permissions on Amazon S3."
146
  msgstr ""
147
 
148
- #: classes/amazon-s3-and-cloudfront.php:3085
149
  msgid ""
150
  "<strong>WP Offload S3 Requirement Missing</strong> &mdash; Looks like you "
151
  "don't have an image manipulation library installed on this server and "
@@ -153,11 +153,11 @@ msgid ""
153
  "Please setup GD or ImageMagick."
154
  msgstr ""
155
 
156
- #: classes/amazon-s3-and-cloudfront.php:3759
157
  msgid "Quick Start Guide"
158
  msgstr ""
159
 
160
- #: classes/amazon-s3-and-cloudfront.php:3761
161
  #, php-format
162
  msgid ""
163
  "Looks like we don't have write access to this bucket. It's likely that the "
@@ -166,7 +166,7 @@ msgid ""
166
  "correctly."
167
  msgstr ""
168
 
169
- #: classes/amazon-s3-and-cloudfront.php:3763
170
  #, php-format
171
  msgid ""
172
  "Looks like we don't have access to the buckets. It's likely that the user "
@@ -174,39 +174,39 @@ msgid ""
174
  "Please see our %s for instructions on setting up permissions correctly."
175
  msgstr ""
176
 
177
- #: classes/amazon-s3-and-cloudfront.php:3914
178
  msgid "WP Offload S3 Activation"
179
  msgstr ""
180
 
181
- #: classes/amazon-s3-and-cloudfront.php:3915
182
  msgid ""
183
  "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
184
  "automatically deactivated WP Offload S3 Lite."
185
  msgstr ""
186
 
187
- #: classes/amazon-s3-and-cloudfront.php:3917
188
  msgid "WP Offload S3 Lite Activation"
189
  msgstr ""
190
 
191
- #: classes/amazon-s3-and-cloudfront.php:3918
192
  msgid ""
193
  "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
194
  "automatically deactivated WP Offload S3."
195
  msgstr ""
196
 
197
- #: classes/amazon-s3-and-cloudfront.php:3992
198
  msgid "More info"
199
  msgstr ""
200
 
201
- #: classes/amazon-s3-and-cloudfront.php:4083
202
  msgid "this doc"
203
  msgstr ""
204
 
205
- #: classes/amazon-s3-and-cloudfront.php:4085
206
  msgid "WP Offload S3 Feature Removed"
207
  msgstr ""
208
 
209
- #: classes/amazon-s3-and-cloudfront.php:4086
210
  #, php-format
211
  msgid ""
212
  "You had the \"Always non-SSL\" option selected in your settings, but we've "
@@ -217,32 +217,32 @@ msgid ""
217
  "to the old behavior."
218
  msgstr ""
219
 
220
- #: classes/amazon-s3-and-cloudfront.php:4114
221
- #: classes/amazon-s3-and-cloudfront.php:4207
222
  msgid "Amazon S3"
223
  msgstr ""
224
 
225
- #: classes/amazon-s3-and-cloudfront.php:4208
226
  msgctxt "Amazon S3 bucket"
227
  msgid "Bucket"
228
  msgstr ""
229
 
230
- #: classes/amazon-s3-and-cloudfront.php:4209
231
  msgctxt "Path to file on Amazon S3"
232
  msgid "Path"
233
  msgstr ""
234
 
235
- #: classes/amazon-s3-and-cloudfront.php:4210
236
  msgctxt "Location of Amazon S3 bucket"
237
  msgid "Region"
238
  msgstr ""
239
 
240
- #: classes/amazon-s3-and-cloudfront.php:4211
241
  msgctxt "Access control list of the file on Amazon S3"
242
  msgid "Access"
243
  msgstr ""
244
 
245
- #: classes/amazon-s3-and-cloudfront.php:4212
246
  msgid "URL"
247
  msgstr ""
248
 
@@ -254,15 +254,15 @@ msgstr ""
254
  msgid "Invalid notice ID."
255
  msgstr ""
256
 
257
- #: classes/as3cf-plugin-compatibility.php:192
258
  msgid "WP Offload S3 Compatibility Addons"
259
  msgstr ""
260
 
261
- #: classes/as3cf-plugin-compatibility.php:194
262
  msgid "compatibility addons"
263
  msgstr ""
264
 
265
- #: classes/as3cf-plugin-compatibility.php:195
266
  #, php-format
267
  msgid ""
268
  "To get WP Offload S3 to work with certain 3rd party plugins, you might need "
@@ -271,7 +271,7 @@ msgid ""
271
  "about each addon to determine if you need it or not."
272
  msgstr ""
273
 
274
- #: classes/as3cf-plugin-compatibility.php:201
275
  #, php-format
276
  msgid ""
277
  "You will need to purchase a license to get access to these addons. If you're "
@@ -279,17 +279,17 @@ msgid ""
279
  "to %s."
280
  msgstr ""
281
 
282
- #: classes/as3cf-plugin-compatibility.php:202
283
  msgid "View Licenses"
284
  msgstr ""
285
 
286
- #: classes/as3cf-plugin-compatibility.php:664
287
  #, php-format
288
  msgid "The local directory %s does not exist and could not be created."
289
  msgstr ""
290
 
291
- #: classes/as3cf-plugin-compatibility.php:665
292
- #: classes/as3cf-plugin-compatibility.php:677
293
  #: classes/upgrades/as3cf-meta-wp-error.php:81
294
  #, php-format
295
  msgid "There was an error attempting to download the file %s from S3: %s"
8
  msgstr ""
9
  "Project-Id-Version: amazon-s3-and-cloudfront\n"
10
  "Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
11
+ "POT-Creation-Date: 2017-03-13 13:16+0000\n"
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
17
  "Content-Type: text/plain; charset=UTF-8\n"
18
  "Content-Transfer-Encoding: 8bit\n"
19
 
20
+ #: classes/amazon-s3-and-cloudfront.php:115
21
  msgid "Offload S3 Lite"
22
  msgstr ""
23
 
24
+ #: classes/amazon-s3-and-cloudfront.php:116
25
  msgid "S3 and CloudFront"
26
  msgstr ""
27
 
28
+ #: classes/amazon-s3-and-cloudfront.php:224
29
  #: view/bucket-setting.php:18
30
  msgid "defined in wp-config.php"
31
  msgstr ""
32
 
33
+ #: classes/amazon-s3-and-cloudfront.php:886
34
  msgid "Upload aborted by filter 'as3cf_pre_upload_attachment'"
35
  msgstr ""
36
 
37
+ #: classes/amazon-s3-and-cloudfront.php:897
38
  #, php-format
39
  msgid "File %s does not exist"
40
  msgstr ""
41
 
42
+ #: classes/amazon-s3-and-cloudfront.php:908
43
  #, php-format
44
  msgid "Mime type %s is not allowed"
45
  msgstr ""
46
 
47
+ #: classes/amazon-s3-and-cloudfront.php:993
48
  #, php-format
49
  msgid "Error uploading %s to S3: %s"
50
  msgstr ""
51
 
52
+ #: classes/amazon-s3-and-cloudfront.php:2191
53
  msgid "Cheatin&#8217; eh?"
54
  msgstr ""
55
 
56
+ #: classes/amazon-s3-and-cloudfront.php:2195
57
  msgid "You do not have sufficient permissions to access this page."
58
  msgstr ""
59
 
60
+ #: classes/amazon-s3-and-cloudfront.php:2201
61
  msgid "No bucket name provided."
62
  msgstr ""
63
 
64
+ #: classes/amazon-s3-and-cloudfront.php:2465
65
  msgid "Error Getting Bucket Region"
66
  msgstr ""
67
 
68
+ #: classes/amazon-s3-and-cloudfront.php:2466
69
  #, php-format
70
  msgid "There was an error attempting to get the region of the bucket %s: %s"
71
  msgstr ""
72
 
73
+ #: classes/amazon-s3-and-cloudfront.php:2585
74
  msgid ""
75
  "This is a test file to check if the user has write permission to S3. Delete "
76
  "me if found."
77
  msgstr ""
78
 
79
+ #: classes/amazon-s3-and-cloudfront.php:2617
80
  #, php-format
81
  msgid ""
82
  "There was an error attempting to check the permissions of the bucket %s: %s"
83
  msgstr ""
84
 
85
+ #: classes/amazon-s3-and-cloudfront.php:2674
86
  msgid "Error creating bucket"
87
  msgstr ""
88
 
89
+ #: classes/amazon-s3-and-cloudfront.php:2675
90
  msgid "Bucket name too short."
91
  msgstr ""
92
 
93
+ #: classes/amazon-s3-and-cloudfront.php:2676
94
  msgid "Bucket name too long."
95
  msgstr ""
96
 
97
+ #: classes/amazon-s3-and-cloudfront.php:2677
98
  msgid ""
99
  "Invalid character. Bucket names can contain lowercase letters, numbers, "
100
  "periods and hyphens."
101
  msgstr ""
102
 
103
+ #: classes/amazon-s3-and-cloudfront.php:2678
104
  msgid "Error saving bucket"
105
  msgstr ""
106
 
107
+ #: classes/amazon-s3-and-cloudfront.php:2679
108
  msgid "Error fetching buckets"
109
  msgstr ""
110
 
111
+ #: classes/amazon-s3-and-cloudfront.php:2680
112
  msgid "Error getting URL preview: "
113
  msgstr ""
114
 
115
+ #: classes/amazon-s3-and-cloudfront.php:2681
116
  msgid "The changes you made will be lost if you navigate away from this page"
117
  msgstr ""
118
 
119
+ #: classes/amazon-s3-and-cloudfront.php:2682
120
  msgid "Getting diagnostic info..."
121
  msgstr ""
122
 
123
+ #: classes/amazon-s3-and-cloudfront.php:2683
124
  msgid "Error getting diagnostic info: "
125
  msgstr ""
126
 
127
+ #: classes/amazon-s3-and-cloudfront.php:2751
128
  msgid "Cheatin' eh?"
129
  msgstr ""
130
 
131
+ #: classes/amazon-s3-and-cloudfront.php:2858
132
  msgctxt "Show the media library tab"
133
  msgid "Media Library"
134
  msgstr ""
135
 
136
+ #: classes/amazon-s3-and-cloudfront.php:2859
137
  msgctxt "Show the support tab"
138
  msgid "Support"
139
  msgstr ""
140
 
141
+ #: classes/amazon-s3-and-cloudfront.php:3076
142
  #, php-format
143
  msgid ""
144
  "<strong>WP Offload S3</strong> &mdash; The file %s has been given %s "
145
  "permissions on Amazon S3."
146
  msgstr ""
147
 
148
+ #: classes/amazon-s3-and-cloudfront.php:3095
149
  msgid ""
150
  "<strong>WP Offload S3 Requirement Missing</strong> &mdash; Looks like you "
151
  "don't have an image manipulation library installed on this server and "
153
  "Please setup GD or ImageMagick."
154
  msgstr ""
155
 
156
+ #: classes/amazon-s3-and-cloudfront.php:3774
157
  msgid "Quick Start Guide"
158
  msgstr ""
159
 
160
+ #: classes/amazon-s3-and-cloudfront.php:3776
161
  #, php-format
162
  msgid ""
163
  "Looks like we don't have write access to this bucket. It's likely that the "
166
  "correctly."
167
  msgstr ""
168
 
169
+ #: classes/amazon-s3-and-cloudfront.php:3778
170
  #, php-format
171
  msgid ""
172
  "Looks like we don't have access to the buckets. It's likely that the user "
174
  "Please see our %s for instructions on setting up permissions correctly."
175
  msgstr ""
176
 
177
+ #: classes/amazon-s3-and-cloudfront.php:3929
178
  msgid "WP Offload S3 Activation"
179
  msgstr ""
180
 
181
+ #: classes/amazon-s3-and-cloudfront.php:3930
182
  msgid ""
183
  "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
184
  "automatically deactivated WP Offload S3 Lite."
185
  msgstr ""
186
 
187
+ #: classes/amazon-s3-and-cloudfront.php:3932
188
  msgid "WP Offload S3 Lite Activation"
189
  msgstr ""
190
 
191
+ #: classes/amazon-s3-and-cloudfront.php:3933
192
  msgid ""
193
  "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
194
  "automatically deactivated WP Offload S3."
195
  msgstr ""
196
 
197
+ #: classes/amazon-s3-and-cloudfront.php:4007
198
  msgid "More info"
199
  msgstr ""
200
 
201
+ #: classes/amazon-s3-and-cloudfront.php:4098
202
  msgid "this doc"
203
  msgstr ""
204
 
205
+ #: classes/amazon-s3-and-cloudfront.php:4100
206
  msgid "WP Offload S3 Feature Removed"
207
  msgstr ""
208
 
209
+ #: classes/amazon-s3-and-cloudfront.php:4101
210
  #, php-format
211
  msgid ""
212
  "You had the \"Always non-SSL\" option selected in your settings, but we've "
217
  "to the old behavior."
218
  msgstr ""
219
 
220
+ #: classes/amazon-s3-and-cloudfront.php:4131
221
+ #: classes/amazon-s3-and-cloudfront.php:4229
222
  msgid "Amazon S3"
223
  msgstr ""
224
 
225
+ #: classes/amazon-s3-and-cloudfront.php:4230
226
  msgctxt "Amazon S3 bucket"
227
  msgid "Bucket"
228
  msgstr ""
229
 
230
+ #: classes/amazon-s3-and-cloudfront.php:4231
231
  msgctxt "Path to file on Amazon S3"
232
  msgid "Path"
233
  msgstr ""
234
 
235
+ #: classes/amazon-s3-and-cloudfront.php:4232
236
  msgctxt "Location of Amazon S3 bucket"
237
  msgid "Region"
238
  msgstr ""
239
 
240
+ #: classes/amazon-s3-and-cloudfront.php:4233
241
  msgctxt "Access control list of the file on Amazon S3"
242
  msgid "Access"
243
  msgstr ""
244
 
245
+ #: classes/amazon-s3-and-cloudfront.php:4234
246
  msgid "URL"
247
  msgstr ""
248
 
254
  msgid "Invalid notice ID."
255
  msgstr ""
256
 
257
+ #: classes/as3cf-plugin-compatibility.php:193
258
  msgid "WP Offload S3 Compatibility Addons"
259
  msgstr ""
260
 
261
+ #: classes/as3cf-plugin-compatibility.php:195
262
  msgid "compatibility addons"
263
  msgstr ""
264
 
265
+ #: classes/as3cf-plugin-compatibility.php:196
266
  #, php-format
267
  msgid ""
268
  "To get WP Offload S3 to work with certain 3rd party plugins, you might need "
271
  "about each addon to determine if you need it or not."
272
  msgstr ""
273
 
274
+ #: classes/as3cf-plugin-compatibility.php:202
275
  #, php-format
276
  msgid ""
277
  "You will need to purchase a license to get access to these addons. If you're "
279
  "to %s."
280
  msgstr ""
281
 
282
+ #: classes/as3cf-plugin-compatibility.php:203
283
  msgid "View Licenses"
284
  msgstr ""
285
 
286
+ #: classes/as3cf-plugin-compatibility.php:669
287
  #, php-format
288
  msgid "The local directory %s does not exist and could not be created."
289
  msgstr ""
290
 
291
+ #: classes/as3cf-plugin-compatibility.php:670
292
+ #: classes/as3cf-plugin-compatibility.php:682
293
  #: classes/upgrades/as3cf-meta-wp-error.php:81
294
  #, php-format
295
  msgid "There was an error attempting to download the file %s from S3: %s"
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: bradt, deliciousbrains
3
  Tags: uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
4
  Requires at least: 4.4
5
- Tested up to: 4.7.1
6
- Stable tag: 1.1.5
7
  License: GPLv3
8
 
9
  Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
@@ -65,6 +65,17 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
65
 
66
  == Changelog ==
67
 
 
 
 
 
 
 
 
 
 
 
 
68
  = WP Offload S3 Lite 1.1.5 - 2017-01-12 =
69
  * Improvement: Filter custom CSS - S3 URLs will no longer be saved to the database
70
  * Bug fix: PDF previews have incorrect MIME type
2
  Contributors: bradt, deliciousbrains
3
  Tags: uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
4
  Requires at least: 4.4
5
+ Tested up to: 4.7.3
6
+ Stable tag: 1.1.6
7
  License: GPLv3
8
 
9
  Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
65
 
66
  == Changelog ==
67
 
68
+ = WP Offload S3 Lite 1.1.6 - 2017-03-13 =
69
+ * New: Compatibility with [Advanced Custom Fields](https://wordpress.org/plugins/advanced-custom-fields/)
70
+ * New: `as3cf_filter_post_local_to_s3` and `as3cf_filter_post_s3_to_local` filters added for filtering S3 URLs in custom content
71
+ * Improvement: Ensure files uploaded using `media_handle_sideload` have unique filename on S3 when 'Remove Files From Server' enabled
72
+ * Bug fix: Files uploaded to S3 with empty filenames when the filename started with non-latin characters
73
+ * Bug fix: Audio files with private ACL not working with WordPress's default media player
74
+ * Bug fix: S3 API version not passed to S3 client
75
+ * Bug fix: Content added to text widgets via the Customizer not saved
76
+ * Bug fix: Original file not removed locally when cropped via the Customizer and 'Remove Files From Server' enabled
77
+ * Bug fix: Incorrect Media Library URLs saved to the database when WordPress installed in a subdirectory
78
+
79
  = WP Offload S3 Lite 1.1.5 - 2017-01-12 =
80
  * Improvement: Filter custom CSS - S3 URLs will no longer be saved to the database
81
  * Bug fix: PDF previews have incorrect MIME type
view/attachment-metabox.php CHANGED
@@ -6,28 +6,28 @@
6
  <?php else : ?>
7
  <div class="misc-pub-section">
8
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'bucket' ); ?>:</div>
9
- <input type="text" class="widefat" readonly="readonly" value="<?php echo $s3object['bucket']; ?>">
10
  </div>
11
  <div class="misc-pub-section">
12
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'key' ); ?>:</div>
13
- <input type="text" class="widefat" readonly="readonly" value="<?php echo $s3object['key']; ?>">
14
  </div>
15
  <?php if ( isset( $s3object['region'] ) && $s3object['region'] ) : ?>
16
  <div class="misc-pub-section">
17
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'region' ); ?>:</div>
18
- <div class="s3-value"><?php echo $s3object['region']; ?></div>
19
  </div>
20
  <?php endif; ?>
21
  <div class="misc-pub-section">
22
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'acl' ); ?>:</div>
23
- <div class="s3-value">
24
  <?php echo $this->get_acl_value_string( $s3object['acl'] ); ?>
25
  </div>
26
  </div>
27
  <?php if ( $user_can_perform_actions && ! $local_file_exists ) : ?>
28
  <div class="misc-pub-section">
29
  <div class="not-copied"><?php _e( 'File does not exist on server', 'amazon-s3-and-cloudfront' ); ?></div>
30
- <a href="<?php echo $this->get_media_action_url( 'download', $post->ID, $sendback ); ?>">
31
  <?php echo $this->get_media_action_strings( 'download' ); ?>
32
  </a>
33
  </div>
@@ -39,14 +39,14 @@
39
  <div class="s3-actions">
40
  <?php if ( $s3object ) : ?>
41
  <div class="remove-action">
42
- <a href="<?php echo $this->get_media_action_url( 'remove', $post->ID, $sendback ); ?>" class="<?php echo ( ! $local_file_exists ) ? 'local-warning' : ''; ?>">
43
  <?php echo $this->get_media_action_strings( 'remove' ); ?>
44
  </a>
45
  </div>
46
  <?php endif; ?>
47
  <?php if ( $local_file_exists ) : ?>
48
  <div class="copy-action">
49
- <a href="<?php echo $this->get_media_action_url( 'copy', $post->ID, $sendback ); ?>" class="button button-secondary">
50
  <?php echo $this->get_media_action_strings( 'copy' ); ?>
51
  </a>
52
  </div>
6
  <?php else : ?>
7
  <div class="misc-pub-section">
8
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'bucket' ); ?>:</div>
9
+ <input type="text" id="as3cf-bucket" class="widefat" readonly="readonly" value="<?php echo $s3object['bucket']; ?>">
10
  </div>
11
  <div class="misc-pub-section">
12
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'key' ); ?>:</div>
13
+ <input type="text" id="as3cf-key" class="widefat" readonly="readonly" value="<?php echo $s3object['key']; ?>">
14
  </div>
15
  <?php if ( isset( $s3object['region'] ) && $s3object['region'] ) : ?>
16
  <div class="misc-pub-section">
17
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'region' ); ?>:</div>
18
+ <div id="as3cf-region" class="s3-value"><?php echo $s3object['region']; ?></div>
19
  </div>
20
  <?php endif; ?>
21
  <div class="misc-pub-section">
22
  <div class="s3-key"><?php echo $this->get_media_action_strings( 'acl' ); ?>:</div>
23
+ <div id="as3cf-acl" class="s3-value">
24
  <?php echo $this->get_acl_value_string( $s3object['acl'] ); ?>
25
  </div>
26
  </div>
27
  <?php if ( $user_can_perform_actions && ! $local_file_exists ) : ?>
28
  <div class="misc-pub-section">
29
  <div class="not-copied"><?php _e( 'File does not exist on server', 'amazon-s3-and-cloudfront' ); ?></div>
30
+ <a id="as3cf-download-action" href="<?php echo $this->get_media_action_url( 'download', $post->ID, $sendback ); ?>">
31
  <?php echo $this->get_media_action_strings( 'download' ); ?>
32
  </a>
33
  </div>
39
  <div class="s3-actions">
40
  <?php if ( $s3object ) : ?>
41
  <div class="remove-action">
42
+ <a id="as3cf-remove-action" href="<?php echo $this->get_media_action_url( 'remove', $post->ID, $sendback ); ?>" class="<?php echo ( ! $local_file_exists ) ? 'local-warning' : ''; ?>">
43
  <?php echo $this->get_media_action_strings( 'remove' ); ?>
44
  </a>
45
  </div>
46
  <?php endif; ?>
47
  <?php if ( $local_file_exists ) : ?>
48
  <div class="copy-action">
49
+ <a id="as3cf-copy-action" href="<?php echo $this->get_media_action_url( 'copy', $post->ID, $sendback ); ?>" class="button button-secondary">
50
  <?php echo $this->get_media_action_strings( 'copy' ); ?>
51
  </a>
52
  </div>
view/wordpress-org-support.php CHANGED
@@ -3,7 +3,7 @@
3
 
4
  <p><?php printf( __( 'You may ask the WordPress community for help by posting to the <a href="%s">WordPress.org support forum</a>. Response time can range from a few days to a few weeks and will likely be from a non-developer.', 'amazon-s3-and-cloudfront'), 'https://wordpress.org/plugins/amazon-s3-and-cloudfront/' ); ?></p>
5
 
6
- <p class="upgrade-to-pro"><?php printf( __( 'If you want a <strong>timely response via email from a developer</strong> who works on this plugin, <a href="%s">upgrade</a> and send us an email.', 'amazon-s3-and-cloudfront' ), 'https://deliciousbrains.com/wp-offload-s3/?utm_source=insideplugin&utm_medium=web&utm_content=support-tab&utm_campaign=freeplugin-as3cf' ); ?></p>
7
 
8
  <p><?php printf( __( 'If you\'ve found a bug, please <a href="%s">submit an issue on GitHub</a>.', 'amazon-s3-and-cloudfront' ), 'https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront/issues' ); ?></p>
9
 
3
 
4
  <p><?php printf( __( 'You may ask the WordPress community for help by posting to the <a href="%s">WordPress.org support forum</a>. Response time can range from a few days to a few weeks and will likely be from a non-developer.', 'amazon-s3-and-cloudfront'), 'https://wordpress.org/plugins/amazon-s3-and-cloudfront/' ); ?></p>
5
 
6
+ <p class="upgrade-to-pro"><?php printf( __( 'If you want a <strong>timely response via email from a developer</strong> who works on this plugin, <a href="%s">upgrade</a> and send us an email.', 'amazon-s3-and-cloudfront' ), 'https://deliciousbrains.com/wp-offload-s3/?utm_source=insideplugin&utm_medium=web&utm_content=support-tab&utm_campaign=os3-free-plugin' ); ?></p>
7
 
8
  <p><?php printf( __( 'If you\'ve found a bug, please <a href="%s">submit an issue on GitHub</a>.', 'amazon-s3-and-cloudfront' ), 'https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront/issues' ); ?></p>
9
 
wordpress-s3.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Offload S3 Lite
4
  Plugin URI: http://wordpress.org/extend/plugins/amazon-s3-and-cloudfront/
5
  Description: Automatically copies media uploads to Amazon S3 for storage and delivery. Optionally configure Amazon CloudFront for even faster delivery.
6
  Author: Delicious Brains
7
- Version: 1.1.5
8
  Author URI: http://deliciousbrains.com/
9
  Network: True
10
  Text Domain: amazon-s3-and-cloudfront
@@ -26,7 +26,7 @@ Domain Path: /languages/
26
  // Then completely rewritten.
27
  */
28
 
29
- $GLOBALS['aws_meta']['amazon-s3-and-cloudfront']['version'] = '1.1.5';
30
 
31
  $aws_plugin_version_required = '1.0.1';
32
 
@@ -76,6 +76,11 @@ function as3cf_init( $aws ) {
76
  require_once $abspath . '/classes/as3cf-stream-wrapper.php';
77
  require_once $abspath . '/classes/as3cf-plugin-compatibility.php';
78
  require_once $abspath . '/classes/amazon-s3-and-cloudfront.php';
 
 
 
 
 
79
  $as3cf = new Amazon_S3_And_CloudFront( __FILE__, $aws );
80
  }
81
 
4
  Plugin URI: http://wordpress.org/extend/plugins/amazon-s3-and-cloudfront/
5
  Description: Automatically copies media uploads to Amazon S3 for storage and delivery. Optionally configure Amazon CloudFront for even faster delivery.
6
  Author: Delicious Brains
7
+ Version: 1.1.6
8
  Author URI: http://deliciousbrains.com/
9
  Network: True
10
  Text Domain: amazon-s3-and-cloudfront
26
  // Then completely rewritten.
27
  */
28
 
29
+ $GLOBALS['aws_meta']['amazon-s3-and-cloudfront']['version'] = '1.1.6';
30
 
31
  $aws_plugin_version_required = '1.0.1';
32
 
76
  require_once $abspath . '/classes/as3cf-stream-wrapper.php';
77
  require_once $abspath . '/classes/as3cf-plugin-compatibility.php';
78
  require_once $abspath . '/classes/amazon-s3-and-cloudfront.php';
79
+
80
+ // Autoloader
81
+ require_once $abspath . '/wp-offload-s3-autoloader.php';
82
+ new WP_Offload_S3_Autoloader( 'WP_Offload_S3', $abspath );
83
+
84
  $as3cf = new Amazon_S3_And_CloudFront( __FILE__, $aws );
85
  }
86
 
wp-offload-s3-autoloader.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Check if already defined
4
+ if ( ! class_exists( 'WP_Offload_S3_Autoloader' ) ) {
5
+
6
+ class WP_Offload_S3_Autoloader {
7
+
8
+ /**
9
+ * @var string
10
+ */
11
+ protected $abspath;
12
+
13
+ /**
14
+ * @var string
15
+ */
16
+ protected $prefix;
17
+
18
+ /**
19
+ * @var string
20
+ */
21
+ protected $vendor = 'DeliciousBrains';
22
+
23
+ /**
24
+ * Autoloader constructor.
25
+ *
26
+ * @param string $prefix
27
+ * @param string $abspath
28
+ */
29
+ public function __construct( $prefix, $abspath ) {
30
+ $this->prefix = $prefix;
31
+ $this->abspath = $abspath;
32
+
33
+ spl_autoload_register( array( $this, 'autoloader' ) );
34
+ }
35
+
36
+ /**
37
+ * Autoloader.
38
+ *
39
+ * @param string $class_name
40
+ */
41
+ public function autoloader( $class_name ) {
42
+ if ( ! $this->class_belongs_to_plugin( $class_name ) ) {
43
+ return;
44
+ }
45
+
46
+ $path = $this->get_classes_directory() . $this->get_class_path( $class_name );
47
+
48
+ if ( file_exists( $path ) ) {
49
+ require_once $path;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Class belong to plugin.
55
+ *
56
+ * @param string $class_name
57
+ *
58
+ * @return bool
59
+ */
60
+ protected function class_belongs_to_plugin( $class_name ) {
61
+ if ( 0 !== strpos( $class_name, $this->vendor . '\\' . $this->prefix . '\\' ) ) {
62
+ return false;
63
+ }
64
+
65
+ return true;
66
+ }
67
+
68
+ /**
69
+ * Get class path.
70
+ *
71
+ * @param string $class_name
72
+ *
73
+ * @return string
74
+ */
75
+ protected function get_class_path( $class_name ) {
76
+ $parts = explode( '\\', strtolower( $class_name ) );
77
+ $parts = array_slice( $parts, 2 );
78
+
79
+ $filename = implode( DIRECTORY_SEPARATOR, $parts ) . '.php';
80
+
81
+ return str_replace( '_', '-', strtolower( $filename ) );
82
+ }
83
+
84
+ /**
85
+ * Get classes directory.
86
+ *
87
+ * @return string
88
+ */
89
+ protected function get_classes_directory() {
90
+ return $this->abspath . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR;
91
+ }
92
+
93
+ }
94
+ }