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 | ![]() |
Version | 1.1.6 |
Comparing to | |
See all releases |
Code changes from version 1.1.5 to 1.1.6
- README.md +13 -2
- assets/js/media.js +4 -1
- assets/js/media.min.js +1 -1
- assets/js/modal.js +19 -4
- assets/js/modal.min.js +1 -1
- classes/amazon-s3-and-cloudfront.php +175 -93
- classes/as3cf-filter.php +3 -3
- classes/as3cf-plugin-compatibility.php +30 -3
- classes/as3cf-upgrade-filter-post.php +4 -4
- classes/filters/as3cf-local-to-s3.php +3 -1
- classes/filters/as3cf-s3-to-local.php +7 -0
- classes/upgrades/as3cf-file-sizes.php +2 -2
- languages/amazon-s3-and-cloudfront-en.pot +56 -56
- readme.txt +13 -2
- view/attachment-metabox.php +7 -7
- view/wordpress-org-support.php +1 -1
- wordpress-s3.php +7 -2
- wp-offload-s3-autoloader.php +94 -0
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.
|
6 |
-
**Stable tag:** 1.1.
|
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 (
|
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
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
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 {
|
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(
|
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
|
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
|
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'] ) &&
|
|
|
|
|
|
|
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
|
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 .
|
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 =
|
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 .
|
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,
|
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 |
-
*
|
1283 |
-
* This only applies when the remove local file option is enabled
|
1284 |
*
|
1285 |
-
* @param array
|
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 $
|
1292 |
}
|
1293 |
|
1294 |
-
$filename = $file['name'];
|
1295 |
-
|
1296 |
// sanitize the file name before we begin processing
|
1297 |
$filename = sanitize_file_name( $filename );
|
1298 |
|
1299 |
-
//
|
1300 |
-
$
|
1301 |
-
$ext =
|
1302 |
-
$name =
|
1303 |
|
1304 |
-
//
|
1305 |
if ( $name === $ext ) {
|
1306 |
$name = '';
|
1307 |
}
|
1308 |
|
1309 |
-
//
|
1310 |
$ext = strtolower( $ext );
|
1311 |
-
$filename = $
|
1312 |
$time = current_time( 'mysql' );
|
1313 |
|
1314 |
-
// Get time if uploaded in post screen
|
1315 |
-
|
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 $
|
1323 |
}
|
1324 |
|
1325 |
-
$
|
1326 |
|
1327 |
-
return $
|
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
|
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 |
-
|
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
|
|
|
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 =
|
2081 |
} else {
|
2082 |
-
$file_name =
|
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 =
|
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
|
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 |
-
|
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(
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2419 |
-
|
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
|
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 =
|
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> — 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> — 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 =
|
|
|
|
|
|
|
|
|
|
|
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 =
|
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
|
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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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(
|
|
|
|
|
|
|
|
|
|
|
|
|
4234 |
|
4235 |
-
wp_localize_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 |
-
$
|
4351 |
-
$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> — 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> — 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( '/&_=[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 |
-
|
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]#x2F;', '', $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 ) ) .
|
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 =
|
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 =
|
350 |
-
$old_file_name =
|
351 |
-
$new_file_name =
|
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 =
|
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->
|
|
|
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 |
-
$
|
79 |
$prefix = trailingslashit( dirname( $s3object['key'] ) );
|
80 |
|
81 |
// Used to search S3 for all files related to an attachment
|
82 |
-
$search_prefix = $prefix .
|
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-
|
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:
|
21 |
msgid "Offload S3 Lite"
|
22 |
msgstr ""
|
23 |
|
24 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
25 |
msgid "S3 and CloudFront"
|
26 |
msgstr ""
|
27 |
|
28 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
29 |
#: view/bucket-setting.php:18
|
30 |
msgid "defined in wp-config.php"
|
31 |
msgstr ""
|
32 |
|
33 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
34 |
msgid "Upload aborted by filter 'as3cf_pre_upload_attachment'"
|
35 |
msgstr ""
|
36 |
|
37 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
38 |
#, php-format
|
39 |
msgid "File %s does not exist"
|
40 |
msgstr ""
|
41 |
|
42 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
43 |
#, php-format
|
44 |
msgid "Mime type %s is not allowed"
|
45 |
msgstr ""
|
46 |
|
47 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
48 |
#, php-format
|
49 |
msgid "Error uploading %s to S3: %s"
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
53 |
msgid "Cheatin’ eh?"
|
54 |
msgstr ""
|
55 |
|
56 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
57 |
msgid "You do not have sufficient permissions to access this page."
|
58 |
msgstr ""
|
59 |
|
60 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
61 |
msgid "No bucket name provided."
|
62 |
msgstr ""
|
63 |
|
64 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
65 |
msgid "Error Getting Bucket Region"
|
66 |
msgstr ""
|
67 |
|
68 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
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:
|
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:
|
86 |
msgid "Error creating bucket"
|
87 |
msgstr ""
|
88 |
|
89 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
90 |
msgid "Bucket name too short."
|
91 |
msgstr ""
|
92 |
|
93 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
94 |
msgid "Bucket name too long."
|
95 |
msgstr ""
|
96 |
|
97 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
104 |
msgid "Error saving bucket"
|
105 |
msgstr ""
|
106 |
|
107 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
108 |
msgid "Error fetching buckets"
|
109 |
msgstr ""
|
110 |
|
111 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
112 |
msgid "Error getting URL preview: "
|
113 |
msgstr ""
|
114 |
|
115 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
120 |
msgid "Getting diagnostic info..."
|
121 |
msgstr ""
|
122 |
|
123 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
124 |
msgid "Error getting diagnostic info: "
|
125 |
msgstr ""
|
126 |
|
127 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
128 |
msgid "Cheatin' eh?"
|
129 |
msgstr ""
|
130 |
|
131 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
132 |
msgctxt "Show the media library tab"
|
133 |
msgid "Media Library"
|
134 |
msgstr ""
|
135 |
|
136 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
137 |
msgctxt "Show the support tab"
|
138 |
msgid "Support"
|
139 |
msgstr ""
|
140 |
|
141 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
142 |
#, php-format
|
143 |
msgid ""
|
144 |
"<strong>WP Offload S3</strong> — The file %s has been given %s "
|
145 |
"permissions on Amazon S3."
|
146 |
msgstr ""
|
147 |
|
148 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
149 |
msgid ""
|
150 |
"<strong>WP Offload S3 Requirement Missing</strong> — 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:
|
157 |
msgid "Quick Start Guide"
|
158 |
msgstr ""
|
159 |
|
160 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
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:
|
178 |
msgid "WP Offload S3 Activation"
|
179 |
msgstr ""
|
180 |
|
181 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
188 |
msgid "WP Offload S3 Lite Activation"
|
189 |
msgstr ""
|
190 |
|
191 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
198 |
msgid "More info"
|
199 |
msgstr ""
|
200 |
|
201 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
202 |
msgid "this doc"
|
203 |
msgstr ""
|
204 |
|
205 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
206 |
msgid "WP Offload S3 Feature Removed"
|
207 |
msgstr ""
|
208 |
|
209 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
221 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
222 |
msgid "Amazon S3"
|
223 |
msgstr ""
|
224 |
|
225 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
226 |
msgctxt "Amazon S3 bucket"
|
227 |
msgid "Bucket"
|
228 |
msgstr ""
|
229 |
|
230 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
231 |
msgctxt "Path to file on Amazon S3"
|
232 |
msgid "Path"
|
233 |
msgstr ""
|
234 |
|
235 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
236 |
msgctxt "Location of Amazon S3 bucket"
|
237 |
msgid "Region"
|
238 |
msgstr ""
|
239 |
|
240 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
241 |
msgctxt "Access control list of the file on Amazon S3"
|
242 |
msgid "Access"
|
243 |
msgstr ""
|
244 |
|
245 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
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:
|
258 |
msgid "WP Offload S3 Compatibility Addons"
|
259 |
msgstr ""
|
260 |
|
261 |
-
#: classes/as3cf-plugin-compatibility.php:
|
262 |
msgid "compatibility addons"
|
263 |
msgstr ""
|
264 |
|
265 |
-
#: classes/as3cf-plugin-compatibility.php:
|
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:
|
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:
|
283 |
msgid "View Licenses"
|
284 |
msgstr ""
|
285 |
|
286 |
-
#: classes/as3cf-plugin-compatibility.php:
|
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:
|
292 |
-
#: classes/as3cf-plugin-compatibility.php:
|
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’ 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> — 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> — 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.
|
6 |
-
Stable tag: 1.1.
|
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=
|
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.
|
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.
|
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 |
+
}
|