WP Offload S3 Lite - Version 0.9.7

Version Description

  • 2015-10-26 =
  • Improvement: Improve compatibility with third party plugins when the Remove Files From Server option is enabled
  • Improvement: Fix inconsistent spacing on the WP Offload S3 settings screen
  • Improvement: Validate CloudFront or custom domain input field
  • Improvement: Link to current S3 bucket added to WP Offload S3 settings screen
  • Improvement: Show notice when neither GD or Imagick image libraries are not installed
  • Improvement: Supply Cache-Control header to S3 when the Far Future Expiration Header option is enabled
  • Improvement: Additional information added to Diagnostic Information
  • Improvement: Added warning when Remove Files From Server option is enabled
  • Improvement: Filter added to allow additional image versions to be uploaded to S3
  • Bug fix: File size not stored in wp_attachment_metadata when Remove Files From Server option is enabled
  • Bug fix: Uploads on Multisite installs allowed after surpassing upload limit
  • Bug fix: Site icon in WordPress customizer returns 404
  • Bug fix: Image versions remain locally and on S3 after deletion, when the file name contains characters which require escaping
  • Bug fix: Files with the same file name overwritten when _Remove Files From Server option is enabled
  • Bug fix: Cron tasks incorrectly scheduled due to passing the wrong time to wp_schedule_event
  • Bug fix: Default options not shown in the UI after first install
Download this release

Release Info

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

Code changes from version 0.9.6 to 0.9.7

README.md CHANGED
@@ -3,7 +3,7 @@
3
  **Tags:** uploads, amazon, s3, mirror, admin, media, cdn, cloudfront
4
  **Requires at least:** 3.7
5
  **Tested up to:** 4.3
6
- **Stable tag:** 0.9.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.
@@ -67,8 +67,25 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
67
 
68
  ## Changelog ##
69
 
70
- ### 0.9.6 - 2015-10-01 ###
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
 
72
  * Improvement: Update text domains for translate.wordpress.org integration
73
 
74
  ### 0.9.5 - 2015-09-01 ###
3
  **Tags:** uploads, amazon, s3, mirror, admin, media, cdn, cloudfront
4
  **Requires at least:** 3.7
5
  **Tested up to:** 4.3
6
+ **Stable tag:** 0.9.7
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.
67
 
68
  ## Changelog ##
69
 
70
+ ### 0.9.7 - 2015-10-26 ###
71
+ * Improvement: Improve compatibility with third party plugins when the _Remove Files From Server_ option is enabled
72
+ * Improvement: Fix inconsistent spacing on the WP Offload S3 settings screen
73
+ * Improvement: Validate _CloudFront or custom domain_ input field
74
+ * Improvement: Link to current S3 bucket added to WP Offload S3 settings screen
75
+ * Improvement: Show notice when neither GD or Imagick image libraries are not installed
76
+ * Improvement: Supply Cache-Control header to S3 when the _Far Future Expiration Header_ option is enabled
77
+ * Improvement: Additional information added to _Diagnostic Information_
78
+ * Improvement: Added warning when _Remove Files From Server_ option is enabled
79
+ * Improvement: Filter added to allow additional image versions to be uploaded to S3
80
+ * Bug fix: File size not stored in _wp_attachment_metadata_ when _Remove Files From Server_ option is enabled
81
+ * Bug fix: Uploads on Multisite installs allowed after surpassing upload limit
82
+ * Bug fix: Site icon in WordPress customizer returns 404
83
+ * Bug fix: Image versions remain locally and on S3 after deletion, when the file name contains characters which require escaping
84
+ * Bug fix: Files with the same file name overwritten when __Remove Files From Server_ option is enabled
85
+ * Bug fix: Cron tasks incorrectly scheduled due to passing the wrong time to `wp_schedule_event`
86
+ * Bug fix: Default options not shown in the UI after first install
87
 
88
+ ### 0.9.6 - 2015-10-01 ###
89
  * Improvement: Update text domains for translate.wordpress.org integration
90
 
91
  ### 0.9.5 - 2015-09-01 ###
assets/css/styles.css CHANGED
@@ -1 +1 @@
1
- .aws-main.wrap>h2{float:left}.aws-main.wrap .as3cf-notice,.aws-main.wrap .as3cf-updated,.aws-main.wrap .as3cf-error{margin-bottom:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.aws-main.wrap .as3cf-error.fatal{clear:both;float:left}.aws-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:0;width:650px;margin-top:10px;padding-left:5px;padding-right:0}.aws-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.aws-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.aws-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.aws-main.wrap .error pre code{padding:0;background:none}.aws-main.wrap[data-tab="support"] .as3cf-notice,.aws-main.wrap[data-tab="support"] .error,.aws-main.wrap[data-tab="support"] .updated,.aws-main.wrap[data-tab="support"] .updated.show{display:none}.aws-main.wrap[data-tab="support"] .fatal .error,.aws-main.wrap[data-tab="support"] .as3cf-notice.important,.aws-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.aws-main.wrap .as3cf-notice,.aws-main.wrap .error,.aws-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.aws-main.wrap .as3cf-updated{display:none}.aws-main.wrap .as3cf-updated.as3cf-notice,.aws-main.wrap .as3cf-updated.show{display:block}.as3cf-tab .as3cf-main-settings{display:none}.as3cf-tab .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-main-settings{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-bucket-container{display:none}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-ssl p.info{margin-top:10px;padding:0}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbbbbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;-webkit-border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;-webkit-border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab h3{font-weight:normal;text-transform:uppercase;margin:15px 0}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}#tab-media{display:block}#tab-media .as3cf-main-settings{display:none}#tab-media .as3cf-bucket-container{display:block}#tab-media.as3cf-has-bucket .as3cf-main-settings{display:block}#tab-media.as3cf-has-bucket .as3cf-bucket-container{display:none}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{box-sizing:border-box;width:100%}.as3cf-bucket-container select{box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .as3cf-invalid-bucket-name{font-size:12px;color:#a00}.as3cf-bucket-container .bucket-actions{margin:15px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-bucket-container .bucket-actions button,.as3cf-bucket-container .bucket-actions .right{float:right;margin-right:0}.as3cf-bucket-container .bucket-actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-bucket-container .bucket-actions .bucket-action-cancel{color:#a00;text-decoration:none}.as3cf-bucket-container .bucket-actions .bucket-action-cancel:hover{color:red}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074A2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074A2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}.as3cf-bucket-container .as3cf-bucket-select,.as3cf-bucket-container .as3cf-bucket-create{display:none}.as3cf-bucket-container .bucket-actions.select{display:none}.as3cf-tab{display:none}#tab-media{display:block}#tab-support{min-height:900px}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:25px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe 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 input[type=text],.as3cf-sidebar .subscribe .field input[type=email]{width:100%}.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-banner@2x.jpg);background-size:292px 156px}}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto;margin-top:50px}}.as3cf-banner{margin-top:28px;width:292px;height:156px;display:block;background-image:url(../img/snail-banner.jpg);position:relative}.as3cf-banner h1{font-size:28px;color:#fff;font-weight:200;margin:0;position:absolute;bottom:25px;left:20px;text-decoration:none}.as3cf-upgrade-details{background-color:#73833b;padding:20px;color:#fff;font-size:13px;margin:0;display:block;text-decoration:none}.as3cf-upgrade-details p{margin:0}.as3cf-upgrade-details a{color:#fff;font-weight:bold;text-decoration:none;font-size:16px}.as3cf-upgrade-details a:hover{color:#fff;opacity:0.9}.as3cf-upgrade-details ul{margin-top:0;margin-left:16px;list-style-type:disc}.aws-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}.as3cf-bucket-error span.title{font-weight:bold}
1
+ .aws-main.wrap>h1{float:left}.aws-main.wrap .as3cf-notice,.aws-main.wrap .as3cf-updated,.aws-main.wrap .as3cf-error{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.aws-main.wrap .as3cf-error.fatal{clear:both;float:left}.aws-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:15px;width:650px;margin-top:10px;padding:9px 0 0 5px}.aws-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.aws-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.aws-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.aws-main.wrap .error pre code{padding:0;background:none}.aws-main.wrap[data-tab="support"] .as3cf-notice,.aws-main.wrap[data-tab="support"] .error,.aws-main.wrap[data-tab="support"] .updated,.aws-main.wrap[data-tab="support"] .updated.show{display:none}.aws-main.wrap[data-tab="support"] .fatal .error,.aws-main.wrap[data-tab="support"] .as3cf-notice.important,.aws-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.aws-main.wrap .as3cf-notice,.aws-main.wrap .error,.aws-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.aws-main.wrap .as3cf-updated{display:none}.aws-main.wrap .as3cf-updated.as3cf-notice,.aws-main.wrap .as3cf-updated.show{display:block}.as3cf-tab .as3cf-main-settings{display:none}.as3cf-tab .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-main-settings{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-bucket-container{display:none}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-ssl p.info{margin-top:10px;padding:0}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbbbbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;-webkit-border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;-webkit-border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab h3{font-weight:normal;text-transform:uppercase;margin:15px 0}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px}.as3cf-tab .form-table tr td .as3cf-notice:last-child{margin-bottom:0}.as3cf-tab .form-table tr:first-of-type td{padding-top:5px}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-tab .as3cf-view-bucket{color:#444;text-decoration:none;margin-right:10px}.as3cf-tab .as3cf-view-bucket:hover,.as3cf-tab .as3cf-view-bucket:active{color:#00a0d2}.as3cf-tab .as3cf-view-bucket .dashicons-external{margin-top:-2px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}#tab-media{display:block}#tab-media .as3cf-main-settings{display:none}#tab-media .as3cf-bucket-container{display:block}#tab-media.as3cf-has-bucket .as3cf-main-settings{display:block}#tab-media.as3cf-has-bucket .as3cf-bucket-container{display:none}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{box-sizing:border-box;width:100%}.as3cf-bucket-container select{box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .bucket-actions{margin:15px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-bucket-container .bucket-actions button,.as3cf-bucket-container .bucket-actions .right{float:right;margin-right:0}.as3cf-bucket-container .bucket-actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-bucket-container .bucket-actions .bucket-action-cancel{color:#a00;text-decoration:none}.as3cf-bucket-container .bucket-actions .bucket-action-cancel:hover{color:red}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074A2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074A2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}.as3cf-bucket-container .as3cf-bucket-select,.as3cf-bucket-container .as3cf-bucket-create{display:none}.as3cf-bucket-container .bucket-actions.select{display:none}.as3cf-tab{display:none}#tab-media{display:block}#tab-support{min-height:900px}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:25px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe 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 input[type=text],.as3cf-sidebar .subscribe .field input[type=email]{width:100%}.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-banner@2x.jpg);background-size:292px 156px}}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto;margin-top:50px}}.as3cf-banner{margin-top:28px;width:292px;height:156px;display:block;background-image:url(../img/snail-banner.jpg);position:relative}.as3cf-banner h1{font-size:28px;color:#fff;font-weight:200;margin:0;position:absolute;bottom:25px;left:20px;text-decoration:none}.as3cf-upgrade-details{background-color:#73833b;padding:20px;color:#fff;font-size:13px;margin:0;display:block;text-decoration:none}.as3cf-upgrade-details p{margin:0}.as3cf-upgrade-details a{color:#fff;font-weight:bold;text-decoration:none;font-size:16px}.as3cf-upgrade-details a:hover{color:#fff;opacity:0.9}.as3cf-upgrade-details ul{margin-top:0;margin-left:16px;list-style-type:disc}.aws-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}.as3cf-bucket-error span.title{font-weight:bold}.as3cf-invalid-bucket-name,.as3cf-validation-error{display:block;margin-top:2px;font-size:12px;color:#a00}
assets/js/notice.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function( $ ) {
2
+
3
+ $( 'body' ).on( 'click', '.as3cf-notice .notice-dismiss', function( e ) {
4
+ var id = $( this ).parents( '.as3cf-notice' ).attr( 'id' );
5
+ if ( id ) {
6
+ var data = {
7
+ action : 'as3cf-dismiss-notice',
8
+ notice_id: id,
9
+ _nonce : as3cf_notice.nonces.dismiss_notice
10
+ };
11
+
12
+ $.ajax( {
13
+ url : ajaxurl,
14
+ type : 'POST',
15
+ dataType: 'JSON',
16
+ data : data,
17
+ error : function( jqXHR, textStatus, errorThrown ) {
18
+ alert( as3cf_notice.strings.dismiss_notice_error + errorThrown );
19
+ }
20
+ } );
21
+ }
22
+ } );
23
+
24
+ })( jQuery );
assets/js/script.js CHANGED
@@ -32,6 +32,25 @@
32
  $checkbox.attr( 'checked', switchOn ).trigger( 'change' );
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  as3cf.tabs = {
36
  defaultTab: 'media',
37
  /**
@@ -348,7 +367,7 @@
348
  var $manualBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-manual-save-bucket-form' );
349
  var $activeBucket = $( '#' + as3cfModal.prefix + '-active-bucket' );
350
 
351
- if ( 'as3cf' === as3cfModal.prefix && '' === $activeBucket.text() ) {
352
  // first time bucket select - enable main options by default
353
  setCheckbox( 'copy-to-s3-wrap' );
354
  setCheckbox( 'serve-from-s3-wrap' );
@@ -376,6 +395,8 @@
376
  generateUrlPreview();
377
  }
378
 
 
 
379
  as3cfModal.close( unlockBucketSelect );
380
  },
381
 
@@ -479,6 +500,25 @@
479
 
480
  };
481
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  /**
483
  * Generate URL preview
484
  */
@@ -525,6 +565,28 @@
525
  as3cf.buckets.bucketSelectLock = false;
526
  }
527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  $( document ).ready( function() {
529
 
530
  // Tabs
@@ -630,6 +692,16 @@
630
  generateUrlPreview();
631
  } );
632
 
 
 
 
 
 
 
 
 
 
 
633
  // Don't allow 'enter' key to submit form on text input settings
634
  $( '.as3cf-setting input[type="text"]' ).keypress( function( event ) {
635
  if ( 13 === event.which ) {
@@ -640,6 +712,28 @@
640
 
641
  } );
642
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
  // Bucket select
644
  // --------------------
645
 
32
  $checkbox.attr( 'checked', switchOn ).trigger( 'change' );
33
  }
34
 
35
+ /**
36
+ * Validate custom domain
37
+ *
38
+ * @param {object} $input
39
+ */
40
+ function validateCustomDomain( $input ) {
41
+ var $error = $input.next( '.as3cf-validation-error' );
42
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
43
+ var pattern = /[^a-zA-Z0-9\.\-]/;
44
+
45
+ if ( pattern.test( $input.val() ) ) {
46
+ $error.show();
47
+ $submit.attr( 'disabled', true );
48
+ } else {
49
+ $error.hide();
50
+ $submit.attr( 'disabled', false );
51
+ }
52
+ }
53
+
54
  as3cf.tabs = {
55
  defaultTab: 'media',
56
  /**
367
  var $manualBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-manual-save-bucket-form' );
368
  var $activeBucket = $( '#' + as3cfModal.prefix + '-active-bucket' );
369
 
370
+ if ( 'as3cf' === as3cfModal.prefix && 0 === $activeBucket.text().trim().length ) {
371
  // first time bucket select - enable main options by default
372
  setCheckbox( 'copy-to-s3-wrap' );
373
  setCheckbox( 'serve-from-s3-wrap' );
395
  generateUrlPreview();
396
  }
397
 
398
+ setBucketLink();
399
+
400
  as3cfModal.close( unlockBucketSelect );
401
  },
402
 
500
 
501
  };
502
 
503
+ /**
504
+ * Get the link to the bucket on the AWS Console and update the DOM
505
+ *
506
+ * @returns {string}
507
+ */
508
+ function setBucketLink() {
509
+ var bucket = $( '#' + as3cfModal.prefix + '-bucket' ).val();
510
+ var $objectPrefix = $activeTab.find( 'input[name="object-prefix"]' );
511
+ var prefix = $objectPrefix.val();
512
+
513
+ if ( '' !== prefix ) {
514
+ prefix = '&prefix=' + encodeURIComponent( prefix );
515
+ }
516
+
517
+ var url = as3cf.aws_bucket_link + bucket + prefix;
518
+
519
+ $( '#' + as3cfModal.prefix + '-view-bucket' ).attr( 'href', url );
520
+ }
521
+
522
  /**
523
  * Generate URL preview
524
  */
565
  as3cf.buckets.bucketSelectLock = false;
566
  }
567
 
568
+ /*
569
+ * Toggle the lost files notice
570
+ */
571
+ function toggleLostFilesNotice() {
572
+ if ( $( '#remove-local-file' ).is( ':checked' ) && $( '#serve-from-s3' ).is( ':not(:checked)' ) ) {
573
+ $( '#as3cf-lost-files-notice' ).show();
574
+ } else {
575
+ $( '#as3cf-lost-files-notice' ).hide();
576
+ }
577
+ }
578
+
579
+ /*
580
+ * Toggle the remove local files notice
581
+ */
582
+ function toggleRemoveLocalNotice() {
583
+ if ( $( '#remove-local-file' ).is( ':checked' ) ) {
584
+ $( '#as3cf-remove-local-notice' ).show();
585
+ } else {
586
+ $( '#as3cf-remove-local-notice' ).hide();
587
+ }
588
+ }
589
+
590
  $( document ).ready( function() {
591
 
592
  // Tabs
692
  generateUrlPreview();
693
  } );
694
 
695
+ toggleLostFilesNotice();
696
+ $( '#serve-from-s3,#remove-local-file' ).on( 'change', function( e ) {
697
+ toggleLostFilesNotice();
698
+ } );
699
+
700
+ toggleRemoveLocalNotice();
701
+ $( '#remove-local-file' ).on( 'change', function( e ) {
702
+ toggleRemoveLocalNotice();
703
+ } );
704
+
705
  // Don't allow 'enter' key to submit form on text input settings
706
  $( '.as3cf-setting input[type="text"]' ).keypress( function( event ) {
707
  if ( 13 === event.which ) {
712
 
713
  } );
714
 
715
+ // Validate custom domain
716
+ $( 'input[name="cloudfront"]' ).on( 'keyup', function( e ) {
717
+ validateCustomDomain( $( this ) );
718
+ } );
719
+
720
+ // Re-enable submit button on domain change
721
+ $( 'input[name="domain"]' ).on( 'change', function( e ) {
722
+ var $input = $( this );
723
+ var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
724
+
725
+ if ( 'cloudfront' !== $input.val() ) {
726
+ $submit.attr( 'disabled', false );
727
+ } else {
728
+ validateCustomDomain( $input.next( '.as3cf-setting' ).find( 'input[name="cloudfront"]' ) );
729
+ }
730
+ } );
731
+
732
+ // Change bucket link when custom path changes
733
+ $( 'input[name="object-prefix"]' ).on( 'change', function( e ) {
734
+ setBucketLink();
735
+ } );
736
+
737
  // Bucket select
738
  // --------------------
739
 
assets/js/script.min.js CHANGED
@@ -1 +1 @@
1
- !function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(b){var c=a("#"+b),d=c.find("input[type=checkbox]");c.toggleClass("on").find("span").toggleClass("checked");var e=c.find("span.on").hasClass("checked");d.attr("checked",e).trigger("change")}function e(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .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.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?a(".as3cf-url-preview").html(b.url):alert(as3cf.strings.get_url_preview_error+b.error)}})}function f(a){as3cf.buckets.bucketSelectLock=!1}var g,h={},i=/[^a-z0-9.-]/,j=a(".as3cf-tab");as3cf.tabs={defaultTab:"media",toggle:function(c,d){j.hide(),g=a("#tab-"+c),g.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".aws-main").attr("data-tab",c),g.attr("data-prefix")&&(b.prefix=g.attr("data-prefix")),d||a(".as3cf-updated").removeClass("show")}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-list"),e=a("#"+b.prefix+"-bucket").val();if(!1===c&&d.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"),void this.scrollToSelected();d.html('<li class="loading">'+d.attr("data-working")+"</li>");var f={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets},g=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:f,error:function(a,b,c){d.html(""),g.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,f){d.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),a(b.buckets).each(function(a,b){var c=b.Name===e?"selected":"";d.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),g.scrollToSelected()):g.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},resetModal:function(){var c=a(".as3cf-bucket-container."+b.prefix);!1===g.hasClass("as3cf-has-bucket")||"manual"===a("#"+b.prefix+"-bucket-select").val()?(c.find(".as3cf-bucket-manual").show().siblings().hide(),c.find(".bucket-actions.manual").show().siblings(".bucket-actions").hide()):(c.find(".as3cf-bucket-select").show().siblings().hide(),c.find(".bucket-actions.select").show().siblings(".bucket-actions").hide(),this.loadList()),c.find(".as3cf-bucket-error").hide();var d=a("#"+b.prefix+"-bucket").val();c.find(".as3cf-bucket-manual .as3cf-bucket-name").val(d),this.bucketSelectLock=!1},saveManual:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find("button[type=submit]"),f=d.val(),h=e.first().text();if(f===a("#"+b.prefix+"-active-bucket").text())return a(".as3cf-bucket-error").hide(),g.addClass("as3cf-has-bucket"),void b.close();a(".as3cf-bucket-error").hide(),e.text(e.attr("data-working")),e.prop("disabled",!0);var i={action:b.prefix+"-manual-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.manual_bucket},j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){e.text(h),j.showError(as3cf.strings.save_bucket_error,c,"as3cf-bucket-manual")},success:function(c,d,g){e.text(h),e.prop("disabled",!1),"undefined"!=typeof c.success?(j.set(f,c.region,c.can_write),a("#"+b.prefix+"-bucket-select").val("manual"),a(".as3cf-bucket-list a").removeClass("selected").filter('[data-bucket="'+f+'"]').addClass("selected")):j.showError(as3cf.strings.save_bucket_error,c.error,"as3cf-bucket-manual")}})},saveSelected:function(c){var d=a(".as3cf-bucket-list");if(!this.bucketSelectLock){if(this.bucketSelectLock=!0,c.hasClass("selected"))return g.addClass("as3cf-has-bucket"),void b.close();var e=a(".as3cf-bucket-list a.selected").attr("data-bucket");a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),d.addClass("saving"),c.find(".spinner").show().css("visibility","visible");var f=c.attr("data-bucket"),h={action:b.prefix+"-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.save_bucket},i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(b,c,f){d.removeClass("saving"),i.showError(as3cf.strings.save_bucket_error,f,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected")},success:function(g,h,j){c.find(".spinner").hide().css("visibility","hidden"),d.removeClass("saving"),"undefined"!=typeof g.success?(i.set(f,g.region,g.can_write),a("#"+b.prefix+"-bucket-select").val("")):(i.showError(as3cf.strings.save_bucket_error,g.error,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"))}})}},disabledButtons:function(){if(0!==a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form").length){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");c.find(".as3cf-bucket-name").val().length<3?c.find("button[type=submit]").attr("disabled",!0):c.find("button[type=submit]").attr("disabled",!1),d.find(".as3cf-bucket-name").val().length<3?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").attr("disabled",!1)}},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,(!d||e.hasClass(d))&&(f.find("span.title").html(b+" &mdash;"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},set:function(i,j,k){var l=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),m=a("#"+b.prefix+"-active-bucket");if("as3cf"===b.prefix&&""===m.text()){d("copy-to-s3-wrap"),d("serve-from-s3-wrap");var n=g.attr("id");h[n]=c(n)}a(".as3cf-error.fatal").hide(),m.text(i),l.find(".as3cf-bucket-name").val(i),a("#"+b.prefix+"-bucket").val(i),a("#"+b.prefix+"-region").val(j),a(".updated").not(".as3cf-notice").show(),g.addClass("as3cf-has-bucket"),g.find(".as3cf-can-write-error").toggle(!k),g.find(".as3cf-bucket-error").hide(),"as3cf"===b.prefix&&e(),b.close(f)},create:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find(".bucket-create-region"),f=c.find("button[type=submit]"),g=d.val(),h=f.text();a(".as3cf-bucket-error").hide(),f.text(f.attr("data-working")),f.prop("disabled",!0);var i={action:b.prefix+"-create-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.create_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.create_bucket_error,c,"as3cf-bucket-create")},success:function(b,c,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof b.success?(j.set(g,b.region,b.can_write),a(".as3cf-bucket-select-region").hide(),a(".as3cf-bucket-select-region").removeAttr("selected"),d.val(""),f.attr("disabled",!0)):j.showError(as3cf.strings.create_bucket_error,b.error,"as3cf-bucket-create")}})},isValidName:function(a){return a.length<3||a.length>63?!1:!0===i.test(a)?!1:!0},updateNameNotice:function(b){var c=null;!0===i.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},a(document).ready(function(){var f=a(".wrap.aws-main .nav-tab-wrapper");if(a(".aws-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(f),window.location.hash){var i=window.location.hash.substring(1);as3cf.tabs.toggle(i,!0)}else g=a("#tab-"+as3cf.tabs.defaultTab),a(".aws-main").attr("data-tab",as3cf.tabs.defaultTab);a(".aws-main").on("click",".nav-tab",function(b){if(b.preventDefault(),!a(this).hasClass("nav-tab-active")){var c=a(this).attr("data-tab");as3cf.tabs.toggle(c),"media"===c?(window.location.hash="","function"==typeof window.history.replaceState&&"#"===window.location.href.slice(-1)&&history.replaceState({},"",window.location.href.slice(0,-1))):window.location.hash=c}}),j.length&&j.each(function(a,b){h[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(h)){var b=g.attr("id");return c(b)!==h[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||d(a(this).attr("id"))}),j.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(b){var c=a(this).closest('input:radio[name="domain"]:checked'),d=c.val(),e=a(this).parents(".as3cf-domain").find(".as3cf-setting.cloudfront"),f="cloudfront"===d;e.toggleClass("hide",!f)}),a(".as3cf-ssl").on("change",'input[type="radio"]',function(b){var c=a('input:radio[name="ssl"]:checked').val();if("https"===c){var d=a('input:radio[name="domain"]:checked').val();"subdomain"===d&&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(a){e()}),a('.as3cf-setting input[type="text"]').keypress(function(a){return 13===a.which?(a.preventDefault(),!1):void 0}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),a("body").on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),a("body").on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList()}),a("body").on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),a("body").on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),a("body").on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),a("body").on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),a("body").on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),a("body").on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),a("body").on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),a("body").on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").removeAttr("disabled"):e.find("button[type=submit]").attr("disabled",!0),as3cf.buckets.updateNameNotice(d)}),a("body").on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length<as3cf.buckets.validLength?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").removeAttr("disabled")})})}(jQuery,as3cfModal);
1
+ !function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(b){var c=a("#"+b),d=c.find("input[type=checkbox]");c.toggleClass("on").find("span").toggleClass("checked");var e=c.find("span.on").hasClass("checked");d.attr("checked",e).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+k.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.attr("disabled",!0)):(c.hide(),d.attr("disabled",!1))}function f(){var c=a("#"+b.prefix+"-bucket").val(),d=k.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e="&prefix="+encodeURIComponent(e));var f=as3cf.aws_bucket_link+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .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.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?a(".as3cf-url-preview").html(b.url):alert(as3cf.strings.get_url_preview_error+b.error)}})}function h(a){as3cf.buckets.bucketSelectLock=!1}function i(){a("#remove-local-file").is(":checked")&&a("#serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function j(){a("#remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}var k,l={},m=/[^a-z0-9.-]/,n=a(".as3cf-tab");as3cf.tabs={defaultTab:"media",toggle:function(c,d){n.hide(),k=a("#tab-"+c),k.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".aws-main").attr("data-tab",c),k.attr("data-prefix")&&(b.prefix=k.attr("data-prefix")),d||a(".as3cf-updated").removeClass("show")}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-list"),e=a("#"+b.prefix+"-bucket").val();if(!1===c&&d.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"),void this.scrollToSelected();d.html('<li class="loading">'+d.attr("data-working")+"</li>");var f={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets},g=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:f,error:function(a,b,c){d.html(""),g.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,f){d.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),a(b.buckets).each(function(a,b){var c=b.Name===e?"selected":"";d.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),g.scrollToSelected()):g.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},resetModal:function(){var c=a(".as3cf-bucket-container."+b.prefix);!1===k.hasClass("as3cf-has-bucket")||"manual"===a("#"+b.prefix+"-bucket-select").val()?(c.find(".as3cf-bucket-manual").show().siblings().hide(),c.find(".bucket-actions.manual").show().siblings(".bucket-actions").hide()):(c.find(".as3cf-bucket-select").show().siblings().hide(),c.find(".bucket-actions.select").show().siblings(".bucket-actions").hide(),this.loadList()),c.find(".as3cf-bucket-error").hide();var d=a("#"+b.prefix+"-bucket").val();c.find(".as3cf-bucket-manual .as3cf-bucket-name").val(d),this.bucketSelectLock=!1},saveManual:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find("button[type=submit]"),f=d.val(),g=e.first().text();if(f===a("#"+b.prefix+"-active-bucket").text())return a(".as3cf-bucket-error").hide(),k.addClass("as3cf-has-bucket"),void b.close();a(".as3cf-bucket-error").hide(),e.text(e.attr("data-working")),e.prop("disabled",!0);var h={action:b.prefix+"-manual-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.manual_bucket},i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){e.text(g),i.showError(as3cf.strings.save_bucket_error,c,"as3cf-bucket-manual")},success:function(c,d,h){e.text(g),e.prop("disabled",!1),"undefined"!=typeof c.success?(i.set(f,c.region,c.can_write),a("#"+b.prefix+"-bucket-select").val("manual"),a(".as3cf-bucket-list a").removeClass("selected").filter('[data-bucket="'+f+'"]').addClass("selected")):i.showError(as3cf.strings.save_bucket_error,c.error,"as3cf-bucket-manual")}})},saveSelected:function(c){var d=a(".as3cf-bucket-list");if(!this.bucketSelectLock){if(this.bucketSelectLock=!0,c.hasClass("selected"))return k.addClass("as3cf-has-bucket"),void b.close();var e=a(".as3cf-bucket-list a.selected").attr("data-bucket");a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),d.addClass("saving"),c.find(".spinner").show().css("visibility","visible");var f=c.attr("data-bucket"),g={action:b.prefix+"-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.save_bucket},h=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:g,error:function(b,c,f){d.removeClass("saving"),h.showError(as3cf.strings.save_bucket_error,f,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected")},success:function(g,i,j){c.find(".spinner").hide().css("visibility","hidden"),d.removeClass("saving"),"undefined"!=typeof g.success?(h.set(f,g.region,g.can_write),a("#"+b.prefix+"-bucket-select").val("")):(h.showError(as3cf.strings.save_bucket_error,g.error,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"))}})}},disabledButtons:function(){if(0!==a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form").length){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");c.find(".as3cf-bucket-name").val().length<3?c.find("button[type=submit]").attr("disabled",!0):c.find("button[type=submit]").attr("disabled",!1),d.find(".as3cf-bucket-name").val().length<3?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").attr("disabled",!1)}},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,(!d||e.hasClass(d))&&(f.find("span.title").html(b+" &mdash;"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},set:function(e,i,j){var m=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),n=a("#"+b.prefix+"-active-bucket");if("as3cf"===b.prefix&&0===n.text().trim().length){d("copy-to-s3-wrap"),d("serve-from-s3-wrap");var o=k.attr("id");l[o]=c(o)}a(".as3cf-error.fatal").hide(),n.text(e),m.find(".as3cf-bucket-name").val(e),a("#"+b.prefix+"-bucket").val(e),a("#"+b.prefix+"-region").val(i),a(".updated").not(".as3cf-notice").show(),k.addClass("as3cf-has-bucket"),k.find(".as3cf-can-write-error").toggle(!j),k.find(".as3cf-bucket-error").hide(),"as3cf"===b.prefix&&g(),f(),b.close(h)},create:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find(".bucket-create-region"),f=c.find("button[type=submit]"),g=d.val(),h=f.text();a(".as3cf-bucket-error").hide(),f.text(f.attr("data-working")),f.prop("disabled",!0);var i={action:b.prefix+"-create-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.create_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.create_bucket_error,c,"as3cf-bucket-create")},success:function(b,c,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof b.success?(j.set(g,b.region,b.can_write),a(".as3cf-bucket-select-region").hide(),a(".as3cf-bucket-select-region").removeAttr("selected"),d.val(""),f.attr("disabled",!0)):j.showError(as3cf.strings.create_bucket_error,b.error,"as3cf-bucket-create")}})},isValidName:function(a){return a.length<3||a.length>63?!1:!0===m.test(a)?!1:!0},updateNameNotice:function(b){var c=null;!0===m.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},a(document).ready(function(){var h=a(".wrap.aws-main .nav-tab-wrapper");if(a(".aws-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(h),window.location.hash){var m=window.location.hash.substring(1);as3cf.tabs.toggle(m,!0)}else k=a("#tab-"+as3cf.tabs.defaultTab),a(".aws-main").attr("data-tab",as3cf.tabs.defaultTab);a(".aws-main").on("click",".nav-tab",function(b){if(b.preventDefault(),!a(this).hasClass("nav-tab-active")){var c=a(this).attr("data-tab");as3cf.tabs.toggle(c),"media"===c?(window.location.hash="","function"==typeof window.history.replaceState&&"#"===window.location.href.slice(-1)&&history.replaceState({},"",window.location.href.slice(0,-1))):window.location.hash=c}}),n.length&&n.each(function(a,b){l[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(l)){var b=k.attr("id");return c(b)!==l[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||d(a(this).attr("id"))}),n.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(b){var c=a(this).closest('input:radio[name="domain"]:checked'),d=c.val(),e=a(this).parents(".as3cf-domain").find(".as3cf-setting.cloudfront"),f="cloudfront"===d;e.toggleClass("hide",!f)}),a(".as3cf-ssl").on("change",'input[type="radio"]',function(b){var c=a('input:radio[name="ssl"]:checked').val();if("https"===c){var d=a('input:radio[name="domain"]:checked').val();"subdomain"===d&&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(a){g()}),i(),a("#serve-from-s3,#remove-local-file").on("change",function(a){i()}),j(),a("#remove-local-file").on("change",function(a){j()}),a('.as3cf-setting input[type="text"]').keypress(function(a){return 13===a.which?(a.preventDefault(),!1):void 0}),a('input[name="cloudfront"]').on("keyup",function(b){e(a(this))}),a('input[name="domain"]').on("change",function(b){var c=a(this),d=a("#"+k.attr("id")+' form button[type="submit"]');"cloudfront"!==c.val()?d.attr("disabled",!1):e(c.next(".as3cf-setting").find('input[name="cloudfront"]'))}),a('input[name="object-prefix"]').on("change",function(a){f()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),a("body").on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),a("body").on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList()}),a("body").on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),a("body").on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),a("body").on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),a("body").on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),a("body").on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),a("body").on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),a("body").on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),a("body").on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").removeAttr("disabled"):e.find("button[type=submit]").attr("disabled",!0),as3cf.buckets.updateNameNotice(d)}),a("body").on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length<as3cf.buckets.validLength?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").removeAttr("disabled")})})}(jQuery,as3cfModal);
assets/sass/styles.scss CHANGED
@@ -3,12 +3,11 @@
3
  * AWS wrap
4
  */
5
  .aws-main.wrap {
6
- &> h2 {
7
  float: left;
8
  }
9
 
10
  .as3cf-notice, .as3cf-updated, .as3cf-error {
11
- margin-bottom: 0;
12
  -webkit-box-sizing: border-box;
13
  -moz-box-sizing: border-box;
14
  box-sizing: border-box;
@@ -21,11 +20,10 @@
21
 
22
  h2.nav-tab-wrapper {
23
  float: none;
24
- margin-bottom: 0;
25
  width: 650px;
26
  margin-top: 10px;
27
- padding-left: 5px;
28
- padding-right: 0;
29
 
30
  a.nav-tab-active {
31
  color: #464646;
@@ -247,6 +245,7 @@
247
 
248
  .form-table {
249
  margin: 0;
 
250
  tr {
251
  &.as3cf-border-bottom td {
252
  border-bottom: 1px solid #ddd;
@@ -264,6 +263,16 @@
264
  vertical-align: top;
265
  min-width: 120px;
266
  }
 
 
 
 
 
 
 
 
 
 
267
  }
268
  }
269
  h3 {
@@ -275,10 +284,21 @@
275
  }
276
  }
277
 
278
- .as3cf-active-bucket {
279
- font-weight: bold;
280
- margin-right: 10px;
281
- }
 
 
 
 
 
 
 
 
 
 
 
282
 
283
  .tooltip {
284
  position: relative;
@@ -405,11 +425,6 @@
405
  }
406
  }
407
 
408
- .as3cf-invalid-bucket-name {
409
- font-size: 12px;
410
- color: #a00;
411
- }
412
-
413
  .bucket-actions {
414
  margin: 15px 0;
415
  border-top: 1px solid #ccc;
@@ -714,4 +729,12 @@
714
  span.title {
715
  font-weight: bold;
716
  }
 
 
 
 
 
 
 
 
717
  }
3
  * AWS wrap
4
  */
5
  .aws-main.wrap {
6
+ & > h1 {
7
  float: left;
8
  }
9
 
10
  .as3cf-notice, .as3cf-updated, .as3cf-error {
 
11
  -webkit-box-sizing: border-box;
12
  -moz-box-sizing: border-box;
13
  box-sizing: border-box;
20
 
21
  h2.nav-tab-wrapper {
22
  float: none;
23
+ margin-bottom: 15px;
24
  width: 650px;
25
  margin-top: 10px;
26
+ padding: 9px 0 0 5px;
 
27
 
28
  a.nav-tab-active {
29
  color: #464646;
245
 
246
  .form-table {
247
  margin: 0;
248
+
249
  tr {
250
  &.as3cf-border-bottom td {
251
  border-bottom: 1px solid #ddd;
263
  vertical-align: top;
264
  min-width: 120px;
265
  }
266
+
267
+ .as3cf-notice:last-child {
268
+ margin-bottom: 0;
269
+ }
270
+ }
271
+
272
+ &:first-of-type {
273
+ td {
274
+ padding-top: 5px;
275
+ }
276
  }
277
  }
278
  h3 {
284
  }
285
  }
286
 
287
+ .as3cf-active-bucket {
288
+ font-weight: bold;
289
+ margin-right: 10px;
290
+ }
291
+ .as3cf-view-bucket {
292
+ color: #444;
293
+ text-decoration: none;
294
+ margin-right: 10px;
295
+ &:hover, &:active {
296
+ color: #00a0d2;
297
+ }
298
+ .dashicons-external {
299
+ margin-top: -2px;
300
+ }
301
+ }
302
 
303
  .tooltip {
304
  position: relative;
425
  }
426
  }
427
 
 
 
 
 
 
428
  .bucket-actions {
429
  margin: 15px 0;
430
  border-top: 1px solid #ccc;
729
  span.title {
730
  font-weight: bold;
731
  }
732
+ }
733
+
734
+ .as3cf-invalid-bucket-name,
735
+ .as3cf-validation-error {
736
+ display: block;
737
+ margin-top: 2px;
738
+ font-size: 12px;
739
+ color: #a00;
740
  }
classes/amazon-s3-and-cloudfront.php CHANGED
@@ -42,6 +42,11 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
42
  */
43
  protected $default_tab = '';
44
 
 
 
 
 
 
45
  /**
46
  * @var string
47
  */
@@ -52,6 +57,16 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
52
  */
53
  protected static $buckets_check = array();
54
 
 
 
 
 
 
 
 
 
 
 
55
  const DEFAULT_ACL = 'public-read';
56
  const PRIVATE_ACL = 'private';
57
  const DEFAULT_EXPIRES = 900;
@@ -70,6 +85,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
70
  parent::__construct( $plugin_file_path );
71
 
72
  $this->aws = $aws;
 
73
 
74
  $this->init( $plugin_file_path );
75
  }
@@ -95,15 +111,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
95
  add_action( 'wp_ajax_as3cf-manual-save-bucket', array( $this, 'ajax_save_bucket' ) );
96
  add_action( 'wp_ajax_as3cf-get-url-preview', array( $this, 'ajax_get_url_preview' ) );
97
 
98
- // Admin notices
99
- add_action( 'admin_notices', array( $this, 'maybe_show_admin_notices' ) );
100
- add_action( 'network_admin_notices', array( $this, 'maybe_show_admin_notices' ) );
101
- add_action( 'shutdown', array( $this, 'save_admin_notices' ) );
102
-
103
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
104
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
105
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 110, 2 );
106
- add_filter( 'wp_get_attachment_metadata', array( $this, 'wp_get_attachment_metadata' ), 10, 2 );
 
 
107
  add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
108
  add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
109
  add_filter( 'get_attached_file', array( $this, 'get_attached_file' ), 10, 2 );
@@ -111,7 +124,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
111
  add_filter( 'pre_get_space_used', array( $this, 'multisite_get_spaced_used' ) );
112
 
113
  // include compatibility code for other plugins
114
- new AS3CF_Plugin_Compatibility( $this );
115
 
116
  load_plugin_textdomain( 'amazon-s3-and-cloudfront', false, dirname( plugin_basename( $plugin_file_path ) ) . '/languages/' );
117
 
@@ -282,9 +295,28 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
282
 
283
  $value = apply_filters( 'as3cf_set_setting_' . $key, $value );
284
 
 
 
 
 
 
285
  parent::set_setting( $key, $value );
286
  }
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  /**
289
  * Return the default object prefix
290
  *
@@ -323,7 +355,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
323
  $interval = $hook;
324
  }
325
  if ( ! wp_next_scheduled( $hook ) ) {
326
- wp_schedule_event( current_time( 'timestamp' ), $interval, $hook, $args );
327
  }
328
  }
329
 
@@ -355,7 +387,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
355
  if ( is_wp_error( $region ) ) {
356
  $region = '';
357
  }
358
- $domain = $this->get_s3_url_domain( $bucket, $region );
359
 
360
  $url = $scheme . '://' . $domain . '/' . $path . $suffix;
361
 
@@ -490,7 +522,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
490
  }
491
 
492
  // upload attachment to S3
493
- $this->upload_attachment_to_s3( $post_id, $data );
494
 
495
  return $data;
496
  }
@@ -508,8 +540,25 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
508
  * @return array|WP_Error $s3object|$meta If meta is supplied, return it. Else return S3 meta
509
  */
510
  function upload_attachment_to_s3( $post_id, $data = null, $file_path = null, $force_new_s3_client = false, $remove_local_files = true ) {
 
511
  if ( is_null( $data ) ) {
512
  $data = wp_get_attachment_metadata( $post_id, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  }
514
 
515
  if ( is_null( $file_path ) ) {
@@ -518,7 +567,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
518
 
519
  // Check file exists locally before attempting upload
520
  if ( ! file_exists( $file_path ) ) {
521
- return new WP_Error( 'exception', sprintf( __( 'File %s does not exist', 'amazon-s3-and-cloudfront' ), $file_path ) );
 
 
522
  }
523
 
524
  $file_name = basename( $file_path );
@@ -527,7 +578,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
527
 
528
  // check mime type of file is in allowed S3 mime types
529
  if ( ! in_array( $type, $allowed_types ) ) {
530
- return new WP_Error( 'exception', sprintf( __( 'Mime type %s is not allowed', 'amazon-s3-and-cloudfront' ), $type ) );
 
 
531
  }
532
 
533
  $acl = self::DEFAULT_ACL;
@@ -590,7 +643,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
590
 
591
  // If far future expiration checked (10 years)
592
  if ( $this->get_setting( 'expires' ) ) {
593
- $args['Expires'] = date( 'D, d M Y H:i:s O', time() + 315360000 );
 
594
  }
595
  $args = apply_filters( 'as3cf_object_meta', $args, $post_id );
596
 
@@ -605,9 +659,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
605
  }
606
  catch ( Exception $e ) {
607
  $error_msg = sprintf( __( 'Error uploading %s to S3: %s', 'amazon-s3-and-cloudfront' ), $file_path, $e->getMessage() );
608
- error_log( $error_msg );
609
 
610
- return new WP_Error( 'exception', $error_msg );
611
  }
612
  }
613
 
@@ -627,8 +680,10 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
627
  // Store in the attachment meta data for use by WP
628
  $data['filesize'] = $bytes;
629
 
630
- // Update metadata with filesize
631
- update_post_meta( $post_id, '_wp_attachment_metadata', $data );
 
 
632
 
633
  // Add to the file size total
634
  $filesize_total += $bytes;
@@ -688,16 +743,43 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
688
  // Make sure we don't have a cached file sizes in the meta
689
  unset( $data['filesize'] );
690
 
691
- // Remove the filesize from the metadata
692
- update_post_meta( $post_id, '_wp_attachment_metadata', $data );
 
 
693
 
694
  delete_post_meta( $post_id, 'wpos3_filesize_total' );
695
  }
696
  }
697
 
 
 
 
 
 
 
 
698
  return $s3object;
699
  }
700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701
  /**
702
  * Remove files from the local site
703
  *
@@ -711,11 +793,31 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
711
  }
712
  }
713
 
 
 
 
 
 
 
 
714
  function get_hidpi_file_path( $orig_path ) {
715
  $hidpi_suffix = apply_filters( 'as3cf_hidpi_suffix', '@2x' );
716
- $pathinfo = pathinfo( $orig_path );
717
 
718
- return $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $hidpi_suffix . '.' . $pathinfo['extension'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  }
720
 
721
  /**
@@ -801,11 +903,6 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
801
  return $file;
802
  }
803
 
804
- // only do this when we are removing local versions of files
805
- if ( ! $this->get_setting( 'remove-local-file' ) ) {
806
- return $file;
807
- }
808
-
809
  $filename = $file['name'];
810
 
811
  // sanitize the file name before we begin processing
@@ -824,37 +921,146 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
824
  // rebuild filename with lowercase extension as S3 will have converted extension on upload
825
  $ext = strtolower( $ext );
826
  $filename = $info['filename'] . $ext;
 
827
 
828
- $time = current_time( 'timestamp' );
829
- $time = date( 'Y/m', $time );
 
 
 
830
 
831
- $prefix = ltrim( trailingslashit( $this->get_object_prefix() ), '/' );
832
- $prefix .= ltrim( trailingslashit( $this->get_dynamic_prefix( $time ) ), '/' );
 
 
 
 
833
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
834
  $bucket = $this->get_setting( 'bucket' );
835
  $region = $this->get_setting( 'region' );
 
836
  if ( is_wp_error( $region ) ) {
837
- return $file;
838
  }
839
 
840
  $s3client = $this->get_s3client( $region );
 
 
841
 
842
- $number = '';
843
- while ( $s3client->doesObjectExist( $bucket, $prefix . $filename ) !== false ) {
844
- $previous = $number;
845
- ++$number;
846
- if ( '' == $previous ) {
847
- $filename = $name . $number . $ext;
848
- } else {
849
- $filename = str_replace( "$previous$ext", $number . $ext, $filename );
850
- }
851
- }
 
 
 
 
 
852
 
853
- $file['name'] = $filename;
 
 
 
854
 
855
- return $file;
856
  }
857
 
 
 
 
 
 
 
 
 
858
  function wp_get_attachment_url( $url, $post_id ) {
859
  $new_url = $this->get_attachment_url( $post_id );
860
  if ( false === $new_url ) {
@@ -867,6 +1073,13 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
867
  return $new_url;
868
  }
869
 
 
 
 
 
 
 
 
870
  function get_attachment_s3_info( $post_id ) {
871
  return get_post_meta( $post_id, 'amazonS3_info', true );
872
  }
@@ -958,10 +1171,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
958
  /**
959
  * Get the custom object prefix if enabled
960
  *
 
 
961
  * @return string
962
  */
963
- function get_object_prefix() {
964
- if ( $this->get_setting( 'enable-object-prefix' ) ) {
965
  $prefix = trim( $this->get_setting( 'object-prefix' ) );
966
  } else {
967
  $prefix = '';
@@ -1121,50 +1336,100 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1121
  }
1122
 
1123
  /**
1124
- * Override the attachment metadata
1125
  *
1126
- * @param unknown $data
1127
- * @param unknown $post_id
 
 
 
 
1128
  *
1129
- * @return mixed
1130
  */
1131
- function wp_get_attachment_metadata( $data, $post_id ) {
1132
- return $this->maybe_encoded_file_of_resized_images( $data, $post_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1133
  }
1134
 
1135
  /**
1136
- * Encodes the file names for resized image files for an attachment where necessary
1137
  *
1138
- * @param array $data
1139
- * @param int $post_id
 
 
1140
  *
1141
- * @return mixed Attachment meta data
1142
  */
1143
- function maybe_encoded_file_of_resized_images( $data, $post_id ) {
1144
  if ( ! $this->get_setting( 'serve-from-s3' ) ) {
1145
- return $data;
 
1146
  }
1147
 
1148
- if ( ! ( $s3object = $this->get_attachment_s3_info( $post_id ) ) ) {
1149
- return $data;
 
1150
  }
1151
 
1152
- // we only need to encode the file name if url encoding is needed
1153
- $filename = basename( $s3object['key'] );
1154
- if ( $filename == rawurlencode( $filename ) ) {
1155
- return $data;
1156
  }
1157
 
1158
- // we only need to encode resized image files
1159
- if ( ! isset( $data['sizes'] ) ) {
1160
- return $data;
 
 
 
 
 
 
 
 
 
 
 
 
 
1161
  }
1162
 
1163
- foreach ( $data['sizes'] as $key => $size ) {
1164
- $data['sizes'][ $key ]['file'] = $this->encode_filename_in_path( $data['sizes'][ $key ]['file'] );
 
1165
  }
1166
 
1167
- return $data;
 
 
 
 
 
 
 
 
 
 
1168
  }
1169
 
1170
  /**
@@ -1176,11 +1441,40 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1176
  * @return string Encoded filename with path prefix untouched
1177
  */
1178
  function encode_filename_in_path( $file ) {
1179
- $file_path = dirname( $file );
1180
- $file_path = ( '.' != $file_path ) ? trailingslashit( $file_path ) : '';
1181
- $file_name = rawurlencode( basename( $file ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1182
 
1183
- return $file_path . $file_name;
 
 
 
 
 
 
 
 
1184
  }
1185
 
1186
  /**
@@ -1498,7 +1792,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1498
  * @param bool|string $region specify region to client for signature
1499
  * @param bool $force force return of new S3 client when swapping regions
1500
  *
1501
- * @return mixed
1502
  */
1503
  function get_s3client( $region = false, $force = false ) {
1504
  if ( is_null( $this->s3client ) || $force ) {
@@ -1739,7 +2033,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1739
  wp_localize_script( 'as3cf-script',
1740
  'as3cf',
1741
  array(
1742
- 'strings' => array(
1743
  'create_bucket_error' => __( 'Error creating bucket', 'amazon-s3-and-cloudfront' ),
1744
  'create_bucket_name_short' => __( 'Bucket name too short.', 'amazon-s3-and-cloudfront' ),
1745
  'create_bucket_name_long' => __( 'Bucket name too long.', 'amazon-s3-and-cloudfront' ),
@@ -1749,19 +2043,21 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1749
  'get_url_preview_error' => __( 'Error getting URL preview: ', 'amazon-s3-and-cloudfront' ),
1750
  'save_alert' => __( 'The changes you made will be lost if you navigate away from this page', 'amazon-s3-and-cloudfront' )
1751
  ),
1752
- 'nonces' => array(
1753
  'create_bucket' => wp_create_nonce( 'as3cf-create-bucket' ),
1754
  'manual_bucket' => wp_create_nonce( 'as3cf-manual-save-bucket' ),
1755
  'get_buckets' => wp_create_nonce( 'as3cf-get-buckets' ),
1756
  'save_bucket' => wp_create_nonce( 'as3cf-save-bucket' ),
1757
  'get_url_preview' => wp_create_nonce( 'as3cf-get-url-preview' ),
1758
  ),
1759
- 'is_pro' => $this->is_pro(),
 
1760
  )
1761
  );
1762
 
1763
  $this->handle_post_request();
1764
  $this->http_prepare_download_log();
 
1765
 
1766
  do_action( 'as3cf_plugin_load' );
1767
  }
@@ -1998,6 +2294,22 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
1998
  return true;
1999
  }
2000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2001
  /**
2002
  * Apply ACL to an attachment and associated files
2003
  *
@@ -2022,7 +2334,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2022
 
2023
  // Add attachment to ACL update notice
2024
  $message = $this->make_acl_admin_notice_text( $s3object );
2025
- $this->set_admin_notice( $message );
2026
 
2027
  // update S3 meta data
2028
  if ( $acl == self::DEFAULT_ACL ) {
@@ -2049,52 +2361,17 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2049
  }
2050
 
2051
  /**
2052
- * Set admin notice
2053
- *
2054
- * @param string $message
2055
- * @param string $type info, updated, error
2056
- * @param bool $dismissible
2057
- * @param bool $inline
2058
- */
2059
- function set_admin_notice( $message, $type = 'info', $dismissible = true, $inline = false ) {
2060
- self::$admin_notices[] = array(
2061
- 'message' => $message,
2062
- 'type' => $type,
2063
- 'dismissible' => $dismissible,
2064
- 'inline' => $inline,
2065
- );
2066
- }
2067
-
2068
- /**
2069
- * Save admin notices to transients before shutdown
2070
- */
2071
- function save_admin_notices() {
2072
- if ( ! empty( self::$admin_notices ) ) {
2073
- set_site_transient( 'as3cf_notices', self::$admin_notices );
2074
- }
2075
- }
2076
-
2077
- /**
2078
- * Maybe show notices on admin page
2079
  */
2080
- function maybe_show_admin_notices() {
2081
- if ( $notices = get_site_transient( 'as3cf_notices' ) ) {
2082
- foreach ( $notices as $notice ) {
2083
- if ( 'info' === $notice['type'] ) {
2084
- $notice['type'] = 'notice-info';
2085
- }
2086
-
2087
- $args = array(
2088
- 'message' => $notice['message'],
2089
- 'type' => $notice['type'],
2090
- 'dismissible' => $notice['dismissible'],
2091
- 'inline' => $notice['inline'],
2092
- );
2093
-
2094
- $this->render_view( 'notice', $args );
2095
- }
2096
 
2097
- delete_site_transient( 'as3cf_notices' );
 
 
 
 
2098
  }
2099
  }
2100
 
@@ -2148,6 +2425,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2148
  echo empty( $wpdb->use_mysqli ) ? 'no' : 'yes';
2149
  echo "\r\n";
2150
 
 
 
 
 
 
 
2151
  echo 'WP Memory Limit: ';
2152
  echo esc_html( WP_MEMORY_LIMIT );
2153
  echo "\r\n";
@@ -2190,6 +2473,10 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2190
  }
2191
  echo "\r\n";
2192
 
 
 
 
 
2193
  echo 'fsockopen: ';
2194
  if ( function_exists( 'fsockopen' ) ) {
2195
  echo 'Enabled';
@@ -2220,6 +2507,23 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2220
  } else {
2221
  echo 'Disabled';
2222
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2223
  echo "\r\n\r\n";
2224
 
2225
  $media_counts = $this->diagnostic_media_counts();
@@ -2294,6 +2598,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2294
 
2295
  echo "Active Plugins:\r\n";
2296
  $active_plugins = (array) get_option( 'active_plugins', array() );
 
2297
 
2298
  if ( is_multisite() ) {
2299
  $network_active_plugins = wp_get_active_network_plugins();
@@ -2301,7 +2606,24 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2301
  }
2302
 
2303
  foreach ( $active_plugins as $plugin ) {
2304
- $this->print_plugin_details( WP_PLUGIN_DIR . '/' . $plugin );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2305
  }
2306
  }
2307
 
@@ -2323,14 +2645,16 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2323
  *
2324
  * @param string $plugin_path
2325
  * @param string $suffix
 
 
2326
  */
2327
- function print_plugin_details( $plugin_path, $suffix = '' ) {
2328
  $plugin_data = get_plugin_data( $plugin_path );
2329
  if ( empty( $plugin_data['Name'] ) ) {
2330
- return;
2331
  }
2332
 
2333
- printf( "%s%s (v%s) by %s\r\n", $plugin_data['Name'], $suffix, $plugin_data['Version'], strip_tags( $plugin_data['AuthorName'] ) );
2334
  }
2335
 
2336
  /**
@@ -2393,6 +2717,32 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2393
  }
2394
  }
2395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2396
  /**
2397
  * Is the current blog ID that specified in wp-config.php
2398
  *
@@ -2523,6 +2873,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2523
  }
2524
  }
2525
 
 
 
 
2526
  // Remove duplicates
2527
  $paths = array_unique( $paths );
2528
 
@@ -2566,26 +2919,22 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
2566
  * @return float|int
2567
  */
2568
  function multisite_get_spaced_used( $space_used ) {
2569
- if ( false === ( $space_used = get_transient( 'wpos3_site_space_used' ) ) ) {
2570
- global $wpdb;
2571
 
2572
- // Sum the total file size (including image sizes) for all S3 attachments
2573
- $sql = "SELECT SUM( meta_value ) AS bytes_total
2574
  FROM {$wpdb->postmeta}
2575
  WHERE meta_key = 'wpos3_filesize_total'";
2576
 
2577
- $space_used = $wpdb->get_var( $sql );
2578
 
2579
- // Get local upload sizes
2580
- $upload_dir = wp_upload_dir();
2581
- $space_used += get_dirsize( $upload_dir['basedir'] );
2582
-
2583
- if ( $space_used > 0 ) {
2584
- // Convert to bytes to MB
2585
- $space_used = $space_used / 1024 / 1024;
2586
- }
2587
 
2588
- set_transient( 'wpos3_site_space_used', $space_used, HOUR_IN_SECONDS );
 
 
2589
  }
2590
 
2591
  return $space_used;
42
  */
43
  protected $default_tab = '';
44
 
45
+ /**
46
+ * @var AS3CF_Notices
47
+ */
48
+ public $notices;
49
+
50
  /**
51
  * @var string
52
  */
57
  */
58
  protected static $buckets_check = array();
59
 
60
+ /**
61
+ * @var array
62
+ */
63
+ protected $encode_files = array();
64
+
65
+ /**
66
+ * @var AS3CF_Plugin_Compatibility
67
+ */
68
+ public $plugin_compat;
69
+
70
  const DEFAULT_ACL = 'public-read';
71
  const PRIVATE_ACL = 'private';
72
  const DEFAULT_EXPIRES = 900;
85
  parent::__construct( $plugin_file_path );
86
 
87
  $this->aws = $aws;
88
+ $this->notices = AS3CF_Notices::get_instance( $this, $plugin_file_path );
89
 
90
  $this->init( $plugin_file_path );
91
  }
111
  add_action( 'wp_ajax_as3cf-manual-save-bucket', array( $this, 'ajax_save_bucket' ) );
112
  add_action( 'wp_ajax_as3cf-get-url-preview', array( $this, 'ajax_get_url_preview' ) );
113
 
 
 
 
 
 
114
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
115
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
116
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 110, 2 );
117
+ add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 10, 6 );
118
+ add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 10, 4 );
119
+ add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js' ), 10, 3 );
120
  add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
121
  add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
122
  add_filter( 'get_attached_file', array( $this, 'get_attached_file' ), 10, 2 );
124
  add_filter( 'pre_get_space_used', array( $this, 'multisite_get_spaced_used' ) );
125
 
126
  // include compatibility code for other plugins
127
+ $this->plugin_compat = new AS3CF_Plugin_Compatibility( $this );
128
 
129
  load_plugin_textdomain( 'amazon-s3-and-cloudfront', false, dirname( plugin_basename( $plugin_file_path ) ) . '/languages/' );
130
 
295
 
296
  $value = apply_filters( 'as3cf_set_setting_' . $key, $value );
297
 
298
+ // Remove disallowed characters from custom domain
299
+ if ( 'cloudfront' === $key ) {
300
+ $value = $this->sanitize_custom_domain( $value );
301
+ }
302
+
303
  parent::set_setting( $key, $value );
304
  }
305
 
306
+ /**
307
+ * Sanitize custom domain
308
+ *
309
+ * @param string $domain
310
+ *
311
+ * @return string
312
+ */
313
+ function sanitize_custom_domain( $domain ) {
314
+ $domain = preg_replace( '@^[a-zA-Z]*:\/\/@', '', $domain );
315
+ $domain = preg_replace( '@[^a-zA-Z0-9\.\-]@', '', $domain );
316
+
317
+ return $domain;
318
+ }
319
+
320
  /**
321
  * Return the default object prefix
322
  *
355
  $interval = $hook;
356
  }
357
  if ( ! wp_next_scheduled( $hook ) ) {
358
+ wp_schedule_event( time(), $interval, $hook, $args );
359
  }
360
  }
361
 
387
  if ( is_wp_error( $region ) ) {
388
  $region = '';
389
  }
390
+ $domain = $this->sanitize_custom_domain( $this->get_s3_url_domain( $bucket, $region ) );
391
 
392
  $url = $scheme . '://' . $domain . '/' . $path . $suffix;
393
 
522
  }
523
 
524
  // upload attachment to S3
525
+ $data = $this->upload_attachment_to_s3( $post_id, $data );
526
 
527
  return $data;
528
  }
540
  * @return array|WP_Error $s3object|$meta If meta is supplied, return it. Else return S3 meta
541
  */
542
  function upload_attachment_to_s3( $post_id, $data = null, $file_path = null, $force_new_s3_client = false, $remove_local_files = true ) {
543
+ $return_metadata = null;
544
  if ( is_null( $data ) ) {
545
  $data = wp_get_attachment_metadata( $post_id, true );
546
+ } else {
547
+ // As we have passed in the meta, return it later
548
+ $return_metadata = $data;
549
+ }
550
+
551
+ // Allow S3 upload to be hijacked / cancelled for any reason
552
+ $pre = apply_filters( 'as3cf_pre_upload_attachment', false, $post_id, $data );
553
+ if ( false !== $pre ) {
554
+ if ( ! is_null( $return_metadata ) ) {
555
+ // If the attachment metadata is supplied, return it
556
+ return $data;
557
+ }
558
+
559
+ $error_msg = is_string( $pre ) ? $pre : __( 'Upload aborted by filter \'as3cf_pre_upload_attachment\'', 'amazon-s3-and-cloudfront' );
560
+
561
+ return $this->return_upload_error( $error_msg );
562
  }
563
 
564
  if ( is_null( $file_path ) ) {
567
 
568
  // Check file exists locally before attempting upload
569
  if ( ! file_exists( $file_path ) ) {
570
+ $error_msg = sprintf( __( 'File %s does not exist', 'amazon-s3-and-cloudfront' ), $file_path );
571
+
572
+ return $this->return_upload_error( $error_msg, $return_metadata );
573
  }
574
 
575
  $file_name = basename( $file_path );
578
 
579
  // check mime type of file is in allowed S3 mime types
580
  if ( ! in_array( $type, $allowed_types ) ) {
581
+ $error_msg = sprintf( __( 'Mime type %s is not allowed', 'amazon-s3-and-cloudfront' ), $type );
582
+
583
+ return $this->return_upload_error( $error_msg, $return_metadata );
584
  }
585
 
586
  $acl = self::DEFAULT_ACL;
643
 
644
  // If far future expiration checked (10 years)
645
  if ( $this->get_setting( 'expires' ) ) {
646
+ $args['CacheControl'] = 'max-age=315360000';
647
+ $args['Expires'] = date( 'D, d M Y H:i:s O', time() + 315360000 );
648
  }
649
  $args = apply_filters( 'as3cf_object_meta', $args, $post_id );
650
 
659
  }
660
  catch ( Exception $e ) {
661
  $error_msg = sprintf( __( 'Error uploading %s to S3: %s', 'amazon-s3-and-cloudfront' ), $file_path, $e->getMessage() );
 
662
 
663
+ return $this->return_upload_error( $error_msg, $return_metadata );
664
  }
665
  }
666
 
680
  // Store in the attachment meta data for use by WP
681
  $data['filesize'] = $bytes;
682
 
683
+ if ( is_null( $return_metadata ) ) {
684
+ // Update metadata with filesize
685
+ update_post_meta( $post_id, '_wp_attachment_metadata', $data );
686
+ }
687
 
688
  // Add to the file size total
689
  $filesize_total += $bytes;
743
  // Make sure we don't have a cached file sizes in the meta
744
  unset( $data['filesize'] );
745
 
746
+ if ( is_null( $return_metadata ) ) {
747
+ // Remove the filesize from the metadata
748
+ update_post_meta( $post_id, '_wp_attachment_metadata', $data );
749
+ }
750
 
751
  delete_post_meta( $post_id, 'wpos3_filesize_total' );
752
  }
753
  }
754
 
755
+ do_action( 'wpos3_post_upload_attachment', $post_id, $s3object );
756
+
757
+ if ( ! is_null( $return_metadata ) ) {
758
+ // If the attachment metadata is supplied, return it
759
+ return $data;
760
+ }
761
+
762
  return $s3object;
763
  }
764
 
765
+ /**
766
+ * Helper to return meta data on upload error
767
+ *
768
+ * @param string $error_msg
769
+ * @param array|null $return
770
+ *
771
+ * @return array|WP_Error
772
+ */
773
+ protected function return_upload_error( $error_msg, $return = null ) {
774
+ if ( is_null( $return ) ) {
775
+ return new WP_Error( 'exception', $error_msg );
776
+ }
777
+
778
+ error_log( $error_msg );
779
+
780
+ return $return;
781
+ }
782
+
783
  /**
784
  * Remove files from the local site
785
  *
793
  }
794
  }
795
 
796
+ /**
797
+ * Add HiDPi suffix to a file path
798
+ *
799
+ * @param string $orig_path
800
+ *
801
+ * @return string
802
+ */
803
  function get_hidpi_file_path( $orig_path ) {
804
  $hidpi_suffix = apply_filters( 'as3cf_hidpi_suffix', '@2x' );
 
805
 
806
+ return $this->apply_file_suffix( $orig_path, $hidpi_suffix );
807
+ }
808
+
809
+ /**
810
+ * Helper to apply a suffix to a file path
811
+ *
812
+ * @param string $file
813
+ * @param string $suffix
814
+ *
815
+ * @return string
816
+ */
817
+ function apply_file_suffix( $file, $suffix ) {
818
+ $pathinfo = pathinfo( $file );
819
+
820
+ return $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $suffix . '.' . $pathinfo['extension'];
821
  }
822
 
823
  /**
903
  return $file;
904
  }
905
 
 
 
 
 
 
906
  $filename = $file['name'];
907
 
908
  // sanitize the file name before we begin processing
921
  // rebuild filename with lowercase extension as S3 will have converted extension on upload
922
  $ext = strtolower( $ext );
923
  $filename = $info['filename'] . $ext;
924
+ $time = current_time( 'mysql' );
925
 
926
+ // Get time if uploaded in post screen
927
+ $post_id = filter_input( INPUT_POST, 'post_id', FILTER_VALIDATE_INT );
928
+ if ( isset( $post_id ) ) {
929
+ $time = $this->get_post_time( $post_id );
930
+ }
931
 
932
+ if ( ! $this->does_file_exist( $filename, $time ) ) {
933
+ // File doesn't exist locally or on S3, return it
934
+ return $file;
935
+ }
936
+
937
+ $file['name'] = $this->generate_unique_filename( $name, $ext, $time );
938
 
939
+ return $file;
940
+ }
941
+
942
+ /**
943
+ * Get post time
944
+ *
945
+ * @param int $post_id
946
+ *
947
+ * @return string
948
+ */
949
+ function get_post_time( $post_id ) {
950
+ $time = current_time( 'mysql' );
951
+
952
+ if ( ! $post = get_post( $post_id ) ) {
953
+ return $time;
954
+ }
955
+
956
+ if ( substr( $post->post_date, 0, 4 ) > 0 ) {
957
+ $time = $post->post_date;
958
+ }
959
+
960
+ return $time;
961
+ }
962
+
963
+ /**
964
+ * Does file exist
965
+ *
966
+ * @param string $filename
967
+ * @param string $time
968
+ *
969
+ * @return bool
970
+ */
971
+ function does_file_exist( $filename, $time ) {
972
+ if ( $this->does_file_exist_local( $filename, $time ) ) {
973
+ return true;
974
+ }
975
+
976
+ if ( ! $this->get_setting( 'object-versioning' ) && $this->does_file_exist_s3( $filename, $time ) ) {
977
+ return true;
978
+ }
979
+
980
+ return false;
981
+ }
982
+
983
+ /**
984
+ * Does file exist local
985
+ *
986
+ * @param string $filename
987
+ * @param string $time
988
+ *
989
+ * @return bool
990
+ */
991
+ function does_file_exist_local( $filename, $time ) {
992
+ global $wpdb;
993
+
994
+ $path = wp_upload_dir( $time );
995
+ $path = ltrim( $path['subdir'], '/' );
996
+
997
+ if ( '' !== $path ) {
998
+ $path = trailingslashit( $path );
999
+ }
1000
+ $file = $path . $filename;
1001
+
1002
+ $sql = $wpdb->prepare( "
1003
+ SELECT COUNT(*)
1004
+ FROM $wpdb->postmeta
1005
+ WHERE meta_key = %s
1006
+ AND meta_value = %s
1007
+ ", '_wp_attached_file', $file );
1008
+
1009
+ return (bool) $wpdb->get_var( $sql );
1010
+ }
1011
+
1012
+ /**
1013
+ * Does file exist s3
1014
+ *
1015
+ * @param string $filename
1016
+ * @param string $time
1017
+ *
1018
+ * @return bool
1019
+ */
1020
+ function does_file_exist_s3( $filename, $time ) {
1021
  $bucket = $this->get_setting( 'bucket' );
1022
  $region = $this->get_setting( 'region' );
1023
+
1024
  if ( is_wp_error( $region ) ) {
1025
+ return false;
1026
  }
1027
 
1028
  $s3client = $this->get_s3client( $region );
1029
+ $prefix = ltrim( trailingslashit( $this->get_object_prefix() ), '/' );
1030
+ $prefix .= ltrim( trailingslashit( $this->get_dynamic_prefix( $time ) ), '/' );
1031
 
1032
+ return $s3client->doesObjectExist( $bucket, $prefix . $filename );
1033
+ }
1034
+
1035
+ /**
1036
+ * Generate unique filename
1037
+ *
1038
+ * @param string $name
1039
+ * @param string $ext
1040
+ * @param string $time
1041
+ *
1042
+ * @return string
1043
+ */
1044
+ function generate_unique_filename( $name, $ext, $time ) {
1045
+ $count = 1;
1046
+ $filename = $name . $count . $ext;
1047
 
1048
+ while ( $this->does_file_exist( $filename, $time ) ) {
1049
+ $count++;
1050
+ $filename = $name . $count . $ext;
1051
+ }
1052
 
1053
+ return $filename;
1054
  }
1055
 
1056
+ /**
1057
+ * Get attachment url
1058
+ *
1059
+ * @param string $url
1060
+ * @param int $post_id
1061
+ *
1062
+ * @return bool|mixed|void|WP_Error
1063
+ */
1064
  function wp_get_attachment_url( $url, $post_id ) {
1065
  $new_url = $this->get_attachment_url( $post_id );
1066
  if ( false === $new_url ) {
1073
  return $new_url;
1074
  }
1075
 
1076
+ /**
1077
+ * Get attachment s3 info
1078
+ *
1079
+ * @param int $post_id
1080
+ *
1081
+ * @return mixed
1082
+ */
1083
  function get_attachment_s3_info( $post_id ) {
1084
  return get_post_meta( $post_id, 'amazonS3_info', true );
1085
  }
1171
  /**
1172
  * Get the custom object prefix if enabled
1173
  *
1174
+ * @param string $toggle_setting
1175
+ *
1176
  * @return string
1177
  */
1178
+ function get_object_prefix( $toggle_setting = 'enable-object-prefix' ) {
1179
+ if ( $this->get_setting( $toggle_setting ) ) {
1180
  $prefix = trim( $this->get_setting( 'object-prefix' ) );
1181
  } else {
1182
  $prefix = '';
1336
  }
1337
 
1338
  /**
1339
+ * Maybe encode attachment URLs when retrieving the image tag
1340
  *
1341
+ * @param string $html
1342
+ * @param int $id
1343
+ * @param string $alt
1344
+ * @param string $title
1345
+ * @param string $align
1346
+ * @param string $size
1347
  *
1348
+ * @return string
1349
  */
1350
+ function maybe_encode_get_image_tag( $html, $id, $alt, $title, $align, $size ) {
1351
+ if ( ! $this->get_setting( 'serve-from-s3' ) ) {
1352
+ // Not serving S3 URLs
1353
+ return $html;
1354
+ }
1355
+
1356
+ if ( ! $this->get_attachment_s3_info( $id ) ) {
1357
+ // File not uploaded to S3
1358
+ return $html;
1359
+ }
1360
+
1361
+ preg_match( '@\ssrc=[\'\"]([^\'\"]*)[\'\"]@', $html, $matches );
1362
+
1363
+ if ( ! isset( $matches[1] ) ) {
1364
+ // Can't establish img src
1365
+ return $html;
1366
+ }
1367
+
1368
+ $img_src = $matches[1];
1369
+ $encoded_src = $this->encode_filename_in_path( $img_src );
1370
+
1371
+ return str_replace( $img_src, $encoded_src, $html );
1372
  }
1373
 
1374
  /**
1375
+ * Maybe encode URLs for images that represent an attachment
1376
  *
1377
+ * @param array|bool $image
1378
+ * @param int $attachment_id
1379
+ * @param string|array $size
1380
+ * @param bool $icon
1381
  *
1382
+ * @return array
1383
  */
1384
+ function maybe_encode_wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
1385
  if ( ! $this->get_setting( 'serve-from-s3' ) ) {
1386
+ // Not serving S3 URLs
1387
+ return $image;
1388
  }
1389
 
1390
+ if ( ! $this->get_attachment_s3_info( $attachment_id ) ) {
1391
+ // File not uploaded to S3
1392
+ return $image;
1393
  }
1394
 
1395
+ if ( isset( $image[0] ) ) {
1396
+ $image[0] = $this->encode_filename_in_path( $image[0] );
 
 
1397
  }
1398
 
1399
+ return $image;
1400
+ }
1401
+
1402
+ /**
1403
+ * Maybe encode URLs when outputting attachments in the media grid
1404
+ *
1405
+ * @param array $response
1406
+ * @param int|object $attachment
1407
+ * @param array $meta
1408
+ *
1409
+ * @return array
1410
+ */
1411
+ function maybe_encode_wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
1412
+ if ( ! $this->get_setting( 'serve-from-s3' ) ) {
1413
+ // Not serving S3 URLs
1414
+ return $response;
1415
  }
1416
 
1417
+ if ( ! $this->get_attachment_s3_info( $attachment->ID ) ) {
1418
+ // File not uploaded to S3
1419
+ return $response;
1420
  }
1421
 
1422
+ if ( isset( $response['url'] ) ) {
1423
+ $response['url'] = $this->encode_filename_in_path( $response['url'] );
1424
+ }
1425
+
1426
+ if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
1427
+ foreach ( $response['sizes'] as $key => $value ) {
1428
+ $response['sizes'][ $key ]['url'] = $this->encode_filename_in_path( $value['url'] );
1429
+ }
1430
+ }
1431
+
1432
+ return $response;
1433
  }
1434
 
1435
  /**
1441
  * @return string Encoded filename with path prefix untouched
1442
  */
1443
  function encode_filename_in_path( $file ) {
1444
+ $url = parse_url( $file );
1445
+
1446
+ if ( ! isset( $url['path'] ) ) {
1447
+ return $file;
1448
+ }
1449
+
1450
+ if ( in_array( $this->leading_slash_it( $url['path'] ), $this->encode_files ) ) {
1451
+ // Already encoded return original file
1452
+ return $file;
1453
+ }
1454
+
1455
+ $file_path = dirname( $file );
1456
+ $file_path = ( '.' !== $file_path ) ? trailingslashit( $file_path ) : '';
1457
+ $file_name = basename( $file );
1458
+ $encoded_file_name = rawurlencode( $file_name );
1459
+ $encoded_file_path = $file_path . $encoded_file_name;
1460
+
1461
+ if ( $file_name !== $encoded_file_name ) {
1462
+ $encoded_url = parse_url( $encoded_file_path );
1463
+ $this->encode_files[] = $this->leading_slash_it( $encoded_url['path'] );
1464
+ }
1465
+
1466
+ return $file_path . $encoded_file_name;
1467
+ }
1468
 
1469
+ /**
1470
+ * Leading slash it
1471
+ *
1472
+ * @param string $path
1473
+ *
1474
+ * @return string
1475
+ */
1476
+ function leading_slash_it( $path ) {
1477
+ return '/' . ltrim( $path, '/\\' );
1478
  }
1479
 
1480
  /**
1792
  * @param bool|string $region specify region to client for signature
1793
  * @param bool $force force return of new S3 client when swapping regions
1794
  *
1795
+ * @return Aws\S3\S3Client
1796
  */
1797
  function get_s3client( $region = false, $force = false ) {
1798
  if ( is_null( $this->s3client ) || $force ) {
2033
  wp_localize_script( 'as3cf-script',
2034
  'as3cf',
2035
  array(
2036
+ 'strings' => array(
2037
  'create_bucket_error' => __( 'Error creating bucket', 'amazon-s3-and-cloudfront' ),
2038
  'create_bucket_name_short' => __( 'Bucket name too short.', 'amazon-s3-and-cloudfront' ),
2039
  'create_bucket_name_long' => __( 'Bucket name too long.', 'amazon-s3-and-cloudfront' ),
2043
  'get_url_preview_error' => __( 'Error getting URL preview: ', 'amazon-s3-and-cloudfront' ),
2044
  'save_alert' => __( 'The changes you made will be lost if you navigate away from this page', 'amazon-s3-and-cloudfront' )
2045
  ),
2046
+ 'nonces' => array(
2047
  'create_bucket' => wp_create_nonce( 'as3cf-create-bucket' ),
2048
  'manual_bucket' => wp_create_nonce( 'as3cf-manual-save-bucket' ),
2049
  'get_buckets' => wp_create_nonce( 'as3cf-get-buckets' ),
2050
  'save_bucket' => wp_create_nonce( 'as3cf-save-bucket' ),
2051
  'get_url_preview' => wp_create_nonce( 'as3cf-get-url-preview' ),
2052
  ),
2053
+ 'is_pro' => $this->is_pro(),
2054
+ 'aws_bucket_link' => $this->get_aws_bucket_link(),
2055
  )
2056
  );
2057
 
2058
  $this->handle_post_request();
2059
  $this->http_prepare_download_log();
2060
+ $this->check_for_gd_imagick();
2061
 
2062
  do_action( 'as3cf_plugin_load' );
2063
  }
2294
  return true;
2295
  }
2296
 
2297
+ /**
2298
+ * Get the link to the bucket on the AWS console
2299
+ *
2300
+ * @param string $bucket
2301
+ * @param string $prefix
2302
+ *
2303
+ * @return string
2304
+ */
2305
+ function get_aws_bucket_link( $bucket = '', $prefix = '' ) {
2306
+ if ( '' !== $prefix ) {
2307
+ $prefix = '&prefix=' . urlencode( $prefix );
2308
+ }
2309
+
2310
+ return 'https://console.aws.amazon.com/s3/home?bucket=' . $bucket . $prefix;
2311
+ }
2312
+
2313
  /**
2314
  * Apply ACL to an attachment and associated files
2315
  *
2334
 
2335
  // Add attachment to ACL update notice
2336
  $message = $this->make_acl_admin_notice_text( $s3object );
2337
+ $this->notices->add_notice( $message );
2338
 
2339
  // update S3 meta data
2340
  if ( $acl == self::DEFAULT_ACL ) {
2361
  }
2362
 
2363
  /**
2364
+ * Check if PHP GD and Imagick is installed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2365
  */
2366
+ function check_for_gd_imagick() {
2367
+ $gd_enabled = $this->gd_enabled();
2368
+ $imagick_enabled = $this->imagick_enabled();
 
 
 
 
 
 
 
 
 
 
 
 
 
2369
 
2370
+ if( ! $gd_enabled && ! $imagick_enabled ) {
2371
+ $this->notices->add_notice(
2372
+ __( '<strong>Image Manipulation Library Missing</strong> &mdash; Looks like you don\'t have an image manipulation library installed on this server and configured with PHP. You may run into trouble if you try to edit images. Please setup GD or ImageMagick.', 'amazon-s3-and-cloudfront' ),
2373
+ array( 'flash' => false, 'only_show_to_user' => false, 'only_show_in_settings' => true )
2374
+ );
2375
  }
2376
  }
2377
 
2425
  echo empty( $wpdb->use_mysqli ) ? 'no' : 'yes';
2426
  echo "\r\n";
2427
 
2428
+ echo 'PHP Memory Limit: ';
2429
+ if ( function_exists( 'ini_get' ) ) {
2430
+ echo esc_html( ini_get( 'memory_limit' ) );
2431
+ }
2432
+ echo "\r\n";
2433
+
2434
  echo 'WP Memory Limit: ';
2435
  echo esc_html( WP_MEMORY_LIMIT );
2436
  echo "\r\n";
2473
  }
2474
  echo "\r\n";
2475
 
2476
+ echo 'WP Cron: ';
2477
+ echo esc_html( ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ? 'Disabled' : 'Enabled' );
2478
+ echo "\r\n";
2479
+
2480
  echo 'fsockopen: ';
2481
  if ( function_exists( 'fsockopen' ) ) {
2482
  echo 'Enabled';
2507
  } else {
2508
  echo 'Disabled';
2509
  }
2510
+ echo "\r\n";
2511
+
2512
+ echo 'PHP GD: ';
2513
+ if ( $this->gd_enabled() ) {
2514
+ $gd_info = gd_info();
2515
+ echo isset( $gd_info['GD Version'] ) ? esc_html( $gd_info['GD Version'] ) : 'Enabled';
2516
+ } else {
2517
+ echo 'Disabled';
2518
+ }
2519
+ echo "\r\n";
2520
+
2521
+ echo 'Imagick: ';
2522
+ if ( $this->imagick_enabled() ) {
2523
+ echo 'Enabled';
2524
+ } else {
2525
+ echo 'Disabled';
2526
+ }
2527
  echo "\r\n\r\n";
2528
 
2529
  $media_counts = $this->diagnostic_media_counts();
2598
 
2599
  echo "Active Plugins:\r\n";
2600
  $active_plugins = (array) get_option( 'active_plugins', array() );
2601
+ $plugin_details = array();
2602
 
2603
  if ( is_multisite() ) {
2604
  $network_active_plugins = wp_get_active_network_plugins();
2606
  }
2607
 
2608
  foreach ( $active_plugins as $plugin ) {
2609
+ $plugin_details[] = $this->get_plugin_details( WP_PLUGIN_DIR . '/' . $plugin );
2610
+ }
2611
+
2612
+ asort( $plugin_details );
2613
+ echo implode( '', $plugin_details );
2614
+
2615
+ $mu_plugins = wp_get_mu_plugins();
2616
+ if ( $mu_plugins ) {
2617
+ $mu_plugin_details = array();
2618
+ echo "\r\n";
2619
+ echo "Must-use Plugins:\r\n";
2620
+
2621
+ foreach ( $mu_plugins as $mu_plugin ) {
2622
+ $mu_plugin_details[] = $this->get_plugin_details( $mu_plugin );
2623
+ }
2624
+
2625
+ asort( $mu_plugin_details );
2626
+ echo implode( '', $mu_plugin_details );
2627
  }
2628
  }
2629
 
2645
  *
2646
  * @param string $plugin_path
2647
  * @param string $suffix
2648
+ *
2649
+ * @return string
2650
  */
2651
+ function get_plugin_details( $plugin_path, $suffix = '' ) {
2652
  $plugin_data = get_plugin_data( $plugin_path );
2653
  if ( empty( $plugin_data['Name'] ) ) {
2654
+ return basename( $plugin_path );
2655
  }
2656
 
2657
+ return sprintf( "%s%s (v%s) by %s\r\n", $plugin_data['Name'], $suffix, $plugin_data['Version'], strip_tags( $plugin_data['AuthorName'] ) );
2658
  }
2659
 
2660
  /**
2717
  }
2718
  }
2719
 
2720
+ /**
2721
+ * Detect if PHP GD is enabled
2722
+ *
2723
+ * @return bool
2724
+ */
2725
+ function gd_enabled() {
2726
+ if ( extension_loaded( 'gd' ) && function_exists( 'gd_info' ) ) {
2727
+ return true;
2728
+ } else {
2729
+ return false;
2730
+ }
2731
+ }
2732
+
2733
+ /**
2734
+ * Detect is Imagick is enabled
2735
+ *
2736
+ * @return bool
2737
+ */
2738
+ function imagick_enabled() {
2739
+ if ( extension_loaded( 'imagick' ) && class_exists( 'Imagick' ) && class_exists( 'ImagickPixel' ) ) {
2740
+ return true;
2741
+ } else {
2742
+ return false;
2743
+ }
2744
+ }
2745
+
2746
  /**
2747
  * Is the current blog ID that specified in wp-config.php
2748
  *
2873
  }
2874
  }
2875
 
2876
+ // Allow other processes to add files to be uploaded
2877
+ $paths = apply_filters( 'as3cf_attachment_file_paths', $paths, $attachment_id, $meta );
2878
+
2879
  // Remove duplicates
2880
  $paths = array_unique( $paths );
2881
 
2919
  * @return float|int
2920
  */
2921
  function multisite_get_spaced_used( $space_used ) {
2922
+ global $wpdb;
 
2923
 
2924
+ // Sum the total file size (including image sizes) for all S3 attachments
2925
+ $sql = "SELECT SUM( meta_value ) AS bytes_total
2926
  FROM {$wpdb->postmeta}
2927
  WHERE meta_key = 'wpos3_filesize_total'";
2928
 
2929
+ $space_used = $wpdb->get_var( $sql );
2930
 
2931
+ // Get local upload sizes
2932
+ $upload_dir = wp_upload_dir();
2933
+ $space_used += get_dirsize( $upload_dir['basedir'] );
 
 
 
 
 
2934
 
2935
+ if ( $space_used > 0 ) {
2936
+ // Convert to bytes to MB
2937
+ $space_used = $space_used / 1024 / 1024;
2938
  }
2939
 
2940
  return $space_used;
classes/as3cf-notices.php ADDED
@@ -0,0 +1,324 @@