WP Offload S3 Lite - Version 0.8

Version Description

  • 2015-01-10 =
  • New: Redesigned settings UI
  • Improvement: SSL setting can be fully controlled, HTTPS for urls always, based on request or never
  • Improvement: Download files from S3 that are not found on server when running Regenerate Thumbnails plugin
  • Improvement: When calling get_attached_file() and file is missing from server, return S3 URL
  • Improvement: Code cleanup to WordPress coding standards
  • Bug Fix: Files for all subsites going into the same S3 folder on multisite installs setup prior to WP 3.5
  • Bug Fix: 'attempting to access local file system' error for some installs
Download this release

Release Info

Developer bradt
Plugin Icon 128x128 WP Offload S3 Lite
Version 0.8
Comparing to
See all releases

Code changes from version 0.7.2 to 0.8

CONTRIBUTING.md ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Contributing
2
+
3
+ ### Getting Started
4
+
5
+ Submit a ticket for your issue, assuming one does not already exist.
6
+ * Raise it on our [Issue Tracker](https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront)
7
+ * Clearly describe the issue, including steps to reproduce the bug (if applicable).
8
+ * If it's a bug, make sure you fill in the earliest version that you know has the issue as well as the version of WordPress you're using.
9
+
10
+ ## Making Changes
11
+
12
+ * Fork the repository on GitHub
13
+ * From the `develop` branch on your forked repository, create a new branch and make your changes
14
+ * It is suggested that your new branch use a name that briefly describes the feature or issue.
15
+ * Ensure you stick to the [WordPress Coding Standards](http://codex.wordpress.org/WordPress_Coding_Standards)
16
+ * When committing, use a [well-formed](http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message) [commit](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) [message](http://who-t.blogspot.com/2009/12/on-commit-messages.html)
17
+ * Push the changes to your fork and submit a pull request to the `develop` branch of the plugin's repository
18
+
19
+ ## Code Documentation
20
+
21
+ * Code comments should be added to all new functions/methods.
22
+ * Comments should tell you the "what" & "why". You'll typically want a one-liner that says what it does, hopefully why, but not how. Only very rarely should they tell you how (e.g. when the code is necessarily complex).
23
+ * Also see the [WordPress PHP Documentation Standards](http://make.wordpress.org/core/handbook/inline-documentation-standards/php-documentation-standards/) doc for general guidelines and best practices.
24
+ * We currently suggest implementing the `@param` & `@return` PHPdoc tags for every function/method if applicable.
25
+
26
+ At this point you're waiting on us to merge your pull request. We'll review all pull requests, and make suggestions and changes if necessary.
27
+
28
+ # Additional Resources
29
+ * [GitHub Help — Forking](https://help.github.com/articles/fork-a-repo)
30
+ * [GitHub Help — Syncing a Fork](https://help.github.com/articles/syncing-a-fork)
31
+ * [GitHub Help — Pull Requests](https://help.github.com/articles/using-pull-requests#before-you-begin)
assets/Gruntfile.js CHANGED
@@ -17,7 +17,7 @@ module.exports = function(grunt) {
17
  },
18
  watch: {
19
  js: {
20
- files: ['js/*'],
21
  tasks: ['uglify']
22
  },
23
  sass: {
17
  },
18
  watch: {
19
  js: {
20
+ files: ['js/*.js', '!js/*.min.js'],
21
  tasks: ['uglify']
22
  },
23
  sass: {
assets/css/styles.css CHANGED
@@ -1 +1 @@
1
- .aws-main .error{max-width:835px}.aws-main .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.aws-main .error pre code{padding:0;background:none}.aws-main .as3cf-notice{max-width:835px}.as3cf-settings{position:relative;width:550px;min-height:800px}.as3cf-settings select.bucket{margin-bottom:5px;width:380px}.as3cf-settings .form-table td{padding-left:0;padding-right:0}.as3cf-settings .form-table tr:first-child h3{margin-top:0}.as3cf-settings .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-settings .tooltip:before,.as3cf-settings .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-settings .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-settings .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-settings .tooltip:hover:before,.as3cf-settings .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-banner img{display:block}.as3cf-sidebar{position:absolute;top:17px;right:-312px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe ul{margin-left:20px;list-style-type:disc}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.as3cf-sidebar .as3cf-banner{background-image:url(../img/snail@2x.jpg);background-size:292px 165px;width:292px;height:165px;display:block}.as3cf-sidebar .as3cf-banner img{display:none}}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto;margin-top:50px}}
1
+ .aws-main .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.aws-main .error pre code{padding:0;background:none}.aws-main .as3cf-notice,.aws-main .error{max-width:935px}.aws-main .updated{display:none}.aws-main .updated.show{display:block}.as3cf-settings{position:relative;width:650px;min-height:800px}.as3cf-settings .as3cf-main-settings{display:none}.as3cf-settings .as3cf-main-settings p{font-size:13px}.as3cf-settings .as3cf-main-settings p a{color:#444}.as3cf-settings.as3cf-has-bucket .as3cf-bucket-select{display:none}.as3cf-settings.as3cf-has-bucket .as3cf-main-settings{display:block}.as3cf-settings tr.configure-url,.as3cf-settings tr.advanced-options{display:none}.as3cf-settings .object-prefix-desc em{white-space:nowrap}.as3cf-settings .as3cf-url-preview-wrap{background:#ffffff;text-align:center;padding:20px 20px 10px;max-width:610px;width:100%}.as3cf-settings .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:5px;overflow-x:scroll;padding-bottom:15px}.as3cf-settings .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-settings .as3cf-ssl p.info{margin-top:10px;padding:0}.as3cf-settings .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-settings .as3cf-radio-group label.disabled,.as3cf-settings .as3cf-radio-group label.disabled p{color:#bbbbbb;cursor:default}.as3cf-settings .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-settings .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-settings .as3cf-switch{position:relative}.as3cf-settings .as3cf-switch.disabled span{cursor:default;margin:1px 0 0 0}.as3cf-settings .as3cf-switch.disabled span.checked{background:#F1F1F1;border:1px solid #dddddd;color:#a3a3a3}.as3cf-settings .as3cf-switch span{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;-webkit-border-radius:2px;font-weight:bold;padding:4px 8px;background:#F1F1F1;border:1px solid #dddddd;color:#CCCCCC;margin:1px -1px 0;z-index:1}.as3cf-settings .as3cf-switch span.checked{background:#ffffff;border-color:#E4E4E4;color:#373737;padding:5px 10px;margin:0;z-index:2}.as3cf-settings .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-settings .as3cf-setting.hide{display:none}.as3cf-settings .as3cf-bucket-actions{position:absolute;right:0;top:2px}.as3cf-settings .as3cf-bucket-actions .as3cf-cancel-bucket-select-wrap{display:none}.as3cf-settings .as3cf-bucket-actions .as3cf-cancel-bucket-select-wrap:after{content:" | "}.as3cf-settings .as3cf-bucket-list-wrapper{background:#fff;padding:15px 20px;margin-bottom:2em}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list{max-height:300px;overflow:auto;margin:0}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list li{font-size:14px;padding:10px 0}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a:hover,.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a.selected{color:#0074A2}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a.selected{font-weight:bold}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a .bucket{float:left;clear:both}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a .bucket .dashicons{margin-right:5px}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list a .spinner{float:left;background-size:15px 15px}.as3cf-settings .as3cf-bucket-list-wrapper .as3cf-bucket-list.saving{opacity:0.5}.as3cf-settings .as3cf-create-bucket-form input[type="text"]{width:80%}.as3cf-settings select.bucket{margin-bottom:5px;width:380px}.as3cf-settings .form-table td{padding-left:0;padding-right:0}.as3cf-settings .form-table td:first-child{vertical-align:top;min-width:120px}.as3cf-settings .form-table h3{font-weight:normal;text-transform:uppercase;margin:0}.as3cf-settings .form-table h4{margin:0}.as3cf-settings .form-table .as3cf-border-bottom td{border-bottom:1px solid #ddd}.as3cf-settings .as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-settings .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-settings .tooltip:before,.as3cf-settings .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-settings .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-settings .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-settings .tooltip:hover:before,.as3cf-settings .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-banner img{display:block}.as3cf-sidebar{position:absolute;top:17px;right:-312px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe ul{margin-left:20px;list-style-type:disc}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.as3cf-sidebar .as3cf-banner{background-image:url(../img/snail@2x.jpg);background-size:292px 165px;width:292px;height:165px;display:block}.as3cf-sidebar .as3cf-banner img{display:none}}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto;margin-top:50px}}
assets/js/script.js CHANGED
@@ -1,78 +1,316 @@
1
  (function($) {
 
2
 
3
  $(document).ready(function() {
4
 
5
  $('.as3cf-settings').each(function() {
6
  var $container = $(this);
 
 
7
 
8
- $('select.bucket', $container).change(function() {
9
- var $select = $(this);
 
10
 
11
- if ($select.val() !== 'new') {
12
- return;
13
- }
 
 
 
 
14
 
15
- var error_func = function(jqXHR, textStatus, errorThrown) {
16
- alert(as3cf_i18n.create_bucket_error + errorThrown);
17
- $select[0].selectedIndex = 0;
18
- console.log( jqXHR );
19
- console.log( textStatus );
20
- console.log( errorThrown );
21
- };
22
 
23
- var success_func = function(data, textStatus, jqXHR) {
24
- if (typeof data['success'] !== 'undefined') {
25
- var opt = document.createElement('option');
26
- opt.value = opt.innerHTML = bucket_name;
27
- var inserted_at_position = 0;
28
- $('option', $select).each(function() {
29
- // For some reason, no error occurs when
30
- // adding a bucket you've already added
31
- if ($(this).val() == bucket_name) {
32
- return false;
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
- if ($(this).val() > bucket_name || 'new' == $(this).val() ) {
35
- $(opt).insertBefore($(this));
36
- return false;
37
- }
38
- inserted_at_position = inserted_at_position + 1;
39
- });
40
- $select[0].selectedIndex = inserted_at_position;
41
 
42
- // If they decided to create a new bucket before refreshing
43
- // the page, we need another nonce
44
- as3cf_i18n.create_bucket_nonce = data['_nonce'];
 
 
 
 
 
 
 
45
  }
46
- else {
47
- alert(as3cf_i18n.create_bucket_error + data['error']);
48
- $select[0].selectedIndex = 0;
49
  }
50
- };
 
51
 
52
- var bucket_name = window.prompt(as3cf_i18n.create_bucket_prompt);
53
- if (!bucket_name) {
54
- $select[0].selectedIndex = 0;
55
- return;
56
- }
 
 
57
 
58
- var data = {
59
- action: 'as3cf-create-bucket',
60
- bucket_name: bucket_name,
61
- _nonce: as3cf_i18n.create_bucket_nonce
62
- };
63
-
64
- $.ajax({
65
- url: ajaxurl,
66
- type: 'POST',
67
- dataType: 'JSON',
68
- success: success_func,
69
- error: error_func,
70
- data: data
71
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
 
 
 
 
 
74
  });
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  });
77
 
78
  })(jQuery);
1
  (function($) {
2
+ var saved_settings;
3
 
4
  $(document).ready(function() {
5
 
6
  $('.as3cf-settings').each(function() {
7
  var $container = $(this);
8
+ var $bucketList = $('.as3cf-bucket-list');
9
+ var $createBucketForm = $container.find('.as3cf-create-bucket-form');
10
 
11
+ if($createBucketForm.length){
12
+ var $createBucketButton = $createBucketForm.find('button'),
13
+ origButtonText = $createBucketButton.text();
14
 
15
+ $createBucketForm.on('submit', function(e){
16
+ e.preventDefault();
17
+ $( '.as3cf-bucket-error' ).hide();
18
+ $bucketList.addClass('saving');
19
+ $createBucketButton.text($createBucketButton.attr('data-working'));
20
+ $createBucketButton.prop('disabled', true);
21
+ var bucketName = $createBucketForm.find('input[name="bucket_name"]').val();
22
 
23
+ var data = {
24
+ action: 'as3cf-create-bucket',
25
+ bucket_name: bucketName,
26
+ _nonce: as3cf_i18n.create_bucket_nonce
27
+ };
 
 
28
 
29
+ $.ajax({
30
+ url: ajaxurl,
31
+ type: 'POST',
32
+ dataType: 'JSON',
33
+ data: data,
34
+ error: function(jqXHR, textStatus, errorThrown) {
35
+ $createBucketButton.text(origButtonText);
36
+ show_bucket_error( as3cf_i18n.create_bucket_error, errorThrown );
37
+ },
38
+ success: function(data, textStatus, jqXHR) {
39
+ $createBucketButton.text(origButtonText);
40
+ $createBucketButton.prop('disabled', false);
41
+ if (typeof data['success'] !== 'undefined') {
42
+ bucket_select( bucketName, data['region'], data['can_write'] );
43
+ // tidy up create bucket form
44
+ $createBucketForm.find('input[name="bucket_name"]').val('');
45
+ $('.as3cf-bucket-list a' ).removeClass('selected');
46
+ loadBuckets();
47
+ $bucketList.removeClass('saving');
48
+ } else {
49
+ show_bucket_error( as3cf_i18n.create_bucket_error, data['error'] );
50
  }
51
+ }
52
+ });
53
+ });
54
+ }
 
 
 
55
 
56
+ var $changeBucket = $container.find('.as3cf-change-bucket');
57
+ if($changeBucket.length){
58
+ $changeBucket.on('click', function(e){
59
+ e.preventDefault();
60
+ $( '.updated' ).hide();
61
+ $('.as3cf-can-write-error').hide();
62
+ $('.as3cf-settings').removeClass('as3cf-has-bucket');
63
+ loadBuckets();
64
+ if ( $('.as3cf-active-bucket' ).html ) {
65
+ $('.as3cf-cancel-bucket-select-wrap' ).show();
66
  }
67
+ if ( $( '.as3cf-bucket-list a.selected' ).length ) {
68
+ $( '.as3cf-bucket-list' ).scrollTop( $( '.as3cf-bucket-list a.selected' ).position().top - 50 );
 
69
  }
70
+ });
71
+ }
72
 
73
+ var $refreshBuckets = $container.find('.as3cf-refresh-buckets');
74
+ if($refreshBuckets.length){
75
+ $refreshBuckets.on('click', function(e){
76
+ e.preventDefault();
77
+ loadBuckets();
78
+ });
79
+ }
80
 
81
+ var $cancelChangeBucket = $container.find('.as3cf-cancel-bucket-select');
82
+ if($cancelChangeBucket.length){
83
+ $cancelChangeBucket.on('click', function(e){
84
+ e.preventDefault();
85
+ $( '.as3cf-bucket-error' ).hide();
86
+ $('.as3cf-settings').addClass('as3cf-has-bucket');
 
 
 
 
 
 
 
87
  });
88
+ }
89
+
90
+ });
91
+
92
+ var $bucketList = $('.as3cf-bucket-list');
93
+ function loadBuckets() {
94
+ $( '.as3cf-bucket-error' ).hide();
95
+ $bucketList.html('<li class="loading">'+ $bucketList.attr('data-working') +'</li>');
96
+
97
+ var data = {
98
+ action: 'as3cf-get-buckets',
99
+ _nonce: as3cf_i18n.get_buckets_nonce
100
+ };
101
+
102
+ $.ajax({
103
+ url: ajaxurl,
104
+ type: 'POST',
105
+ dataType: 'JSON',
106
+ data: data,
107
+ error: function(jqXHR, textStatus, errorThrown) {
108
+ $bucketList.html('');
109
+ show_bucket_error( as3cf_i18n.get_buckets_error, errorThrown );
110
+ },
111
+ success: function(data, textStatus, jqXHR) {
112
+ $bucketList.html('');
113
+ if (typeof data['success'] !== 'undefined') {
114
+ $(data['buckets']).each(function(idx, bucket){
115
+ var bucket_class = ( bucket.Name == data['selected'] ) ? 'selected' : '';
116
+ $bucketList.append('<li><a class="' + bucket_class + '" href="#" data-bucket="'+ bucket.Name +'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+ bucket.Name +'</span><span class="spinner"></span></span></a></li>');
117
+ });
118
+ } else {
119
+ show_bucket_error( as3cf_i18n.get_buckets_error, data[ 'error' ] );
120
+ }
121
+ }
122
  });
123
+ }
124
+
125
+ $bucketList.on('click', 'a', function(e){
126
+ e.preventDefault();
127
+
128
+ if ( $(this).hasClass('selected') ) {
129
+ $('.as3cf-settings').addClass('as3cf-has-bucket');
130
+ return;
131
+ }
132
+
133
+ var bucket = this;
134
+ $('.as3cf-bucket-list a' ).removeClass('selected');
135
+ $(bucket).addClass('selected');
136
+
137
+ $bucketList.addClass('saving');
138
+ $(bucket).find('.spinner').show();
139
+ var bucketName = $(bucket).attr('data-bucket');
140
+
141
+ var data = {
142
+ action: 'as3cf-save-bucket',
143
+ bucket_name: bucketName,
144
+ _nonce: as3cf_i18n.save_bucket_nonce
145
+ };
146
+
147
+ $.ajax({
148
+ url: ajaxurl,
149
+ type: 'POST',
150
+ dataType: 'JSON',
151
+ data: data,
152
+ error: function(jqXHR, textStatus, errorThrown) {
153
+ $bucketList.removeClass('saving');
154
+ show_bucket_error( as3cf_i18n.save_bucket_error, errorThrown );
155
+ },
156
+ success: function(data, textStatus, jqXHR) {
157
+ $(bucket).find('.spinner').hide();
158
+ $bucketList.removeClass('saving');
159
+ if (typeof data['success'] !== 'undefined') {
160
+ bucket_select( bucketName, data['region'], data['can_write'] );
161
+ } else {
162
+ show_bucket_error( as3cf_i18n.save_bucket_error, data['error'] );
163
+ }
164
+ }
165
+ });
166
+ });
167
+
168
+ function show_bucket_error( title, error ) {
169
+ $( '.as3cf-bucket-error span.title' ).html( title );
170
+ $( '.as3cf-bucket-error span.message' ).html( error );
171
+ $( '.as3cf-bucket-error' ).show();
172
+ }
173
+
174
+ function bucket_select( bucket, region, can_write ) {
175
+ if ( '' == $( '.as3cf-active-bucket' ).text() ) {
176
+ // first time bucket select - enable main options by default
177
+ set_checkbox( 'copy-to-s3-wrap' );
178
+ set_checkbox( 'serve-from-s3-wrap' );
179
+ }
180
+ $( '.as3cf-active-bucket' ).text( bucket );
181
+ $( '#as3cf-bucket' ).val( bucket );
182
+ $( '#as3cf-region' ).val( region );
183
+ $( '.updated' ).show();
184
+ // check permission on bucket
185
+ if( can_write === false){
186
+ $('.as3cf-can-write-error').show();
187
+ }
188
+ $( '.as3cf-settings' ).addClass( 'as3cf-has-bucket' );
189
+ generate_url_preview();
190
+ }
191
 
192
+ $('.as3cf-switch').on('click', 'span', function(e){
193
+ if ( ! $(this).parent().hasClass('disabled') ) {
194
+ var parent_id = $(this).parent().attr('id');
195
+ set_checkbox( parent_id );
196
+ }
197
  });
198
 
199
+ function set_checkbox( checkbox_wrap ) {
200
+ $('#' + checkbox_wrap + ' span' ).toggleClass('checked');
201
+ var switch_on = $('#' + checkbox_wrap + ' span.on' ).hasClass('checked');
202
+ var checkbox_name = $('#' + checkbox_wrap).data('checkbox');
203
+ var $checkbox = $('input#' + checkbox_name);
204
+ $checkbox.attr( "checked", switch_on );
205
+ $checkbox.trigger("change");
206
+ }
207
+
208
+ if ( $( '.as3cf-settings' ).length && ! $( '.as3cf-settings' ).hasClass( 'as3cf-has-bucket' ) ) {
209
+ loadBuckets();
210
+ }
211
+
212
+ if ( $( '#copy-to-s3' ).is( ":checked" ) ) {
213
+ $('tr.advanced-options').show();
214
+ }
215
+
216
+ $('.as3cf-settings').on('change', '#copy-to-s3', function(e){
217
+ $('tr.advanced-options').toggle();
218
+ });
219
+
220
+ if ( $( '#serve-from-s3' ).is( ":checked" ) ) {
221
+ $('tr.configure-url').show();
222
+ }
223
+
224
+ $('.as3cf-settings').on('change', '#serve-from-s3', function(e){
225
+ $('tr.configure-url').toggle();
226
+ });
227
+
228
+ $('.as3cf-settings').on('change', '.sub-toggle', function(e){
229
+ var setting = $(this ).attr('id');
230
+ $('.as3cf-setting.' + setting ).toggleClass('hide');
231
+ });
232
+
233
+ $('.as3cf-domain').on('change', 'input[type="radio"]', function(e){
234
+ var domain = $( 'input:radio[name="domain"]:checked' ).val();
235
+ if ( 'cloudfront' == domain && $('.as3cf-setting.cloudfront' ).hasClass('hide') ) {
236
+ $('.as3cf-setting.cloudfront' ).removeClass('hide');
237
+ } else {
238
+ $('.as3cf-setting.cloudfront' ).addClass('hide');
239
+ }
240
+ });
241
+
242
+ $( '.as3cf-ssl' ).on( 'change', 'input[type="radio"]', function( e ) {
243
+ var ssl = $( 'input:radio[name="ssl"]:checked' ).val();
244
+ if ( 'https' == ssl ) {
245
+ var domain = $( 'input:radio[name="domain"]:checked' ).val();
246
+ if ( 'subdomain' == domain ) {
247
+ $( 'input[name="domain"][value="path"]' ).attr( "checked", true );
248
+ }
249
+ $( '.subdomain-wrap input' ).attr( 'disabled', true );
250
+ $( '.subdomain-wrap' ).addClass( 'disabled' );
251
+ } else {
252
+ $( '.subdomain-wrap input' ).removeAttr( 'disabled' );
253
+ $( '.subdomain-wrap' ).removeClass( 'disabled' );
254
+ }
255
+ } );
256
+
257
+ $('.url-preview').on('change', 'input', function(e){
258
+ generate_url_preview();
259
+ });
260
+
261
+ function generate_url_preview() {
262
+ $('.as3cf-url-preview' ).html( 'Generating...' );
263
+
264
+ var data = {
265
+ _nonce: as3cf_i18n.get_url_preview_nonce
266
+ };
267
+
268
+ $.each( $(".as3cf-main-settings form").serializeArray(), function(i,o){
269
+ var n = o.name,
270
+ v = o.value;
271
+ n = n.replace('[]', '');
272
+ data[n] = data[n] === undefined ? v
273
+ : $.isArray( data[n] ) ? data[n].concat( v )
274
+ : [ data[n], v ];
275
+ });
276
+
277
+ // overwrite the save action stored in the form
278
+ data['action'] = 'as3cf-get-url-preview';
279
+
280
+ $.ajax({
281
+ url: ajaxurl,
282
+ type: 'POST',
283
+ dataType: 'JSON',
284
+ data: data,
285
+ error: function(jqXHR, textStatus, errorThrown) {
286
+ alert(as3cf_i18n.get_url_preview_error + errorThrown);
287
+ },
288
+ success: function(data, textStatus, jqXHR) {
289
+ if (typeof data['success'] !== 'undefined') {
290
+ $('.as3cf-url-preview' ).html( data['url'] );
291
+ } else {
292
+ alert(as3cf_i18n.get_url_preview_error + data['error']);
293
+ }
294
+ }
295
+ });
296
+ }
297
+
298
+ // save the original state of the form for comparison later
299
+ saved_settings = $( '.as3cf-main-settings form' ).serialize();
300
+
301
+ // let the save settings submit happen as normal
302
+ $( document ).on( 'submit', '.as3cf-main-settings form', function( event ) {
303
+ // disable unload warning
304
+ $( window ).off( 'beforeunload.as3cf-settings' );
305
+ } );
306
+
307
+ // prompt user with dialog if leaving the settings page with unsaved changes
308
+ $( window ).on( 'beforeunload.as3cf-settings', function() {
309
+ if ( $( '.as3cf-main-settings form' ).serialize() != saved_settings ) {
310
+ return as3cf_i18n.save_alert;
311
+ }
312
+ } );
313
+
314
  });
315
 
316
  })(jQuery);
assets/js/script.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){a(document).ready(function(){a(".as3cf-settings").each(function(){var b=a(this);a("select.bucket",b).change(function(){var b=a(this);if("new"===b.val()){var c=function(a,c,d){alert(as3cf_i18n.create_bucket_error+d),b[0].selectedIndex=0,console.log(a),console.log(c),console.log(d)},d=function(c){if("undefined"!=typeof c.success){var d=document.createElement("option");d.value=d.innerHTML=e;var f=0;a("option",b).each(function(){return a(this).val()==e?!1:a(this).val()>e||"new"==a(this).val()?(a(d).insertBefore(a(this)),!1):void(f+=1)}),b[0].selectedIndex=f,as3cf_i18n.create_bucket_nonce=c._nonce}else alert(as3cf_i18n.create_bucket_error+c.error),b[0].selectedIndex=0},e=window.prompt(as3cf_i18n.create_bucket_prompt);if(!e)return void(b[0].selectedIndex=0);var f={action:"as3cf-create-bucket",bucket_name:e,_nonce:as3cf_i18n.create_bucket_nonce};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",success:d,error:c,data:f})}})})})}(jQuery);
1
+ !function(a){var b;a(document).ready(function(){function c(){a(".as3cf-bucket-error").hide(),h.html('<li class="loading">'+h.attr("data-working")+"</li>");var b={action:"as3cf-get-buckets",_nonce:as3cf_i18n.get_buckets_nonce};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){h.html(""),d(as3cf_i18n.get_buckets_error,c)},success:function(b){h.html(""),"undefined"!=typeof b.success?a(b.buckets).each(function(a,c){var d=c.Name==b.selected?"selected":"";h.append('<li><a class="'+d+'" href="#" data-bucket="'+c.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+c.Name+'</span><span class="spinner"></span></span></a></li>')}):d(as3cf_i18n.get_buckets_error,b.error)}})}function d(b,c){a(".as3cf-bucket-error span.title").html(b),a(".as3cf-bucket-error span.message").html(c),a(".as3cf-bucket-error").show()}function e(b,c,d){""==a(".as3cf-active-bucket").text()&&(f("copy-to-s3-wrap"),f("serve-from-s3-wrap")),a(".as3cf-active-bucket").text(b),a("#as3cf-bucket").val(b),a("#as3cf-region").val(c),a(".updated").show(),d===!1&&a(".as3cf-can-write-error").show(),a(".as3cf-settings").addClass("as3cf-has-bucket"),g()}function f(b){a("#"+b+" span").toggleClass("checked");var c=a("#"+b+" span.on").hasClass("checked"),d=a("#"+b).data("checkbox"),e=a("input#"+d);e.attr("checked",c),e.trigger("change")}function g(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf_i18n.get_url_preview_nonce};a.each(a(".as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf_i18n.get_url_preview_error+c)},success:function(b){"undefined"!=typeof b.success?a(".as3cf-url-preview").html(b.url):alert(as3cf_i18n.get_url_preview_error+b.error)}})}a(".as3cf-settings").each(function(){var b=a(this),f=a(".as3cf-bucket-list"),g=b.find(".as3cf-create-bucket-form");if(g.length){var h=g.find("button"),i=h.text();g.on("submit",function(b){b.preventDefault(),a(".as3cf-bucket-error").hide(),f.addClass("saving"),h.text(h.attr("data-working")),h.prop("disabled",!0);var j=g.find('input[name="bucket_name"]').val(),k={action:"as3cf-create-bucket",bucket_name:j,_nonce:as3cf_i18n.create_bucket_nonce};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:k,error:function(a,b,c){h.text(i),d(as3cf_i18n.create_bucket_error,c)},success:function(b){h.text(i),h.prop("disabled",!1),"undefined"!=typeof b.success?(e(j,b.region,b.can_write),g.find('input[name="bucket_name"]').val(""),a(".as3cf-bucket-list a").removeClass("selected"),c(),f.removeClass("saving")):d(as3cf_i18n.create_bucket_error,b.error)}})})}var j=b.find(".as3cf-change-bucket");j.length&&j.on("click",function(b){b.preventDefault(),a(".updated").hide(),a(".as3cf-can-write-error").hide(),a(".as3cf-settings").removeClass("as3cf-has-bucket"),c(),a(".as3cf-active-bucket").html&&a(".as3cf-cancel-bucket-select-wrap").show(),a(".as3cf-bucket-list a.selected").length&&a(".as3cf-bucket-list").scrollTop(a(".as3cf-bucket-list a.selected").position().top-50)});var k=b.find(".as3cf-refresh-buckets");k.length&&k.on("click",function(a){a.preventDefault(),c()});var l=b.find(".as3cf-cancel-bucket-select");l.length&&l.on("click",function(b){b.preventDefault(),a(".as3cf-bucket-error").hide(),a(".as3cf-settings").addClass("as3cf-has-bucket")})});var h=a(".as3cf-bucket-list");h.on("click","a",function(b){if(b.preventDefault(),a(this).hasClass("selected"))return void a(".as3cf-settings").addClass("as3cf-has-bucket");var c=this;a(".as3cf-bucket-list a").removeClass("selected"),a(c).addClass("selected"),h.addClass("saving"),a(c).find(".spinner").show();var f=a(c).attr("data-bucket"),g={action:"as3cf-save-bucket",bucket_name:f,_nonce:as3cf_i18n.save_bucket_nonce};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:g,error:function(a,b,c){h.removeClass("saving"),d(as3cf_i18n.save_bucket_error,c)},success:function(b){a(c).find(".spinner").hide(),h.removeClass("saving"),"undefined"!=typeof b.success?e(f,b.region,b.can_write):d(as3cf_i18n.save_bucket_error,b.error)}})}),a(".as3cf-switch").on("click","span",function(){if(!a(this).parent().hasClass("disabled")){var b=a(this).parent().attr("id");f(b)}}),a(".as3cf-settings").length&&!a(".as3cf-settings").hasClass("as3cf-has-bucket")&&c(),a("#copy-to-s3").is(":checked")&&a("tr.advanced-options").show(),a(".as3cf-settings").on("change","#copy-to-s3",function(){a("tr.advanced-options").toggle()}),a("#serve-from-s3").is(":checked")&&a("tr.configure-url").show(),a(".as3cf-settings").on("change","#serve-from-s3",function(){a("tr.configure-url").toggle()}),a(".as3cf-settings").on("change",".sub-toggle",function(){var b=a(this).attr("id");a(".as3cf-setting."+b).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(){var b=a('input:radio[name="domain"]:checked').val();"cloudfront"==b&&a(".as3cf-setting.cloudfront").hasClass("hide")?a(".as3cf-setting.cloudfront").removeClass("hide"):a(".as3cf-setting.cloudfront").addClass("hide")}),a(".as3cf-ssl").on("change",'input[type="radio"]',function(){var b=a('input:radio[name="ssl"]:checked').val();if("https"==b){var c=a('input:radio[name="domain"]:checked').val();"subdomain"==c&&a('input[name="domain"][value="path"]').attr("checked",!0),a(".subdomain-wrap input").attr("disabled",!0),a(".subdomain-wrap").addClass("disabled")}else a(".subdomain-wrap input").removeAttr("disabled"),a(".subdomain-wrap").removeClass("disabled")}),a(".url-preview").on("change","input",function(){g()}),b=a(".as3cf-main-settings form").serialize(),a(document).on("submit",".as3cf-main-settings form",function(){a(window).off("beforeunload.as3cf-settings")}),a(window).on("beforeunload.as3cf-settings",function(){return a(".as3cf-main-settings form").serialize()!=b?as3cf_i18n.save_alert:void 0})})}(jQuery);
assets/sass/styles.scss CHANGED
@@ -1,6 +1,5 @@
1
  .aws-main {
2
  .error {
3
- max-width: 835px;
4
  pre {
5
  background: #eaeaea;
6
  background: rgba(0, 0, 0, 0.07);
@@ -8,251 +7,465 @@
8
  padding: 10px 15px;
9
 
10
  code {
11
- padding: 0;
12
  background: none;
13
  }
14
  }
15
  }
16
 
17
- .as3cf-notice {
18
- max-width: 835px;
 
 
 
 
 
 
 
19
  }
20
  }
21
 
22
  .as3cf-settings {
23
- position: relative;
24
- width: 550px;
25
- min-height: 800px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- select.bucket {
28
- margin-bottom: 5px;
29
- width: 380px;
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
 
 
 
 
 
 
31
 
32
- .form-table {
33
- td {
34
- padding-left: 0;
35
- padding-right: 0;
36
- }
 
37
 
38
- tr:first-child {
39
- h3 {
40
- margin-top: 0;
41
- }
42
- }
 
 
 
43
  }
44
 
45
- .tooltip {
46
- position: relative;
47
- z-index: 2;
48
- cursor: pointer;
 
 
 
 
49
  }
 
50
 
51
- /* Hide the tooltip content by default */
52
- .tooltip:before,
53
- .tooltip:after {
54
- visibility: hidden;
55
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
56
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  opacity: 0;
58
- pointer-events: none;
59
- }
60
-
61
- /* Position tooltip above the element */
62
- .tooltip:before {
63
- position: absolute;
64
- bottom: 150%;
65
- left: 50%;
66
- margin-bottom: 5px;
67
- margin-left: -250px;
68
- padding: 10px;
69
- width: 500px;
70
- -webkit-border-radius: 3px;
71
- -moz-border-radius: 3px;
72
- border-radius: 3px;
73
- background-color: #000;
74
- background-color: hsla(0, 0%, 20%, 0.9);
75
- color: #fff;
76
- content: attr(data-tooltip);
77
- text-align: center;
78
- font-size: 14px;
79
- line-height: 1.3;
80
- }
81
-
82
- /* Triangle hack to make tooltip look like a speech bubble */
83
- .tooltip:after {
84
- position: absolute;
85
- bottom: 150%;
86
- left: 50%;
87
- margin-left: -5px;
88
- width: 0;
89
- border-top: 5px solid #000;
90
- border-top: 5px solid hsla(0, 0%, 20%, 0.9);
91
- border-right: 5px solid transparent;
92
- border-left: 5px solid transparent;
93
- content: " ";
94
- font-size: 0;
95
- line-height: 0;
96
- }
97
-
98
- /* Show tooltip content on hover */
99
- .tooltip:hover:before,
100
- .tooltip:hover:after {
101
- visibility: visible;
102
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
103
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
104
- opacity: 1;
105
  }
106
- }
107
 
108
- .as3cf-banner {
109
- img {
110
- display: block;
111
  }
112
- }
113
 
114
- .as3cf-sidebar {
115
  position: absolute;
116
- top: 17px;
117
- right: -312px;
118
- width: 292px;
119
-
120
- .block {
121
- padding: 20px;
122
- border: 1px solid #ccc;
123
- }
124
-
125
- .subscribe {
126
- border-top: none;
127
-
128
- h2 {
129
- padding: 0;
130
- margin: 0;
131
- margin-bottom: 0.5em;
132
- color: #666;
133
- font-size: 20px;
134
- line-height: 1.2em;
135
- float: none;
136
- }
137
 
138
- h3 {
139
- font-size: 16px;
140
- margin: 0;
141
- }
 
 
 
142
 
143
- p {
144
- margin: 0;
145
- }
 
146
 
147
- .intro {
148
- margin-bottom: 1em;
149
- line-height: 1.4;
150
- }
151
 
152
- ul {
153
- margin-left: 20px;
154
- list-style-type: disc;
 
 
 
 
 
 
155
  }
156
-
157
- li {
158
- line-height: 1.4;
159
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
- .links {
162
- margin-bottom: 2em;
 
 
 
163
 
164
- a {
165
- text-decoration: none;
166
- }
167
- }
168
 
169
- .promise {
170
- color: #999;
171
- font-size: 12px;
172
- line-height: 1.4em;
173
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- .field {
176
- margin-bottom: 0.5em;
 
 
177
 
178
- p {
179
- margin-bottom: 0.3em;
180
- }
 
 
181
 
182
- &.submit-button {
183
- margin-bottom: 1em;
184
- }
185
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  }
187
 
188
- .credits {
189
- border-top: 0;
 
 
190
 
191
- h4 {
192
- font-size: 16px;
193
- margin-top: 0;
194
- margin-bottom: 10px;
195
- }
196
 
197
- ul {
198
- margin: 0;
199
- }
 
200
 
201
- li {
202
- overflow: hidden;
203
- }
 
204
 
205
- li:last-child {
206
- margin-bottom: 0;
207
- }
208
 
209
- img {
210
- float: left;
211
- margin-right: 10px;
212
- }
213
 
214
- span {
215
- float: left;
216
- display: block;
217
- line-height: 32px;
218
- }
219
 
220
- a {
221
- display: block;
222
- text-decoration: none;
223
- color: #444;
224
- font-size: 16px;
225
- text-align: center;
226
 
227
- &:hover {
228
- color: #888;
229
- }
230
- }
 
 
 
 
 
 
231
  }
 
232
 
233
- @media (min--moz-device-pixel-ratio: 1.3),
234
- (-o-min-device-pixel-ratio: 2.6/2),
235
- (-webkit-min-device-pixel-ratio: 1.3),
236
- (min-device-pixel-ratio: 1.3),
237
- (min-resolution: 1.3dppx) {
238
 
239
- .as3cf-banner {
240
- background-image: url(../img/snail@2x.jpg);
241
- background-size: 292px 165px;
242
- width: 292px;
243
- height: 165px;
244
- display: block;
245
 
246
- img {
247
- display: none;
248
- }
249
- }
 
 
 
 
 
 
 
 
 
 
 
250
  }
251
 
252
- @media screen and (max-width: 1052px) {
253
- position: relative;
254
- top: auto;
255
- right: auto;
256
- margin-top: 50px;
257
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  }
1
  .aws-main {
2
  .error {
 
3
  pre {
4
  background: #eaeaea;
5
  background: rgba(0, 0, 0, 0.07);
7
  padding: 10px 15px;
8
 
9
  code {
10
+ padding: 0;
11
  background: none;
12
  }
13
  }
14
  }
15
 
16
+ .as3cf-notice, .error {
17
+ max-width: 935px;
18
+ }
19
+
20
+ .updated {
21
+ display: none;
22
+ &.show {
23
+ display: block;
24
+ }
25
  }
26
  }
27
 
28
  .as3cf-settings {
29
+ position: relative;
30
+ width: 650px;
31
+ min-height: 800px;
32
+
33
+ .as3cf-main-settings {
34
+ display: none;
35
+ p {
36
+ font-size: 13px;
37
+ a {
38
+ color: #444;
39
+ }
40
+ }
41
+ }
42
+ &.as3cf-has-bucket {
43
+ .as3cf-bucket-select {
44
+ display: none;
45
+ }
46
+ .as3cf-main-settings {
47
+ display: block;
48
+ }
49
+ }
50
+
51
+ tr.configure-url, tr.advanced-options {
52
+ display: none;
53
+ }
54
 
55
+ .object-prefix-desc {
56
+ em {
57
+ white-space: nowrap;
58
+ }
59
+ }
60
+
61
+ .as3cf-url-preview-wrap {
62
+ background: #ffffff;
63
+ text-align: center;
64
+ padding: 20px 20px 10px;
65
+ max-width: 610px;
66
+ width: 100%;
67
+ .as3cf-url-preview {
68
+ margin-top: 5px;
69
+ overflow-x: scroll;
70
+ padding-bottom: 15px;
71
  }
72
+ span {
73
+ color: #aaa;
74
+ text-transform: uppercase;
75
+ font-weight: bold;
76
+ }
77
+ }
78
 
79
+ .as3cf-ssl {
80
+ p.info {
81
+ margin-top: 10px;
82
+ padding: 0;
83
+ }
84
+ }
85
 
86
+ .as3cf-radio-group {
87
+ label {
88
+ display: block;
89
+ margin-bottom: 10px;
90
+ &.disabled, &.disabled p {
91
+ color: #bbbbbb;
92
+ cursor: default;
93
+ }
94
  }
95
 
96
+ p {
97
+ padding-left: 25px;
98
+ color: #6b6b6b;
99
+ margin: 0;
100
+ font-size: 12px;
101
+ &.as3cf-setting {
102
+ margin-top: 5px;
103
+ }
104
  }
105
+ }
106
 
107
+ .as3cf-switch {
108
+ position: relative;
109
+
110
+ &.disabled {
111
+ span {
112
+ cursor: default;
113
+ margin: 1px 0 0 0;
114
+ }
115
+ span.checked {
116
+ background: #F1F1F1;
117
+ border: 1px solid #dddddd;
118
+ color: #a3a3a3;
119
+ }
120
+ }
121
+ span {
122
+ -webkit-box-sizing: border-box;
123
+ -moz-box-sizing: border-box;
124
+ box-sizing: border-box;
125
+ cursor: pointer;
126
+ float: left;
127
+ display: inline-block;
128
+ height: 100%;
129
+ font-size: 12px;
130
+ line-height: 20px;
131
+ border-radius: 2px;
132
+ -webkit-border-radius: 2px;
133
+ font-weight: bold;
134
+ padding: 4px 8px;
135
+ background: #F1F1F1;
136
+ border: 1px solid #dddddd;
137
+ color: #CCCCCC;
138
+ margin: 1px -1px 0;
139
+ z-index: 1;
140
+
141
+ &.checked {
142
+ background: #ffffff;
143
+ border-color: #E4E4E4;
144
+ color: #373737;
145
+ padding: 5px 10px;
146
+ margin: 0;
147
+ z-index: 2;
148
+ }
149
+ }
150
+ input[type="checkbox"] {
151
+ position: absolute !important;
152
+ top: 0;
153
+ left: 0;
154
  opacity: 0;
155
+ filter: alpha(opacity=0);
156
+ z-index: -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
+ }
159
 
160
+ .as3cf-setting {
161
+ &.hide{
162
+ display: none;
163
  }
164
+ }
165
 
166
+ .as3cf-bucket-actions {
167
  position: absolute;
168
+ right: 0;
169
+ top: 2px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
+ .as3cf-cancel-bucket-select-wrap {
172
+ display: none;
173
+ &:after {
174
+ content: " | "
175
+ }
176
+ }
177
+ }
178
 
179
+ .as3cf-bucket-list-wrapper {
180
+ background: #fff;
181
+ padding: 15px 20px;
182
+ margin-bottom: 2em;
183
 
184
+ .as3cf-bucket-list {
185
+ max-height: 300px;
186
+ overflow: auto;
187
+ margin: 0;
188
 
189
+ li {
190
+ font-size: 14px;
191
+ padding: 10px 0;
192
+ }
193
+ a {
194
+ color: #444;
195
+ text-decoration: none;
196
+ &:hover, &.selected {
197
+ color: #0074A2;
198
  }
199
+ &.selected {
200
+ font-weight: bold;
 
201
  }
202
+ .bucket {
203
+ float: left;
204
+ clear: both;
205
+ .dashicons {
206
+ margin-right: 5px;
207
+ }
208
+ }
209
+ .spinner {
210
+ float: left;
211
+ background-size: 15px 15px
212
+ }
213
+ }
214
+ &.saving {
215
+ opacity: 0.5;
216
+ }
217
+ }
218
+ }
219
 
220
+ .as3cf-create-bucket-form {
221
+ input[type="text"] {
222
+ width: 80%;
223
+ }
224
+ }
225
 
226
+ select.bucket {
227
+ margin-bottom: 5px;
228
+ width: 380px;
229
+ }
230
 
231
+ .form-table {
232
+ td {
233
+ padding-left: 0;
234
+ padding-right: 0;
235
+ &:first-child {
236
+ vertical-align: top;
237
+ min-width: 120px;
238
+ }
239
+ }
240
+ h3 {
241
+ font-weight: normal;
242
+ text-transform: uppercase;
243
+ margin: 0;
244
+ }
245
+ h4 {
246
+ margin: 0;
247
+ }
248
+ .as3cf-border-bottom td {
249
+ border-bottom: 1px solid #ddd;
250
+ }
251
+ }
252
 
253
+ .as3cf-active-bucket {
254
+ font-weight: bold;
255
+ margin-right: 10px;
256
+ }
257
 
258
+ .tooltip {
259
+ position: relative;
260
+ z-index: 2;
261
+ cursor: pointer;
262
+ }
263
 
264
+ /* Hide the tooltip content by default */
265
+ .tooltip:before,
266
+ .tooltip:after {
267
+ visibility: hidden;
268
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
269
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
270
+ opacity: 0;
271
+ pointer-events: none;
272
+ }
273
+
274
+ /* Position tooltip above the element */
275
+ .tooltip:before {
276
+ position: absolute;
277
+ bottom: 150%;
278
+ left: 50%;
279
+ margin-bottom: 5px;
280
+ margin-left: -250px;
281
+ padding: 10px;
282
+ width: 500px;
283
+ -webkit-border-radius: 3px;
284
+ -moz-border-radius: 3px;
285
+ border-radius: 3px;
286
+ background-color: #000;
287
+ background-color: hsla(0, 0%, 20%, 0.9);
288
+ color: #fff;
289
+ content: attr(data-tooltip);
290
+ text-align: center;
291
+ font-size: 14px;
292
+ line-height: 1.3;
293
+ }
294
+
295
+ /* Triangle hack to make tooltip look like a speech bubble */
296
+ .tooltip:after {
297
+ position: absolute;
298
+ bottom: 150%;
299
+ left: 50%;
300
+ margin-left: -5px;
301
+ width: 0;
302
+ border-top: 5px solid #000;
303
+ border-top: 5px solid hsla(0, 0%, 20%, 0.9);
304
+ border-right: 5px solid transparent;
305
+ border-left: 5px solid transparent;
306
+ content: " ";
307
+ font-size: 0;
308
+ line-height: 0;
309
+ }
310
+
311
+ /* Show tooltip content on hover */
312
+ .tooltip:hover:before,
313
+ .tooltip:hover:after {
314
+ visibility: visible;
315
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
316
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
317
+ opacity: 1;
318
+ }
319
+ }
320
+
321
+ .as3cf-banner {
322
+ img {
323
+ display: block;
324
+ }
325
+ }
326
+
327
+ .as3cf-sidebar {
328
+ position: absolute;
329
+ top: 17px;
330
+ right: -312px;
331
+ width: 292px;
332
+
333
+ .block {
334
+ padding: 20px;
335
+ border: 1px solid #ccc;
336
+ }
337
+
338
+ .subscribe {
339
+ border-top: none;
340
+
341
+ h2 {
342
+ padding: 0;
343
+ margin: 0;
344
+ margin-bottom: 0.5em;
345
+ color: #666;
346
+ font-size: 20px;
347
+ line-height: 1.2em;
348
+ float: none;
349
  }
350
 
351
+ h3 {
352
+ font-size: 16px;
353
+ margin: 0;
354
+ }
355
 
356
+ p {
357
+ margin: 0;
358
+ }
 
 
359
 
360
+ .intro {
361
+ margin-bottom: 1em;
362
+ line-height: 1.4;
363
+ }
364
 
365
+ ul {
366
+ margin-left: 20px;
367
+ list-style-type: disc;
368
+ }
369
 
370
+ li {
371
+ line-height: 1.4;
372
+ }
373
 
374
+ .links {
375
+ margin-bottom: 2em;
 
 
376
 
377
+ a {
378
+ text-decoration: none;
379
+ }
380
+ }
 
381
 
382
+ .promise {
383
+ color: #999;
384
+ font-size: 12px;
385
+ line-height: 1.4em;
386
+ }
 
387
 
388
+ .field {
389
+ margin-bottom: 0.5em;
390
+
391
+ p {
392
+ margin-bottom: 0.3em;
393
+ }
394
+
395
+ &.submit-button {
396
+ margin-bottom: 1em;
397
+ }
398
  }
399
+ }
400
 
401
+ .credits {
402
+ border-top: 0;
 
 
 
403
 
404
+ h4 {
405
+ font-size: 16px;
406
+ margin-top: 0;
407
+ margin-bottom: 10px;
408
+ }
 
409
 
410
+ ul {
411
+ margin: 0;
412
+ }
413
+
414
+ li {
415
+ overflow: hidden;
416
+ }
417
+
418
+ li:last-child {
419
+ margin-bottom: 0;
420
+ }
421
+
422
+ img {
423
+ float: left;
424
+ margin-right: 10px;
425
  }
426
 
427
+ span {
428
+ float: left;
429
+ display: block;
430
+ line-height: 32px;
 
431
  }
432
+
433
+ a {
434
+ display: block;
435
+ text-decoration: none;
436
+ color: #444;
437
+ font-size: 16px;
438
+ text-align: center;
439
+
440
+ &:hover {
441
+ color: #888;
442
+ }
443
+ }
444
+ }
445
+
446
+ @media (min--moz-device-pixel-ratio: 1.3),
447
+ (-o-min-device-pixel-ratio: 2.6/2),
448
+ (-webkit-min-device-pixel-ratio: 1.3),
449
+ (min-device-pixel-ratio: 1.3),
450
+ (min-resolution: 1.3dppx) {
451
+
452
+ .as3cf-banner {
453
+ background-image: url(../img/snail@2x.jpg);
454
+ background-size: 292px 165px;
455
+ width: 292px;
456
+ height: 165px;
457
+ display: block;
458
+
459
+ img {
460
+ display: none;
461
+ }
462
+ }
463
+ }
464
+
465
+ @media screen and (max-width: 1052px) {
466
+ position: relative;
467
+ top: auto;
468
+ right: auto;
469
+ margin-top: 50px;
470
+ }
471
  }
classes/amazon-s3-and-cloudfront.php CHANGED
@@ -25,18 +25,45 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
25
  $this->plugin_title = __( 'Amazon S3 and CloudFront', 'as3cf' );
26
  $this->plugin_menu_title = __( 'S3 and CloudFront', 'as3cf' );
27
 
 
 
28
  add_action( 'wp_ajax_as3cf-create-bucket', array( $this, 'ajax_create_bucket' ) );
 
29
 
30
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
31
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
32
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 100, 2 );
33
  add_filter( 'wp_get_attachment_metadata', array( $this, 'wp_get_attachment_metadata' ), 10, 2 );
34
  add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
 
 
35
 
36
  load_plugin_textdomain( 'as3cf', false, dirname( plugin_basename( $plugin_file_path ) ) . '/languages/' );
37
  }
38
 
 
 
 
 
 
 
 
 
39
  function get_setting( $key, $default = '' ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  $settings = $this->get_settings();
41
 
42
  // If legacy setting set, migrate settings
@@ -45,22 +72,91 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
45
  }
46
 
47
  // Default object prefix
48
- if ( 'object-prefix' == $key && !isset( $settings['object-prefix'] ) ) {
49
- $uploads = wp_upload_dir();
50
- $parts = parse_url( $uploads['baseurl'] );
51
- return substr( $parts['path'], 1 ) . '/';
52
  }
53
 
54
- if ( 'bucket' == $key && defined( 'AS3CF_BUCKET' ) ) {
55
- $value = AS3CF_BUCKET;
 
56
  }
57
- else {
58
- $value = parent::get_setting( $key, $default );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  return apply_filters( 'as3cf_setting_' . $key, $value );
62
  }
63
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  /**
65
  * Allowed mime types array that can be edited for specific S3 uploading
66
  *
@@ -70,12 +166,49 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
70
  return apply_filters( 'as3cf_allowed_mime_types', get_allowed_mime_types() );
71
  }
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  /**
74
  * Find backup images and add to array for removal
75
  *
76
- * @param unknown $post_id
77
- * @param unknown $objects
78
- * @param unknown $path
79
  */
80
  function prepare_backup_size_images_to_remove( $post_id, &$objects, $path ) {
81
  $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
@@ -92,9 +225,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
92
  /**
93
  * Find intermediate size images and add to array for removal
94
  *
95
- * @param unknown $post_id
96
- * @param unknown $objects
97
- * @param unknown $path
98
  */
99
  function prepare_intermediate_images_to_remove( $post_id, &$objects, $path ) {
100
  $intermediate_images = get_intermediate_image_sizes();
@@ -111,8 +244,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
111
  /**
112
  * Delete bulk objects from an S3 bucket
113
  *
114
- * @param unknown $bucket
115
- * @param unknown $objects
116
  * @param bool $log_error
117
  * @param bool $return_on_error
118
  */
@@ -120,7 +253,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
120
  try {
121
  $this->get_s3client()->deleteObjects( array(
122
  'Bucket' => $bucket,
123
- 'Objects' => $objects
124
  ) );
125
  } catch ( Exception $e ) {
126
  if ( $log_error ) {
@@ -133,11 +266,11 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
133
  }
134
 
135
  function delete_attachment( $post_id ) {
136
- if ( !$this->is_plugin_setup() ) {
137
  return;
138
  }
139
 
140
- if ( !( $s3object = $this->get_attachment_s3_info( $post_id ) ) ) {
141
  return;
142
  }
143
 
@@ -146,7 +279,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
146
  $this->set_s3client_region( $s3object );
147
 
148
  $amazon_path = dirname( $s3object['key'] );
149
- $objects = array();
150
 
151
  // remove intermediate images
152
  $this->prepare_intermediate_images_to_remove( $post_id, $objects, $amazon_path );
@@ -167,7 +300,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
167
 
168
  // add main file to be deleted
169
  $objects[] = array(
170
- 'Key' => $s3object['key']
171
  );
172
 
173
  $this->delete_s3_objects( $bucket, $objects, true, true );
@@ -176,7 +309,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
176
  }
177
 
178
  function wp_update_attachment_metadata( $data, $post_id ) {
179
- if ( !$this->get_setting( 'copy-to-s3' ) || !$this->is_plugin_setup() ) {
180
  return $data;
181
  }
182
 
@@ -219,12 +352,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
219
  $time = date( 'Y/m', $time );
220
  }
221
 
222
- $prefix = ltrim( trailingslashit( $this->get_setting( 'object-prefix' ) ), '/' );
223
- $prefix .= ltrim( trailingslashit( $this->get_dynamic_prefix( $time ) ), '/' );
224
 
225
- if ( $this->get_setting( 'object-versioning' ) ) {
226
- $prefix .= $this->get_object_version_string( $post_id );
227
- }
228
  // use bucket from settings
229
  $bucket = $this->get_setting( 'bucket' );
230
  }
@@ -239,7 +368,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
239
 
240
  $s3object = array(
241
  'bucket' => $bucket,
242
- 'key' => $prefix . $file_name
243
  );
244
 
245
  // store acl if not default
@@ -259,12 +388,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
259
  'Bucket' => $bucket,
260
  'Key' => $prefix . $file_name,
261
  'SourceFile' => $file_path,
262
- 'ACL' => $acl
263
  );
264
 
265
  // If far future expiration checked (10 years)
266
  if ( $this->get_setting( 'expires' ) ) {
267
- $args['Expires'] = date( 'D, d M Y H:i:s O', time()+315360000 );
268
  }
269
 
270
  // if the original image is being restored and 'IMAGE_EDIT_OVERWRITE' is set
@@ -304,18 +433,17 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
304
  if ( file_exists( $path ) ) {
305
  $additional_images[] = array(
306
  'Key' => $prefix . $data['thumb'],
307
- 'SourceFile' => $path
308
  );
309
  $files_to_remove[] = $path;
310
  }
311
- }
312
- elseif ( !empty( $data['sizes'] ) ) {
313
  foreach ( $data['sizes'] as $size ) {
314
  $path = str_replace( $file_name, $size['file'], $file_path );
315
  if ( file_exists( $path ) ) {
316
  $additional_images[] = array(
317
  'Key' => $prefix . $size['file'],
318
- 'SourceFile' => $path
319
  );
320
  $files_to_remove[] = $path;
321
  }
@@ -332,7 +460,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
332
  if ( file_exists( $hidpi_path ) ) {
333
  $hidpi_images[] = array(
334
  'Key' => $this->get_hidpi_file_path( $image['Key'] ),
335
- 'SourceFile' => $hidpi_path
336
  );
337
  $files_to_remove[] = $hidpi_path;
338
  }
@@ -361,7 +489,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
361
 
362
  function remove_local_files( $file_paths ) {
363
  foreach ( $file_paths as $path ) {
364
- if ( !@unlink( $path ) ) {
365
  error_log( 'Error removing local file ' . $path );
366
  }
367
  }
@@ -369,15 +497,15 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
369
 
370
  function get_hidpi_file_path( $orig_path ) {
371
  $hidpi_suffix = apply_filters( 'as3cf_hidpi_suffix', '@2x' );
372
- $pathinfo = pathinfo( $orig_path );
 
373
  return $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $hidpi_suffix . '.' . $pathinfo['extension'];
374
  }
375
 
376
  function get_object_version_string( $post_id ) {
377
- if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
378
  $date_format = 'dHis';
379
- }
380
- else {
381
  $date_format = 'YmdHis';
382
  }
383
 
@@ -394,15 +522,15 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
394
  function get_attachment_folder_time( $post_id ) {
395
  $time = current_time( 'timestamp' );
396
 
397
- if ( !( $attach = get_post( $post_id ) ) ) {
398
  return $time;
399
  }
400
 
401
- if ( !$attach->post_parent ) {
402
  return $time;
403
  }
404
 
405
- if ( !( $post = get_post( $attach->post_parent ) ) ) {
406
  return $time;
407
  }
408
 
@@ -492,16 +620,16 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
492
  }
493
 
494
  function is_plugin_setup() {
495
- return (bool) $this->get_setting( 'bucket' ) && !is_wp_error( $this->aws->get_client() );
496
  }
497
 
498
  /**
499
  * Generate a link to download a file from Amazon S3 using query string
500
  * authentication. This link is only valid for a limited amount of time.
501
  *
502
- * @param unknown $post_id Post ID of the attachment
503
  * @param int $expires Seconds for the link to live
504
- * @param null $size Size of the image to get
505
  *
506
  * @return mixed|void|WP_Error
507
  */
@@ -512,13 +640,125 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
512
  return $this->get_attachment_url( $post_id, $expires, $size );
513
  }
514
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
  /**
516
  * Get the url of the file from Amazon S3
517
  *
518
- * @param unknown $post_id Post ID of the attachment
519
- * @param null $expires Seconds for the link to live
520
- * @param null $size Size of the image to get
521
- * @param null $meta Pre retrieved _wp_attachment_metadata for the attachment
522
  *
523
  * @return bool|mixed|void|WP_Error
524
  */
@@ -532,12 +772,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
532
  return false;
533
  }
534
 
535
- if ( is_ssl() || $this->get_setting( 'force-ssl' ) ) {
536
- $scheme = 'https';
537
- }
538
- else {
539
- $scheme = 'http';
540
- }
541
 
542
  // We don't use $this->get_s3object_region() here because we don't want
543
  // to make an AWS API call and slow down page loading
@@ -553,31 +788,18 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
553
  $expires = self::DEFAULT_EXPIRES;
554
  }
555
 
556
- $prefix = ( '' == $region ) ? 's3' : 's3-' . $region;
557
-
558
- if ( is_null( $expires ) && $this->get_setting( 'cloudfront' ) ) {
559
- $domain_bucket = $this->get_setting( 'cloudfront' );
560
- }
561
- elseif ( $this->get_setting( 'virtual-host' ) ) {
562
- $domain_bucket = $s3object['bucket'];
563
- }
564
- elseif ( is_ssl() || $this->get_setting( 'force-ssl' ) ) {
565
- $domain_bucket = $prefix . '.amazonaws.com/' . $s3object['bucket'];
566
- }
567
- else {
568
- $domain_bucket = $s3object['bucket'] . '.' . $prefix . '.amazonaws.com';
569
- }
570
 
571
  if ( $size ) {
572
  if ( is_null( $meta ) ) {
573
  $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
574
  }
575
- if ( isset( $meta['sizes'][$size]['file'] ) ) {
576
- $s3object['key'] = dirname( $s3object['key'] ) . '/' . $meta['sizes'][$size]['file'];
577
  }
578
  }
579
 
580
- if ( !is_null( $expires ) ) {
581
  try {
582
  $expires = time() + $expires;
583
  $secure_url = $this->get_s3client()->getObjectUrl( $s3object['bucket'], $s3object['key'], $expires );
@@ -613,8 +835,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
613
  /**
614
  * Encodes the file names for resized image files for an attachment where necessary
615
  *
616
- * @param unknown $data
617
- * @param unknown $post_id
618
  *
619
  * @return mixed Attachment meta data
620
  */
@@ -649,7 +871,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
649
  * Encode file names according to RFC 3986 when generating urls
650
  * As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
651
  *
652
- * @param unknown $file
653
  *
654
  * @return string Encoded filename with path prefix untouched
655
  */
@@ -661,29 +883,118 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
661
  return $file_path . $file_name;
662
  }
663
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  function verify_ajax_request() {
665
- if ( !is_admin() || !wp_verify_nonce( $_POST['_nonce'], $_POST['action'] ) ) {
666
  wp_die( __( 'Cheatin&#8217; eh?', 'as3cf' ) );
667
  }
668
 
669
- if ( !current_user_can( 'manage_options' ) ) {
670
  wp_die( __( 'You do not have sufficient permissions to access this page.', 'as3cf' ) );
671
  }
672
  }
673
 
 
 
 
 
 
 
 
 
 
674
  function ajax_create_bucket() {
675
  $this->verify_ajax_request();
676
 
677
- if ( !isset( $_POST['bucket_name'] ) || !$_POST['bucket_name'] ) {
678
- wp_die( __( 'No bucket name provided.', 'as3cf' ) );
679
- }
680
 
681
- $result = $this->create_bucket( $_POST['bucket_name'] );
682
  if ( is_wp_error( $result ) ) {
683
  $out = array( 'error' => $result->get_error_message() );
684
- }
685
- else {
686
- $out = array( 'success' => '1', '_nonce' => wp_create_nonce( 'as3cf-create-bucket' ) );
 
 
 
 
 
 
 
 
 
 
687
  }
688
 
689
  echo json_encode( $out );
@@ -701,6 +1012,53 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
701
  return true;
702
  }
703
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
704
  function admin_menu( $aws ) {
705
  $hook_suffix = $aws->add_page( $this->plugin_title, $this->plugin_menu_title, 'manage_options', $this->plugin_slug, array( $this, 'render_page' ) );
706
  add_action( 'load-' . $hook_suffix , array( $this, 'plugin_load' ) );
@@ -715,24 +1073,43 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
715
  }
716
 
717
  /**
718
- * Get the region of the bucket.
719
  *
 
720
  *
721
- * @param unknown $s3object
722
- * @param unknown $post_id - if supplied will update the s3 meta if no region found
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
723
  *
724
- * @return string - region name
 
 
 
 
725
  */
726
  function get_s3object_region( $s3object, $post_id = null ) {
727
  if ( ! isset( $s3object['region'] ) ) {
728
  // if region hasn't been stored in the s3 metadata retrieve using the bucket
729
- try {
730
- $region = $this->get_s3client()->getBucketLocation( array( 'Bucket' => $s3object['bucket'] ) );
731
- }
732
- catch ( Exception $e ) {
733
- return new WP_Error( 'exception', $e->getMessage() );
734
  }
735
- $s3object['region'] = $region['Location'];
 
736
 
737
  if ( ! is_null( $post_id ) ) {
738
  // retrospectively update s3 metadata with region
@@ -768,8 +1145,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
768
  *
769
  * This is needed for non US standard buckets to add and delete files.
770
  *
771
- * @param unknown $s3object
772
- * @param unknown $post_id
773
  *
774
  * @return string - region name
775
  */
@@ -788,6 +1165,32 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
788
  return $region;
789
  }
790
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
  function get_buckets() {
792
  try {
793
  $result = $this->get_s3client()->listBuckets();
@@ -802,63 +1205,53 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
802
  /**
803
  * Checks the user has write permission for S3
804
  *
 
 
 
805
  * @return bool
806
  */
807
- function check_write_permission( ) {
808
- if ( ! ( $bucket = $this->get_setting('bucket') ) ) {
809
- // if no bucket set then no need check
810
- return true;
811
- }
812
- // fire up the filesystem API
813
- $filesystem = WP_Filesystem();
814
- global $wp_filesystem;
815
- if ( false === $filesystem || is_null( $wp_filesystem ) ) {
816
- return new WP_Error( 'exception', __( 'There was an error attempting to access the local file system whilst checking the bucket permissions', 'as3cf' ) );
817
  }
818
 
819
- $uploads = wp_upload_dir();
820
  $file_name = 'as3cf-permission-check.txt';
821
- $file = trailingslashit( $uploads['basedir'] ) . $file_name;
822
  $file_contents = __( 'This is a test file to check if the user has write permission to S3. Delete me if found.', 'as3cf' );
823
- // create a temp file to upload
824
- $temp_file = $wp_filesystem->put_contents( $file, $file_contents, FS_CHMOD_FILE );
825
- if ( false === $temp_file ) {
826
- return new WP_Error( 'exception', __( 'It looks like we cannot create a file locally to test the S3 permissions', 'as3cf' ) );
827
- }
828
 
829
  $path = $this->get_setting( 'object-prefix' );
830
- $key = $path . $file_name;
831
 
832
  $args = array(
833
- 'Bucket' => $bucket,
834
- 'Key' => $key,
835
- 'SourceFile' => $file,
836
- 'ACL' => 'public-read'
837
  );
838
 
839
  try {
840
  // need to set region for buckets in non default region
841
- $region = $this->get_s3client()->getBucketLocation( array( 'Bucket' => $bucket ) );
842
- if ( $region['Location'] ) {
843
- $region = $this->translate_region( $region['Location'] );
 
844
  $this->get_s3client()->setRegion( $region );
845
  }
846
  // attempt to create the test file
847
  $this->get_s3client()->putObject( $args );
848
  // delete it straight away if created
849
  $this->get_s3client()->deleteObject( array(
850
- 'Bucket' => $bucket,
851
- 'Key' => $key
852
- ) );
853
  $can_write = true;
854
  } catch ( Exception $e ) {
855
  // write permission not found
856
  $can_write = false;
857
  }
858
 
859
- // delete temp file
860
- $wp_filesystem->delete( $file );
861
-
862
  return $can_write;
863
  }
864
 
@@ -874,33 +1267,42 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {