| 1 |
<?php |
| 2 |
/** |
| 3 |
* File Download routines for s2Member ( inner processing routines ). |
| 4 |
* |
| 5 |
* Copyright: © 2009-2011 |
| 6 |
* {@link http://www.websharks-inc.com/ WebSharks, Inc.} |
| 7 |
* ( coded in the USA ) |
| 8 |
* |
| 9 |
* Released under the terms of the GNU General Public License. |
| 10 |
* You should have received a copy of the GNU General Public License, |
| 11 |
* along with this software. In the main directory, see: /licensing/ |
| 12 |
* If not, see: {@link http://www.gnu.org/licenses/}. |
| 13 |
* |
| 14 |
* @package s2Member\Files |
| 15 |
* @since 3.5 |
| 16 |
*/ |
| 17 |
if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"])) |
| 18 |
exit("Do not access this file directly."); |
| 19 |
/**/ |
| 20 |
if (!class_exists ("c_ws_plugin__s2member_files_in")) |
| 21 |
{ |
| 22 |
/** |
| 23 |
* File Download routines for s2Member ( inner processing routines ). |
| 24 |
* |
| 25 |
* @package s2Member\Files |
| 26 |
* @since 3.5 |
| 27 |
*/ |
| 28 |
class c_ws_plugin__s2member_files_in |
| 29 |
{ |
| 30 |
/** |
| 31 |
* Handles Download Access permissions. |
| 32 |
* |
| 33 |
* @package s2Member\Files |
| 34 |
* @since 3.5 |
| 35 |
* |
| 36 |
* @attaches-to: ``add_action("init");`` |
| 37 |
* @also-called-by: API Function {@link s2Member\API_Functions\s2member_file_download_url()}, w/ ``$create_file_download_url`` param. |
| 38 |
* |
| 39 |
* @param array $create_file_download_url Optional. If this function is called directly, we can pass arguments through this array. |
| 40 |
* Possible array elements: `file_download` *(required)*, `file_download_key`, `file_stream`, `file_inline`, `file_storage`, `file_remote`, `file_ssl`, `file_rewrite`, `file_rewrite_base`, `skip_confirmation`, `url_to_storage_source`, `count_against_user`, `check_user`. |
| 41 |
* @return null|str If called directly with ``$create_file_download_url``, returns a string with the URL, based on configuration. |
| 42 |
* Else, this function may exit script execution after serving a File Download. |
| 43 |
*/ |
| 44 |
public static function check_file_download_access ($create_file_download_url = FALSE) |
| 45 |
{ |
| 46 |
eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;'); |
| 47 |
do_action ("ws_plugin__s2member_before_file_download_access", get_defined_vars ()); |
| 48 |
unset ($__refs, $__v); /* Unset defined __refs, __v. */ |
| 49 |
/**/ |
| 50 |
$_g = !empty ($_GET) ? $_GET : array (); |
| 51 |
$_g = c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep ($_g)); |
| 52 |
/**/ |
| 53 |
$creating = (is_array ($create = $create_file_download_url)) ? true : false; /* Creating URL? */ |
| 54 |
$serving = (!$creating) ? true : false; /* If NOT creating a File Download URL, we're serving one. */ |
| 55 |
/**/ |
| 56 |
$req["file_download"] = ($creating) ? @$create["file_download"] : @$_g["s2member_file_download"]; |
| 57 |
$req["file_download_key"] = ($creating) ? @$create["file_download_key"] : @$_g["s2member_file_download_key"]; |
| 58 |
/**/ |
| 59 |
$req["file_stream"] = ($creating) ? @$create["file_stream"] : @$_g["s2member_file_stream"]; |
| 60 |
$req["file_inline"] = ($creating) ? @$create["file_inline"] : @$_g["s2member_file_inline"]; |
| 61 |
$req["file_storage"] = ($creating) ? @$create["file_storage"] : @$_g["s2member_file_storage"]; |
| 62 |
$req["file_remote"] = ($creating) ? @$create["file_remote"] : @$_g["s2member_file_remote"]; |
| 63 |
$req["file_ssl"] = ($creating) ? @$create["file_ssl"] : @$_g["s2member_file_ssl"]; |
| 64 |
/**/ |
| 65 |
$req["file_rewrite"] = ($creating) ? @$create["file_rewrite"] : /* N/A. */ null; |
| 66 |
$req["file_rewrite_base"] = ($creating) ? @$create["file_rewrite_base"] : /* N/A. */ null; |
| 67 |
/**/ |
| 68 |
$req["skip_confirmation"] = ($creating) ? @$create["skip_confirmation"] : /* N/A. */ null; |
| 69 |
$req["url_to_storage_source"] = ($creating) ? @$create["url_to_storage_source"] : /* N/A. */ null; |
| 70 |
$req["count_against_user"] = ($creating) ? @$create["count_against_user"] : /* N/A. */ null; |
| 71 |
$req["check_user"] = ($creating) ? @$create["check_user"] : /* N/A. */ null; |
| 72 |
/**/ |
| 73 |
if ($req["file_download"] && is_string ($req["file_download"]) && ($req["file_download"] = trim ($req["file_download"], "/"))) |
| 74 |
if (strpos ($req["file_download"], "..") === false && strpos (basename ($req["file_download"]), ".") !== 0) |
| 75 |
{ |
| 76 |
$using_amazon_s3_storage = ((!$req["file_storage"] || strcasecmp ((string)$req["file_storage"], "s3") === 0) && c_ws_plugin__s2member_utils_conds::using_amazon_s3_storage ()) ? true : false; |
| 77 |
$using_amazon_cf_storage = ((!$req["file_storage"] || strcasecmp ((string)$req["file_storage"], "cf") === 0) && c_ws_plugin__s2member_utils_conds::using_amazon_cf_storage ()) ? true : false; |
| 78 |
$using_amazon_storage = ($using_amazon_s3_storage || $using_amazon_cf_storage) ? true : false; /* Either/or? */ |
| 79 |
/**/ |
| 80 |
$excluded = apply_filters ("ws_plugin__s2member_check_file_download_access_excluded", false, get_defined_vars ()); |
| 81 |
$valid_file_download_key = ($req["file_download_key"] && is_string ($req["file_download_key"])) ? c_ws_plugin__s2member_files_in::check_file_download_key ($req["file_download"], $req["file_download_key"]) : false; |
| 82 |
$checking_user = ($excluded || $valid_file_download_key || ($creating && (!isset ($req["check_user"]) || !filter_var ($req["check_user"], FILTER_VALIDATE_BOOLEAN)) && (!isset ($req["count_against_user"]) || !filter_var ($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true; |
| 83 |
$updating_user_counter = (!$checking_user || ($creating && (!isset ($req["count_against_user"]) || !filter_var ($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true; |
| 84 |
/**/ |
| 85 |
if (($serving || $creating) && $checking_user) /* In either case, the following routines apply whenever we ARE ``$checking_user``. */ |
| 86 |
{ |
| 87 |
if (!$using_amazon_storage && !file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $req["file_download"])) |
| 88 |
{ |
| 89 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 90 |
status_header(404) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') # |
| 91 |
. exit (_x ('<strong>404: Sorry, file not found.</strong> Please contact Support for assistance.', "s2member-front", "s2member")); |
| 92 |
/**/ |
| 93 |
else /* Else return false. */ |
| 94 |
return false; |
| 95 |
} |
| 96 |
/**/ |
| 97 |
else if ($req["file_download_key"] && is_string ($req["file_download_key"]) && !$valid_file_download_key) |
| 98 |
{ |
| 99 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 100 |
status_header(503) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') # |
| 101 |
. exit (_x ('<strong>503 ( Invalid Key ):</strong> Sorry, your access to this file has expired. Please contact Support for assistance.', "s2member-front", "s2member")); |
| 102 |
/**/ |
| 103 |
else /* Else return false. */ |
| 104 |
return false; |
| 105 |
} |
| 106 |
/**/ |
| 107 |
else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] || ($file_downloads_enabled_by_site_owner = $min_level_4_downloads = c_ws_plugin__s2member_files::min_level_4_downloads ()) === false) |
| 108 |
{ |
| 109 |
if ($serving) /* We only need remote functionality when/if we're actually serving. */ |
| 110 |
if (!has_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization")) |
| 111 |
add_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization", 10, 2); |
| 112 |
/**/ |
| 113 |
if ($creating) /* We only need remote functionality when/if we're actually serving. */ |
| 114 |
if (has_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization")) |
| 115 |
remove_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization", 10, 2); |
| 116 |
/**/ |
| 117 |
if ((isset ($file_downloads_enabled_by_site_owner, $min_level_4_downloads) && $file_downloads_enabled_by_site_owner === false) || ($file_downloads_enabled_by_site_owner = $min_level_4_downloads = c_ws_plugin__s2member_files::min_level_4_downloads ()) === false) |
| 118 |
{ |
| 119 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 120 |
status_header(503) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') # |
| 121 |
. exit (_x ('<strong>503: Basic File Downloads are NOT enabled yet.</strong> Please contact Support for assistance. If you are the site owner, please configure: <code>s2Member -> Download Options -> Basic Download Restrictions</code>.', "s2member-front", "s2member")); |
| 122 |
/**/ |
| 123 |
else /* Else return false. */ |
| 124 |
return false; |
| 125 |
} |
| 126 |
/**/ |
| 127 |
else if (!is_object ($user = apply_filters ("ws_plugin__s2member_check_file_download_access_user", ((is_user_logged_in ()) ? wp_get_current_user () : false), get_defined_vars ())) || empty ($user->ID) || !($user_id = $user->ID) || !is_array ($user_file_downloads = c_ws_plugin__s2member_files::user_downloads ($user)) || (!$user->has_cap ("administrator") && (!$user_file_downloads["allowed"] || !$user_file_downloads["allowed_days"]))) |
| 128 |
{ |
| 129 |
if (preg_match ("/^access[_\-]s2member[_\-]level([0-9]+)\//", $req["file_download"], $m) && strlen ($level_req = $m[1]) && (!is_object ($user) || empty ($user->ID) || !$user->has_cap ("access_s2member_level" . $level_req))) |
| 130 |
{ |
| 131 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 132 |
wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $req["file_download"], "s2member_level_req" => $level_req)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit (); |
| 133 |
/**/ |
| 134 |
else /* Else return false. */ |
| 135 |
return false; |
| 136 |
} |
| 137 |
/**/ |
| 138 |
else if (preg_match ("/^access[_\-]s2member[_\-]ccap[_\-](.+?)\//", $req["file_download"], $m) && strlen ($ccap_req = preg_replace ("/-/", "_", $m[1])) && (!is_object ($user) || empty ($user->ID) || !$user->has_cap ("access_s2member_ccap_" . $ccap_req))) |
| 139 |
{ |
| 140 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 141 |
wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $req["file_download"], "s2member_ccap_req" => $ccap_req)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit (); |
| 142 |
/**/ |
| 143 |
else /* Else return false. */ |
| 144 |
return false; |
| 145 |
} |
| 146 |
/**/ |
| 147 |
else if ($serving) /* We only need this section when/if we're actually serving. */ |
| 148 |
wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $req["file_download"], "s2member_level_req" => (string)$min_level_4_downloads)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit (); |
| 149 |
/**/ |
| 150 |
else /* Else return false. */ |
| 151 |
return false; |
| 152 |
} |
| 153 |
/**/ |
| 154 |
else if (preg_match ("/^access[_\-]s2member[_\-]level([0-9]+)\//", $req["file_download"], $m) && strlen ($level_req = $m[1]) && !$user->has_cap ("access_s2member_level" . $level_req)) |
| 155 |
{ |
| 156 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 157 |
wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $req["file_download"], "s2member_level_req" => $level_req)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit (); |
| 158 |
/**/ |
| 159 |
else /* Else return false. */ |
| 160 |
return false; |
| 161 |
} |
| 162 |
/**/ |
| 163 |
else if (preg_match ("/^access[_\-]s2member[_\-]ccap[_\-](.+?)\//", $req["file_download"], $m) && strlen ($ccap_req = preg_replace ("/-/", "_", $m[1])) && !$user->has_cap ("access_s2member_ccap_" . $ccap_req)) |
| 164 |
{ |
| 165 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 166 |
wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $req["file_download"], "s2member_ccap_req" => $ccap_req)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit (); |
| 167 |
/**/ |
| 168 |
else /* Else return false. */ |
| 169 |
return false; |
| 170 |
} |
| 171 |
/**/ |
| 172 |
else if ($serving || $creating) /* In either case, the following routines apply. */ |
| 173 |
{ |
| 174 |
$user_previous_file_downloads = 0; /* Downloads the User has already; in current period/cycle. */ |
| 175 |
$user_already_downloaded_this_file = $user_already_downloaded_a_streaming_variation_of_this_file = false; |
| 176 |
/**/ |
| 177 |
$user_file_download_access_log = (array)get_user_option ("s2member_file_download_access_log", $user_id); |
| 178 |
$user_file_download_access_arc = (array)get_user_option ("s2member_file_download_access_arc", $user_id); |
| 179 |
/**/ |
| 180 |
$streaming_file_extns = c_ws_plugin__s2member_utils_strings::preg_quote_deep ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"], "/"); |
| 181 |
$streaming_variations = /* Only count one streaming media file variation. */ "/\.(" . implode ("|", $streaming_file_extns) . ")$/i"; |
| 182 |
/**/ |
| 183 |
$max_download_period_days = c_ws_plugin__s2member_files::max_download_period (); /* Max download period; counted in days. */ |
| 184 |
/**/ |
| 185 |
foreach ($user_file_download_access_log as $user_file_download_access_log_entry_key => $user_file_download_access_log_entry) |
| 186 |
{ |
| 187 |
if (strtotime ($user_file_download_access_log_entry["date"]) < strtotime ("-" . $max_download_period_days . " days")) |
| 188 |
{ |
| 189 |
unset($user_file_download_access_log[$user_file_download_access_log_entry_key]); |
| 190 |
$user_file_download_access_arc[] = $user_file_download_access_log_entry; |
| 191 |
} |
| 192 |
else if (strtotime ($user_file_download_access_log_entry["date"]) >= strtotime ("-" . $user_file_downloads["allowed_days"] . " days")) |
| 193 |
{ |
| 194 |
$user_previous_file_downloads++; /* A previous file that counts against this User/Member, since it's already in the log. */ |
| 195 |
/**/ |
| 196 |
if ($user_file_download_access_log_entry["file"] === $req["file_download"]) /* Already downloaded this file before? */ |
| 197 |
$user_already_downloaded_this_file = true; /* Already downloaded this file? If yes, mark this flag as true. */ |
| 198 |
/**/ |
| 199 |
else if (preg_replace ($streaming_variations, "", $user_file_download_access_log_entry["file"]) === preg_replace ($streaming_variations, "", $req["file_download"])) |
| 200 |
$user_already_downloaded_this_file = $user_already_downloaded_a_streaming_variation_of_this_file = true; |
| 201 |
} |
| 202 |
} |
| 203 |
/**/ |
| 204 |
if (!$user_already_downloaded_this_file && !$user_already_downloaded_a_streaming_variation_of_this_file && !$user->has_cap ("administrator") && $user_previous_file_downloads >= $user_file_downloads["allowed"]) |
| 205 |
{ |
| 206 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 207 |
wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $req["file_download"])), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit (); |
| 208 |
/**/ |
| 209 |
else /* Else return false. */ |
| 210 |
return false; |
| 211 |
} |
| 212 |
/**/ |
| 213 |
else if (!$user_already_downloaded_this_file && !$user_already_downloaded_a_streaming_variation_of_this_file) |
| 214 |
$user_file_download_access_log[] = array ("date" => date ("Y-m-d"), "file" => $req["file_download"]); |
| 215 |
/**/ |
| 216 |
if ($updating_user_counter) /* By default, we do NOT update the counter when a URL is being created; but this behavior can be modified. */ |
| 217 |
{ |
| 218 |
update_user_option ($user_id, "s2member_file_download_access_arc", c_ws_plugin__s2member_utils_arrays::array_unique ($user_file_download_access_arc)); |
| 219 |
update_user_option ($user_id, "s2member_file_download_access_log", c_ws_plugin__s2member_utils_arrays::array_unique ($user_file_download_access_log)); |
| 220 |
} |
| 221 |
} |
| 222 |
} |
| 223 |
} |
| 224 |
else /* Otherwise, we're either NOT ``$checking_user``; or permission was granted with a valid File Download Key. */ |
| 225 |
{ |
| 226 |
if (!$using_amazon_storage && !file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $req["file_download"])) |
| 227 |
{ |
| 228 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 229 |
status_header(404) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') # |
| 230 |
. exit (_x ('<strong>404: Sorry, file not found.</strong> Please contact Support for assistance.', "s2member-front", "s2member")); |
| 231 |
/**/ |
| 232 |
else /* Else return false. */ |
| 233 |
return false; |
| 234 |
} |
| 235 |
} |
| 236 |
/**/ |
| 237 |
if ($serving || $creating) /* In either case, the following routines apply. */ |
| 238 |
{ |
| 239 |
$basename = basename ($req["file_download"]); |
| 240 |
$mimetypes = parse_ini_file (dirname (dirname (dirname (__FILE__))) . "/includes/mime-types.ini"); |
| 241 |
$extension = strtolower (substr ($req["file_download"], strrpos ($req["file_download"], ".") + 1)); |
| 242 |
/**/ |
| 243 |
$key = ($req["file_download_key"] && is_string ($req["file_download_key"])) ? $req["file_download_key"] : false; |
| 244 |
/**/ |
| 245 |
$stream = (isset ($req["file_stream"])) ? filter_var ($req["file_stream"], FILTER_VALIDATE_BOOLEAN) : ((in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_stream_extensions"]))) ? true : false); |
| 246 |
$inline = (!$stream && isset ($req["file_inline"])) ? filter_var ($req["file_inline"], FILTER_VALIDATE_BOOLEAN) : (($stream || in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]))) ? true : false); |
| 247 |
$ssl = (isset ($req["file_ssl"])) ? filter_var ($req["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl ()) ? true : false); |
| 248 |
$storage = ($req["file_storage"] && is_string ($req["file_storage"])) ? strtolower ($req["file_storage"]) : false; |
| 249 |
$remote = (isset ($req["file_remote"])) ? filter_var ($req["file_remote"], FILTER_VALIDATE_BOOLEAN) : false; |
| 250 |
/**/ |
| 251 |
$rewrite_base_guess = dirname ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . "/" . c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]); |
| 252 |
$rewrite_base = ($req["file_rewrite_base"] && is_string ($req["file_rewrite_base"])) ? $req["file_rewrite_base"] : false; |
| 253 |
$rewrite = $rewriting = (!$rewrite_base && isset ($req["file_rewrite"])) ? filter_var ($req["file_rewrite"], FILTER_VALIDATE_BOOLEAN) : (($rewrite_base) ? true : false); |
| 254 |
/**/ |
| 255 |
$skip_confirmation = (isset ($req["skip_confirmation"])) ? filter_var ($req["skip_confirmation"], FILTER_VALIDATE_BOOLEAN) : false; |
| 256 |
$url_to_storage_source = (isset ($req["url_to_storage_source"])) ? filter_var ($req["url_to_storage_source"], FILTER_VALIDATE_BOOLEAN) : false; |
| 257 |
/**/ |
| 258 |
$pathinfo = (!$using_amazon_storage) ? pathinfo (($file = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $req["file_download"])) : array (); |
| 259 |
$mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream"; |
| 260 |
$length = (!$using_amazon_storage && $file) ? filesize ($file) : -1; |
| 261 |
/**/ |
| 262 |
eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;'); |
| 263 |
do_action ("ws_plugin__s2member_during_file_download_access", get_defined_vars ()); |
| 264 |
unset ($__refs, $__v); /* Unset defined __refs, __v. */ |
| 265 |
/**/ |
| 266 |
if ($using_amazon_s3_storage && ($serving || ($creating && $url_to_storage_source))) |
| 267 |
{ |
| 268 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 269 |
wp_redirect(c_ws_plugin__s2member_files_in::amazon_s3_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype)) . exit (); |
| 270 |
/**/ |
| 271 |
else /* Else return File Download URL. */ |
| 272 |
return apply_filters ("ws_plugin__s2member_file_download_access_url", c_ws_plugin__s2member_files_in::amazon_s3_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype), get_defined_vars ()); |
| 273 |
} |
| 274 |
/**/ |
| 275 |
else if ($using_amazon_cf_storage && ($serving || ($creating && $url_to_storage_source))) |
| 276 |
{ |
| 277 |
if ($serving) /* We only need this section when/if we're actually serving. */ |
| 278 |
wp_redirect(c_ws_plugin__s2member_files_in::amazon_cf_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype)) . exit (); |
| 279 |
/**/ |
| 280 |
else /* Else return File Download URL. */ |
| 281 |
return apply_filters ("ws_plugin__s2member_file_download_access_url", c_ws_plugin__s2member_files_in::amazon_cf_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype), get_defined_vars ()); |
| 282 |
} |
| 283 |
/**/ |
| 284 |
else if ($creating && $rewriting) /* Creating a rewrite URL, pointing to local storage. */ |
| 285 |
{ |
| 286 |
$url = ($rewrite_base) ? rtrim ($rewrite_base, "/") : rtrim ($rewrite_base_guess, "/"); |
| 287 |
$url .= (isset ($req["file_download_key"])) ? (($key) ? "/s2member-file-download-key-" . $key : "") : ""; |
| 288 |
$url .= (isset ($req["file_stream"])) ? (($stream) ? "/s2member-file-stream" : "/s2member-file-stream-no") : ""; |
| 289 |
$url .= (isset ($req["file_inline"])) ? (($inline) ? "/s2member-file-inline" : "/s2member-file-inline-no") : ""; |
| 290 |
$url .= (isset ($req["file_storage"])) ? (($storage) ? "/s2member-file-storage-" . $storage : "") : ""; |
| 291 |
$url .= (isset ($req["file_remote"])) ? (($remote) ? "/s2member-file-remote" : "/s2member-file-remote-no") : ""; |
| 292 |
$url .= (isset ($req["skip_confirmation"])) ? (($skip_confirmation) ? "/s2member-skip-confirmation" : "/s2member-skip-confirmation-no") : ""; |
| 293 |
/**/ |
| 294 |
$url = $url . "/" . $req["file_download"]; /* File Download Access URL via `mod_rewrite` functionality. */ |
| 295 |
$url = ($ssl) ? preg_replace ("/^https?/", "https", $url) : preg_replace ("/^https?/", "http", $url); |
| 296 |
/**/ |
| 297 |
return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ()); |
| 298 |
} |
| 299 |
/**/ |
| 300 |
else if ($creating) /* Else we're creating a URL w/ a query-string; w/ local storage. */ |
| 301 |
{ |
| 302 |
/* * Note: we don't URL encode unreserved chars. Improves media player compatibility. */ |
| 303 |
$_url_e_key = ($key) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($key)) : ""; |
| 304 |
$_url_e_storage = ($storage) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($storage)) : ""; |
| 305 |
$_url_e_file = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($req["file_download"])); |
| 306 |
/**/ |
| 307 |
$url = (isset ($req["file_download_key"])) ? (($key && $_url_e_key) ? "&s2member_file_download_key=" . $_url_e_key : "") : ""; |
| 308 |
$url .= (isset ($req["file_stream"])) ? (($stream) ? "&s2member_file_stream=yes" : "&s2member_file_stream=no") : ""; |
| 309 |
$url .= (isset ($req["file_inline"])) ? (($inline) ? "&s2member_file_inline=yes" : "&s2member_file_inline=no") : ""; |
| 310 |
$url .= (isset ($req["file_storage"])) ? (($storage && $_url_e_storage) ? "&s2member_file_storage=" . $_url_e_storage : "") : ""; |
| 311 |
$url .= (isset ($req["file_remote"])) ? (($remote) ? "&s2member_file_remote=yes" : "&s2member_file_remote=no") : ""; |
| 312 |
$url .= (isset ($req["skip_confirmation"])) ? (($skip_confirmation) ? "&s2member_skip_confirmation=yes" : "&s2member_skip_confirmation=no") : ""; |
| 313 |
/**/ |
| 314 |
$url = site_url ("/?" . ltrim ($url . "&s2member_file_download=/" . $_url_e_file, "&")); |
| 315 |
$url = ($ssl) ? preg_replace ("/^https?/", "https", $url) : preg_replace ("/^https?/", "http", $url); |
| 316 |
/**/ |
| 317 |
return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ()); |
| 318 |
} |
| 319 |
/**/ |
| 320 |
else /* Else, ``if ($serving)`` , use local storage option (default). */ |
| 321 |
{ |
| 322 |
@set_time_limit(0) . @ini_set ("zlib.output_compression", 0); |
| 323 |
/**/ |
| 324 |
status_header(200); /* 200 OK status header. */ |
| 325 |
/**/ |
| 326 |
header("Accept-Ranges: none"); |
| 327 |
header("Content-Encoding: none"); |
| 328 |
header("Content-Type: " . $mimetype); |
| 329 |
header("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT"); |
| 330 |
header("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT"); |
| 331 |
header("Cache-Control: no-cache, must-revalidate, max-age=0"); |
| 332 |
header ("Cache-Control: post-check=0, pre-check=0", false); |
| 333 |
header("Pragma: no-cache"); |
| 334 |
/**/ |
| 335 |
header('Content-Disposition: ' . (($inline) ? "inline" : "attachment") . '; filename="' . $basename . '"'); |
| 336 |
/**/ |
| 337 |
eval('while (@ob_end_clean ());'); /* End/clean any output buffers that may exist already. */ |
| 338 |
/**/ |
| 339 |
if ($length && apply_filters ("ws_plugin__s2member_chunk_file_downloads", true, get_defined_vars ()) && is_resource ($resource = fopen ($file, "rb"))) |
| 340 |
{ |
| 341 |
$_chunk_size = apply_filters ("ws_plugin__s2member_chunk_file_downloads_w_chunk_size", 2097152, get_defined_vars ()); |
| 342 |
$_chunk_w_content_length = (stripos (PHP_OS, "win") === 0 && (!function_exists ("apache_get_version") || apache_get_version () === false)) ? false : true; |
| 343 |
/**/ |
| 344 |
/* Windows® IIS doesn't seem to like it when both `Content-Length` and `Transfer-Encoding: chunked` are sent together. */ |
| 345 |
if (apply_filters ("ws_plugin__s2member_chunk_file_downloads_w_content_length", $_chunk_w_content_length, get_defined_vars ())) |
| 346 |
header("Content-Length: " . $length); |
| 347 |
/**/ |
| 348 |
header("Transfer-Encoding: chunked"); /* Uses `Transfer-Encoding: chunked` for simulated streaming. */ |
| 349 |
/**/ |
| 350 |
while (!feof ($resource) && ($chunk_size = strlen ($data = fread ($resource, $_chunk_size)))) |
| 351 |
eval('echo dechex ($chunk_size) . "\r\n". $data . "\r\n"; @flush ();'); |
| 352 |
/**/ |
| 353 |
fclose($resource) . exit ("0\r\n\r\n"); |
| 354 |
} |
| 355 |
else if ($length) /* Else, use: ``file_get_contents()``. */ |
| 356 |
{ |
| 357 |
header("Content-Length: " . $length) . exit (file_get_contents ($file)); |
| 358 |
} |
| 359 |
else /* Else, we have an empty file with no length. */ |
| 360 |
{ |
| 361 |
header("Content-Length: 0") . exit (); |
| 362 |
} |
| 363 |
} |
| 364 |
} |
| 365 |
} |
| 366 |
/**/ |
| 367 |
else if ($serving && $req["file_download"]) /* We only need this section when/if we're actually serving. */ |
| 368 |
status_header(503) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') # |
| 369 |
. exit (_x ('<strong>503: Access denied.</strong> Invalid File Download specs.', "s2member-front", "s2member")); |
| 370 |
/**/ |
| 371 |
else if ($creating) /* We only need this section when/if we're creating a URL. */ |
| 372 |
return false; |
| 373 |
/**/ |
| 374 |
do_action ("ws_plugin__s2member_after_file_download_access", get_defined_vars ()); |
| 375 |
/**/ |
| 376 |
return ($creating) ? false : null; /* If creating, false. */ |
| 377 |
} |
| 378 |
/** |
| 379 |
* Generates a File Download URL for access to a file protected by s2Member. |
| 380 |
* |
| 381 |
* @package s2Member\Files |
| 382 |
* @since 110926 |
| 383 |
* |
| 384 |
* @param array $config Required. This is an array of configuration options associated with permissions being checked against the current User/Member; and also the actual URL generated by this routine. |
| 385 |
* Possible ``$config`` array elements: `file_download` *(required)*, `file_download_key`, `file_stream`, `file_inline`, `file_storage`, `file_remote`, `file_ssl`, `file_rewrite`, `file_rewrite_base`, `skip_confirmation`, `url_to_storage_source`, `count_against_user`, `check_user`. |
| 386 |
* @param bool $get_streamer_array Optional. Defaults to `false`. If `true`, this function will return an array with the following elements: `streamer`, `file`, `url`. For further details, please review this section in your Dashboard: `s2Member -> Download Options -> JW Player® & RTMP Protocol Examples`. |
| 387 |
* @return str A File Download URL string on success; or an array on success, with elements `streamer`, `file`, `url` when/if ``$get_streamer_array`` is true; else false on any type of failure. |
| 388 |
* |
| 389 |
* @see s2Member\API_Functions\s2member_file_download_url() |
| 390 |
*/ |
| 391 |
public static function create_file_download_url ($config = FALSE, $get_streamer_array = FALSE) |
| 392 |
{ |
| 393 |
eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;'); |
| 394 |
do_action ("ws_plugin__s2member_before_create_file_download_url", get_defined_vars ()); /* Be VERY careful, if you use this Hook. */ |
| 395 |
unset ($__refs, $__v); /* Unset defined __refs, __v. */ |
| 396 |
/**/ |
| 397 |
$config = (is_array ($config)) ? $config : array (); /* This absolutely MUST be an array. */ |
| 398 |
/**/ |
| 399 |
$config["file_download"] = (isset ($config["file_download"]) && is_string ($config["file_download"])) ? trim ($config["file_download"], "/") : @$config["file_download"]; |
| 400 |
$config["file_download_key"] = (isset ($config["file_download"]) && is_string ($config["file_download"]) && !empty ($config["file_download_key"])) ? c_ws_plugin__s2member_files::file_download_key ($config["file_download"], ((in_array ($config["file_download_key"], array ("ip-forever", "universal", "cache-compatible"))) ? $config["file_download_key"] : false)) : @$config["file_download_key"]; |
| 401 |
/**/ |
| 402 |
$config["url_to_storage_source"] = /* Force a streaming URL here via ``$get_streamer_array``? */ ($get_streamer_array) ? true : @$config["url_to_storage_source"]; |
| 403 |
$config["file_stream"] = /* Force a streaming URL here via ``$get_streamer_array``? */ ($get_streamer_array) ? true : @$config["file_stream"]; |
| 404 |
/**/ |
| 405 |
if (($_url = c_ws_plugin__s2member_files_in::check_file_download_access (($create_file_download_url = $config))) /* Successfully created a URL to the file? */) |
| 406 |
{ |
| 407 |
eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;'); |
| 408 |
do_action ("ws_plugin__s2member_during_create_file_download_url", get_defined_vars ()); /* Be VERY careful, if you use this Hook. */ |
| 409 |
unset ($__refs, $__v); /* Unset defined __refs, __v. */ |
| 410 |
/**/ |
| 411 |
$extension = strtolower (substr ($config["file_download"], strrpos ($config["file_download"], ".") + 1)); |
| 412 |
$streaming = (isset ($config["file_stream"])) ? filter_var ($config["file_stream"], FILTER_VALIDATE_BOOLEAN) : ((in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_stream_extensions"]))) ? true : false); |
| 413 |
$ssl = (isset ($config["file_ssl"])) ? filter_var ($config["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl ()) ? true : false); |
| 414 |
/**/ |
| 415 |
if ($get_streamer_array && $streaming && ($cfx = "/cfx/st") && ($cfx_pos = strpos ($_url, $cfx)) !== false && ($streamer = substr ($_url, 0, $cfx_pos + strlen ($cfx))) && ($url = c_ws_plugin__s2member_files_in::check_file_download_access (array_merge ($config, array ("file_stream" => false, "check_user" => false))))) |
| 416 |
$return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url)); |
| 417 |
/**/ |
| 418 |
else if ($get_streamer_array && $streaming && is_array ($ups = c_ws_plugin__s2member_utils_urls::parse_url ($_url)) && isset ($ups["scheme"], $ups["host"]) && ($streamer = $ups["scheme"] . "://" . $ups["host"] . ((!empty ($ups["port"])) ? ":" . $ups["port"] : "")) && ($url = c_ws_plugin__s2member_files_in::check_file_download_access (array_merge ($config, array ("file_stream" => false, "check_user" => false))))) |
| 419 |
$return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url)); |
| 420 |
/**/ |
| 421 |
else if ($get_streamer_array) /* Else, we MUST return false here, unable to acquire streamer/file. */ |
| 422 |
$return = false; /* We MUST return false here, unable to acquire streamer. */ |
| 423 |
/**/ |
| 424 |
else /* Else return URL string ( ``$get_streamer_array`` is false ). */ |
| 425 |
$return = $_url; /* Else return URL string. */ |
| 426 |
} |
| 427 |
/**/ |
| 428 |
return apply_filters ("ws_plugin__s2member_create_file_download_url", ((isset ($return)) ? $return : false), get_defined_vars ()); |
| 429 |
} |
| 430 |
/** |
| 431 |
* Checks Header Authorization for Remote File Downloads. |
| 432 |
* |
| 433 |
* @package s2Member\Files |
| 434 |
* @since 110926 |
| 435 |
* |
| 436 |
* @attaches-to: ``add_filter("ws_plugin__s2member_check_file_download_access_user");`` |
| 437 |
* |
| 438 |
* @param obj $user Expects a WP_User object passed in by the Filter. |
| 439 |
* @return obj A `WP_User` object, possibly obtained through Header Authorization. |
| 440 |
*/ |
| 441 |
public static function check_file_remote_authorization ($user = FALSE) |
| 442 |
{ |
| 443 |
eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;'); |
| 444 |
do_action ("ws_plugin__s2member_before_check_file_remote_authorization", get_defined_vars ()); |
| 445 |
unset ($__refs, $__v); /* Unset defined __refs, __v. */ |
| 446 |
/**/ |
| 447 |
$_g = c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep (((!empty ($_GET)) ? $_GET : array ()))); |
| 448 |
/**/ |
| 449 |
if (!is_object ($user) && isset ($_g["s2member_file_remote"]) && filter_var ($_g["s2member_file_remote"], FILTER_VALIDATE_BOOLEAN)) |
| 450 |
{ |
| 451 |
do_action ("ws_plugin__s2member_during_check_file_remote_authorization_before", get_defined_vars ()); |
| 452 |
/**/ |
| 453 |
if (empty ($_SERVER["PHP_AUTH_USER"]) || empty ($_SERVER["PHP_AUTH_PW"]) || !user_pass_ok ($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])) |
| 454 |
{ |
| 455 |
header('WWW-Authenticate: Basic realm="' . c_ws_plugin__s2member_utils_strings::esc_dq (strip_tags (_x ("Members Only", "s2member-front", "s2member"))) . '"'); |
| 456 |
/**/ |
| 457 |
status_header(401); /* Send an unauthorized 401 status header now. */ |
| 458 |
header("Content-Type: text/html; charset=utf-8"); /* Content-Type with UTF-8. */ |
| 459 |
eval('while (@ob_end_clean ());'); /* End/clean any output buffers that may exist. */ |
| 460 |
/**/ |
| 461 |
exit(_x ('<strong>401:</strong> Sorry, access denied.', "s2member-front", "s2member")); |
| 462 |
} |
| 463 |
else if (is_object ($_user = new WP_User ($_SERVER["PHP_AUTH_USER"])) && !empty ($_user->ID)) |
| 464 |
$user = $_user; /* Now assign ``$user``. */ |
| 465 |
/**/ |
| 466 |
do_action ("ws_plugin__s2member_during_check_file_remote_authorization_after", get_defined_vars ()); |
| 467 |
} |
| 468 |
/**/ |
| 469 |
return apply_filters ("ws_plugin__s2member_check_file_remote_authorization", $user, get_defined_vars ()); |
| 470 |
} |
| 471 |
/** |
| 472 |
* Checks a File Download Key for validity. |
| 473 |
* |
| 474 |
* @package s2Member\Files |
| 475 |
* @since 110926 |
| 476 |
* |
| 477 |
* @param str $file Input File Download to validate. |
| 478 |
* @param str $key Input File Download Key to validate. |
| 479 |
* @return bool True if valid, else false. |
| 480 |
*/ |
| 481 |
public static function check_file_download_key ($file = FALSE, $key = FALSE) |
| 482 |
{ |
| 483 |
eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;'); |
| 484 |
do_action ("_ws_plugin__s2member_before_check_file_download_key", get_defined_vars ()); |
| 485 |
unset ($__refs, $__v); /* Unset defined __refs, __v. */ |
| 486 |
/**/ |
| 487 |
if ($file && is_string ($file) && ($file = trim ($file, "/")) && $key && is_string ($key)) /* Requirements to properly validate. */ |
| 488 |
{ |
| 489 |
if ($key === c_ws_plugin__s2member_files::file_download_key ($file) || $key === c_ws_plugin__s2member_files::file_download_key ("/" . $file)) |
| 490 |
$valid = true; /* File Download Key is valid. */ |
| 491 |
else if ($key === c_ws_plugin__s2member_files::file_download_key ($file, "ip-forever") || $key === c_ws_plugin__s2member_files::file_download_key ("/" . $file, "ip-forever")) |
| 492 |
$valid = true; /* File Download Key is valid. */ |
| 493 |
else if ($key === c_ws_plugin__s2member_files::file_download_key ($file, "universal") || $key === c_ws_plugin__s2member_files::file_download_key ("/" . $file, "universal")) |
| 494 |
$valid = true; /* File Download Key is valid. */ |
| 495 |
} |
| 496 |
/**/ |
| 497 |
return apply_filters ("ws_plugin__s2member_check_file_download_key", ((isset ($valid) && $valid) ? true : false), get_defined_vars ()); |
| 498 |
} |
| 499 |
/** |
| 500 |
* Creates an Amazon® S3 HMAC-SHA1 signature. |
| 501 |
* |
| 502 |
* @package s2Member\Files |
| 503 |
* @since 110524RC |
| 504 |
* |
| 505 |
* @param str $string Input string/data, to be signed by this routine. |
| 506 |
* @return str An HMAC-SHA1 signature for Amazon® S3. |
| 507 |
*/ |
| 508 |
public static function amazon_s3_sign ($string = FALSE) |
| 509 |
{ |
| 510 |
$s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 511 |
/**/ |
| 512 |
return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign ((string)$string, $s3c["secret_key"]); |
| 513 |
} |
| 514 |
/** |
| 515 |
* Creates an Amazon® S3 HMAC-SHA1 signature URL. |
| 516 |
* |
| 517 |
* @package s2Member\Files |
| 518 |
* @since 110926 |
| 519 |
* |
| 520 |
* @param str $file Input file path, to be signed by this routine. |
| 521 |
* @param bool $stream Is this resource file to be served as streaming media? |
| 522 |
* @param bool $inline Is this resource file to be served inline, or no? |
| 523 |
* @param bool $ssl Is this resource file to be served via SSL, or no? |
| 524 |
* @param str $basename The absolute basename of the resource file. |
| 525 |
* @param str $mimetype The MIME content-type of the resource file. |
| 526 |
* @return str An HMAC-SHA1 signature URL for Amazon® S3. |
| 527 |
*/ |
| 528 |
public static function amazon_s3_url ($file = FALSE, $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = FALSE, $mimetype = FALSE) |
| 529 |
{ |
| 530 |
$file = trim ((string)$file, "/"); /* Trim / force string. */ |
| 531 |
/**/ |
| 532 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 533 |
if (preg_match ("/^amazon_s3_files_/", $option) && ($option = preg_replace ("/^amazon_s3_files_/", "", $option))) |
| 534 |
$s3c[$option] = $option_value; |
| 535 |
/**/ |
| 536 |
$s3c["expires"] = strtotime ("+" . apply_filters ("ws_plugin__s2member_amazon_s3_file_expires_time", "30 seconds", get_defined_vars ())); |
| 537 |
/**/ |
| 538 |
$s3_file = add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode_deep (array ("response-cache-control" => ($s3_cache_control = "no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"), "response-content-disposition" => ($s3_content_disposition = (((bool)$inline) ? "inline" : "attachment") . '; filename="' . (string)$basename . '"'), "response-content-type" => ($s3_content_type = (string)$mimetype), "response-expires" => ($s3_expires = gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT")))), "/" . $file); |
| 539 |
$s3_raw_file = add_query_arg (array ("response-cache-control" => $s3_cache_control, "response-content-disposition" => $s3_content_disposition, "response-content-type" => $s3_content_type, "response-expires" => $s3_expires), "/" . $file); |
| 540 |
$s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("GET\n\n\n" . $s3c["expires"] . "\n" . "/" . $s3c["bucket"] . $s3_raw_file)); |
| 541 |
/**/ |
| 542 |
$s3_url = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "http" . (($ssl) ? "s" : "") . "://s3.amazonaws.com/" . $s3c["bucket"] . $s3_file : "http" . (($ssl) ? "s" : "") . "://" . $s3c["bucket"] . ".s3.amazonaws.com" . $s3_file; |
| 543 |
return add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */ |
| 544 |
(urlencode_deep (array ("AWSAccessKeyId" => $s3c["access_key"], "Expires" => $s3c["expires"], "Signature" => $s3_signature))), $s3_url); |
| 545 |
} |
| 546 |
/** |
| 547 |
* Auto-configures an Amazon® S3 Bucket's ACLs. |
| 548 |
* |
| 549 |
* @package s2Member\Files |
| 550 |
* @since 110926 |
| 551 |
* |
| 552 |
* @return array Array containing a true `success` element on success, else a failure array. |
| 553 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 554 |
*/ |
| 555 |
public static function amazon_s3_auto_configure_acls () |
| 556 |
{ |
| 557 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 558 |
if (preg_match ("/^amazon_s3_files_/", $option) && ($option = preg_replace ("/^amazon_s3_files_/", "", $option))) |
| 559 |
$s3c[$option] = $option_value; |
| 560 |
/**/ |
| 561 |
$cfc["distros_s3_access_id"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_s3_access_id"]; |
| 562 |
/**/ |
| 563 |
if ($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"]) /* Must have Amazon® S3 Bucket/Keys. */ |
| 564 |
{ |
| 565 |
$s3_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 566 |
$s3_location = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "/" . $s3c["bucket"] . "/?acl" : "/?acl"; |
| 567 |
$s3_domain = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "s3.amazonaws.com" : $s3c["bucket"] . ".s3.amazonaws.com"; |
| 568 |
$s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("GET\n\n\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?acl")); |
| 569 |
$s3_args = array ("method" => "GET", "headers" => array ("Host" => $s3_domain, "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); |
| 570 |
/**/ |
| 571 |
if (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && $s3_response["code"] === 200) |
| 572 |
{ |
| 573 |
if (preg_match ("/\<Owner\>(.+?)\<\/Owner\>/is", $s3_response["body"], $s3_owner_tag) && preg_match ("/\<ID\>(.+?)\<\/ID\>/is", $s3_owner_tag[1], $s3_owner_id_tag) && (preg_match ("/\<DisplayName\>(.*?)\<\/DisplayName\>/is", $s3_owner_tag[1], $s3_owner_display_name_tag) || ($s3_owner_display_name_tag = array ("-", "Owner")))) |
| 574 |
{ |
| 575 |
$s3_owner = array ("access_id" => trim ($s3_owner_id_tag[1]), "display_name" => trim ($s3_owner_display_name_tag[1])); |
| 576 |
$s3_acls_xml = '<AccessControlPolicy><Owner><ID>' . esc_html ($s3_owner["access_id"]) . '</ID><DisplayName>' . esc_html ($s3_owner["display_name"]) . '</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>' . esc_html ($s3_owner["access_id"]) . '</ID><DisplayName>' . esc_html ($s3_owner["display_name"]) . '</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant>' . (($cfc["distros_s3_access_id"]) ? '<Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>' . esc_html ($cfc["distros_s3_access_id"]) . '</ID><DisplayName>s2Member/CloudFront</DisplayName></Grantee><Permission>READ</Permission></Grant>' : '') . '</AccessControlList></AccessControlPolicy>'; |
| 577 |
$s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("PUT\n\napplication/xml\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?acl")); |
| 578 |
$s3_args = array ("method" => "PUT", "body" => $s3_acls_xml, "headers" => array ("Host" => $s3_domain, "Content-Type" => "application/xml", "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); |
| 579 |
/**/ |
| 580 |
if (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && $s3_response["code"] === 200) |
| 581 |
{ |
| 582 |
$s3_location = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "/" . $s3c["bucket"] . "/?policy" : "/?policy"; |
| 583 |
$s3_policy_json = '{"Version":"2008-10-17","Id":"' . md5 ("s2Member/CloudFront") . '","Statement":[{"Sid":"s2Member/CloudFront","Effect":"Allow","Principal":{"CanonicalUser":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($cfc["distros_s3_access_id"]) . '"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::' . c_ws_plugin__s2member_utils_strings::esc_dq ($s3c["bucket"]) . '/*"}]}'; |
| 584 |
$s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("PUT\n\napplication/json\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?policy")); |
| 585 |
$s3_args = array ("method" => "PUT", "body" => $s3_policy_json, "headers" => array ("Host" => $s3_domain, "Content-Type" => "application/json", "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); |
| 586 |
/**/ |
| 587 |
if (!$cfc["distros_s3_access_id"] || (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && ($s3_response["code"] === 200 || $s3_response["code"] === 204 /* Also OK. */))) |
| 588 |
{ |
| 589 |
$s3_location = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "/" . $s3c["bucket"] . "/crossdomain.xml" : "/crossdomain.xml"; |
| 590 |
$s3_policy_xml = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/cfg-files/s2-cross-xml.php"))); |
| 591 |
$s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("PUT\n\ntext/xml\n" . $s3_date . "\nx-amz-acl:public-read\n/" . $s3c["bucket"] . "/crossdomain.xml")); |
| 592 |
$s3_args = array ("method" => "PUT", "body" => $s3_policy_xml, "headers" => array ("Host" => $s3_domain, "Content-Type" => "text/xml", "Date" => $s3_date, "X-Amz-Acl" => "public-read", "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); |
| 593 |
/**/ |
| 594 |
if (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && $s3_response["code"] === 200) |
| 595 |
return array ("success" => true, "code" => null, "message" => null); /* Successfully configured Amazon® S3 Bucket ACLs and Policy. */ |
| 596 |
/**/ |
| 597 |
else if (isset ($s3_response["code"], $s3_response["message"])) |
| 598 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */ |
| 599 |
return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 Cross-Domain Policy. %s", "s2member-admin", "s2member"), $s3_response["message"])); |
| 600 |
/**/ |
| 601 |
else /* Else, we use a default error code and message. */ |
| 602 |
return array ("success" => false, "code" => -94, "message" => _x ("Unable to update existing Amazon® S3 Cross-Domain Policy. Connection failed.", "s2member-admin", "s2member")); |
| 603 |
} |
| 604 |
else if (isset ($s3_response["code"], $s3_response["message"])) |
| 605 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */ |
| 606 |
return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 Bucket Policy. %s", "s2member-admin", "s2member"), $s3_response["message"])); |
| 607 |
/**/ |
| 608 |
else /* Else, we use a default error code and message. */ |
| 609 |
return array ("success" => false, "code" => -95, "message" => _x ("Unable to update existing Amazon® S3 Bucket Policy. Connection failed.", "s2member-admin", "s2member")); |
| 610 |
} |
| 611 |
else if (isset ($s3_response["code"], $s3_response["message"])) |
| 612 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */ |
| 613 |
return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 Bucket ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"])); |
| 614 |
/**/ |
| 615 |
else /* Else, we use a default error code and message. */ |
| 616 |
return array ("success" => false, "code" => -96, "message" => _x ("Unable to update existing Amazon® S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member")); |
| 617 |
} |
| 618 |
else /* Else, we use a default error code and message. */ |
| 619 |
return array ("success" => false, "code" => -97, "message" => _x ("Unable to acquire/read existing Amazon® S3 Bucket ACLs. Unexpected response.", "s2member-admin", "s2member")); |
| 620 |
} |
| 621 |
else if (isset ($s3_response["code"], $s3_response["message"])) |
| 622 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */ |
| 623 |
return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® S3 Bucket ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"])); |
| 624 |
/**/ |
| 625 |
else /* Else, we use a default error code and message. */ |
| 626 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to acquire existing Amazon® S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member")); |
| 627 |
} |
| 628 |
else /* Else, we use a default error code and message. */ |
| 629 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to auto-configure existing Amazon® S3 Bucket ACLs. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key.", "s2member-admin", "s2member")); |
| 630 |
} |
| 631 |
/** |
| 632 |
* Creates an Amazon® CloudFront HMAC-SHA1 signature. |
| 633 |
* |
| 634 |
* @package s2Member\Files |
| 635 |
* @since 110926 |
| 636 |
* |
| 637 |
* @param str $string Input string/data, to be signed by this routine. |
| 638 |
* @return str An HMAC-SHA1 signature for Amazon® CloudFront. |
| 639 |
*/ |
| 640 |
public static function amazon_cf_sign ($string = FALSE) |
| 641 |
{ |
| 642 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 643 |
/**/ |
| 644 |
return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign ((string)$string, ($cfc["secret_key"] = $s3c["secret_key"])); |
| 645 |
} |
| 646 |
/** |
| 647 |
* Creates an Amazon® CloudFront RSA-SHA1 signature. |
| 648 |
* |
| 649 |
* @package s2Member\Files |
| 650 |
* @since 110926 |
| 651 |
* |
| 652 |
* @param str $string Input string/data, to be signed by this routine. |
| 653 |
* @return str|bool An RSA-SHA1 signature for Amazon® CloudFront, else false on failure. |
| 654 |
* |
| 655 |
* @todo Double underscores *( i.e. base64 padding chars )* in the signature seem to cause issues for Amazon® CloudFront? |
| 656 |
* See ticket: {@link https://forums.aws.amazon.com/thread.jspa?messageID=286182񅷦} |
| 657 |
*/ |
| 658 |
public static function amazon_cf_rsa_sign ($string = FALSE) |
| 659 |
{ |
| 660 |
$cfc["private_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]; |
| 661 |
/**/ |
| 662 |
return c_ws_plugin__s2member_utils_strings::rsa_sha1_sign ((string)$string, $cfc["private_key"]); |
| 663 |
} |
| 664 |
/** |
| 665 |
* Creates an Amazon® CloudFront RSA-SHA1 signature URL. |
| 666 |
* |
| 667 |
* @package s2Member\Files |
| 668 |
* @since 110926 |
| 669 |
* |
| 670 |
* @param str $file Input file path, to be signed by this routine. |
| 671 |
* @param bool $stream Is this resource file to be served as streaming media? |
| 672 |
* @param bool $inline Is this resource file to be served inline, or no? |
| 673 |
* @param bool $ssl Is this resource file to be served via SSL, or no? |
| 674 |
* @param str $basename The absolute basename of the resource file. |
| 675 |
* @param str $mimetype The MIME content-type of the resource file. |
| 676 |
* @return str An RSA-SHA1 signature URL for Amazon® CloudFront. |
| 677 |
*/ |
| 678 |
public static function amazon_cf_url ($file = FALSE, $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = FALSE, $mimetype = FALSE) |
| 679 |
{ |
| 680 |
$file = trim ((string)$file, "/"); /* Trim / force string. */ |
| 681 |
/**/ |
| 682 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 683 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 684 |
$cfc[$option] = $option_value; |
| 685 |
/**/ |
| 686 |
$cfc["expires"] = strtotime ("+" . apply_filters ("ws_plugin__s2member_amazon_cf_file_expires_time", "24 hours", get_defined_vars ())); |
| 687 |
/**/ |
| 688 |
$cf_extn = strtolower (substr ($file, strrpos ($file, ".") + 1)); /* Parses the file extension out so we can scan it in some special scenarios. */ |
| 689 |
$cf_stream_extn_resource_exclusions = array_unique ((array)apply_filters ("ws_plugin__s2member_amazon_cf_file_streaming_extension_resource_exclusions", array ("mp3" /* MP3 files should NOT include an extension in their resource reference. */), get_defined_vars ())); |
| 690 |
$cf_resource = ($stream) ? ((in_array ($cf_extn, $cf_stream_extn_resource_exclusions)) ? substr ($file, 0, strrpos ($file, ".")) : $file) : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file; |
| 691 |
$cf_url = ($stream) ? "rtmp" . (($ssl) ? "e" : "") . "://" . (($cfc["distro_streaming_cname"]) ? $cfc["distro_streaming_cname"] : $cfc["distro_streaming_dname"]) . "/cfx/st/" . $file : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file; |
| 692 |
$cf_ip_res = (stripos ($_SERVER["HTTP_HOST"], "localhost") === false && strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") === false && (!defined ("LOCALHOST") || !LOCALHOST)) ? true : false; /* Don NOT restrict access to a particular IP during `localhost` development. The IP will NOT be the same one Amazon® CloudFront sees ( will NOT jive ). */ |
| 693 |
$cf_policy = '{"Statement":[{"Resource":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($cf_resource) . '","Condition":{' . (($cf_ip_res) ? '"IpAddress":{"AWS:SourceIp":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($_SERVER["REMOTE_ADDR"]) . '/32"},' : '') . '"DateLessThan":{"AWS:EpochTime":' . (int)$cfc["expires"] . '}}}]}'; |
| 694 |
/**/ |
| 695 |
$cf_signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_sign ($cf_policy); |
| 696 |
$cf_base64_url_safe_policy = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_policy, array ("+", "=", "/"), array ("-", "_", "~"), false); |
| 697 |
$cf_base64_url_safe_signature = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_signature, array ("+", "=", "/"), array ("-", "_", "~"), false); |
| 698 |
/**/ |
| 699 |
return add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */ |
| 700 |
(urlencode_deep (array ("Policy" => $cf_base64_url_safe_policy, "Signature" => $cf_base64_url_safe_signature, "Key-Pair-Id" => $cfc["private_key_id"]))), $cf_url); |
| 701 |
} |
| 702 |
/** |
| 703 |
* Auto-configures Amazon® S3/CloudFront distros. |
| 704 |
* |
| 705 |
* @package s2Member\Files |
| 706 |
* @since 110926 |
| 707 |
* |
| 708 |
* @return array Array containing a true `success` element on success, else a failure array. |
| 709 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 710 |
*/ |
| 711 |
public static function amazon_cf_auto_configure_distros () |
| 712 |
{ |
| 713 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 714 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 715 |
$cfc[$option] = $option_value; |
| 716 |
/**/ |
| 717 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 718 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 719 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 720 |
/**/ |
| 721 |
if ($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"]) /* We MUST have an Amazon® S3 Bucket and Keys. */ |
| 722 |
{ |
| 723 |
if ($cfc["private_key"] && $cfc["private_key_id"]) /* We MUST have Amazon® CloudFront Keys in order to auto-configure. */ |
| 724 |
{ |
| 725 |
if (!$cfc["distro_downloads_id"] || ($cfc["distro_downloads_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro ($cfc["distro_downloads_id"], "downloads")) && ($cf_get_response["success"] || $cf_get_response["code"] === 404))) |
| 726 |
{ |
| 727 |
if (!$cfc["distro_downloads_id"] || ($cfc["distro_downloads_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404)) |
| 728 |
$cf_distro_downloads_clear = true; /* Clear, ready for a new one. */ |
| 729 |
/**/ |
| 730 |
else if ($cfc["distro_downloads_id"] && $cf_get_response && $cf_get_response["success"] && !$cf_get_response["deployed"]) |
| 731 |
return array ("success" => false, "code" => -86, "message" => _x ("Unable to delete existing Amazon® CloudFront Downloads Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member")); |
| 732 |
/**/ |
| 733 |
else if ($cfc["distro_downloads_id"] && $cf_get_response && $cf_get_response["success"] && $cf_get_response["deployed"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_distro ($cfc["distro_downloads_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"]) |
| 734 |
$cf_distro_downloads_clear = true; /* Clear, ready for a new one. */ |
| 735 |
/**/ |
| 736 |
else if (isset ($cf_del_response["code"], $cf_del_response["message"])) |
| 737 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 738 |
return array ("success" => false, "code" => $cf_del_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_del_response["message"])); |
| 739 |
/**/ |
| 740 |
if (isset ($cf_distro_downloads_clear) && $cf_distro_downloads_clear) /* Successfully cleared? Ready for a new one? */ |
| 741 |
{ |
| 742 |
unset ($cf_get_response, $cf_del_response); /* Unset these before processing additional routines. Prevents problems in error reporting. */ |
| 743 |
/**/ |
| 744 |
if (!$cfc["distro_streaming_id"] || ($cfc["distro_streaming_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro ($cfc["distro_streaming_id"], "streaming")) && ($cf_get_response["success"] || $cf_get_response["code"] === 404))) |
| 745 |
{ |
| 746 |
if (!$cfc["distro_streaming_id"] || ($cfc["distro_streaming_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404)) |
| 747 |
$cf_distro_streaming_clear = true; /* Clear, ready for a new one. */ |
| 748 |
/**/ |
| 749 |
else if ($cfc["distro_streaming_id"] && $cf_get_response && $cf_get_response["success"] && !$cf_get_response["deployed"]) |
| 750 |
return array ("success" => false, "code" => -87, "message" => _x ("Unable to delete existing Amazon® CloudFront Streaming Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member")); |
| 751 |
/**/ |
| 752 |
else if ($cfc["distro_streaming_id"] && $cf_get_response && $cf_get_response["success"] && $cf_get_response["deployed"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_distro ($cfc["distro_streaming_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"]) |
| 753 |
$cf_distro_streaming_clear = true; /* Clear, ready for a new one. */ |
| 754 |
/**/ |
| 755 |
else if (isset ($cf_del_response["code"], $cf_del_response["message"])) |
| 756 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 757 |
return array ("success" => false, "code" => $cf_del_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_del_response["message"])); |
| 758 |
/**/ |
| 759 |
if (isset ($cf_distro_streaming_clear) && $cf_distro_streaming_clear) /* Successfully cleared? Ready for a new one? */ |
| 760 |
{ |
| 761 |
unset ($cf_get_response, $cf_del_response); /* Unset these before processing additional routines. Prevents problems in error reporting. */ |
| 762 |
/**/ |
| 763 |
if (!$cfc["distros_access_id"] || ($cfc["distros_access_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_access_origin_identity ($cfc["distros_access_id"])) && ($cf_get_response["success"] || $cf_get_response["code"] === 404))) |
| 764 |
{ |
| 765 |
if (!$cfc["distros_access_id"] || ($cfc["distros_access_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404)) |
| 766 |
$cf_distros_access_clear = true; /* Clear, ready for a new one. */ |
| 767 |
/**/ |
| 768 |
else if ($cfc["distros_access_id"] && $cf_get_response && $cf_get_response["success"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_access_origin_identity ($cfc["distros_access_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"]) |
| 769 |
$cf_distros_access_clear = true; /* Clear, ready for a new one. */ |
| 770 |
/**/ |
| 771 |
else if (isset ($cf_del_response["code"], $cf_del_response["message"])) |
| 772 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 773 |
return array ("success" => false, "code" => $cf_del_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_del_response["message"])); |
| 774 |
/**/ |
| 775 |
if (isset ($cf_distros_access_clear) && $cf_distros_access_clear) /* Successfully cleared? Ready for a new one? */ |
| 776 |
{ |
| 777 |
unset ($cf_get_response, $cf_del_response); /* Unset these before processing additional routines. Prevents problems in error reporting. */ |
| 778 |
/**/ |
| 779 |
$cfc = array_merge ($cfc, array ("distros_access_id" => "", "distros_s3_access_id" => "", "distro_downloads_id" => "", "distro_downloads_dname" => "", "distro_streaming_id" => "", "distro_streaming_dname" => "", "distros_auto_config_status" => "")); |
| 780 |
$cf_options = array ("ws_plugin__s2member_amazon_cf_files_distros_access_id" => "", "ws_plugin__s2member_amazon_cf_files_distros_s3_access_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_downloads_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_downloads_dname" => "", "ws_plugin__s2member_amazon_cf_files_distro_streaming_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_streaming_dname" => "", "ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" => ""); |
| 781 |
c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false); |
| 782 |
/**/ |
| 783 |
if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distros_access_origin_identity ()) && $cf_response["success"]) |
| 784 |
{ |
| 785 |
$cfc = array_merge ($cfc, array ("distros_access_id" => $cf_response["distros_access_id"], "distros_s3_access_id" => $cf_response["distros_s3_access_id"])); |
| 786 |
$cf_options = array ("ws_plugin__s2member_amazon_cf_files_distros_access_id" => $cf_response["distros_access_id"], "ws_plugin__s2member_amazon_cf_files_distros_s3_access_id" => $cf_response["distros_s3_access_id"]); |
| 787 |
c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false); |
| 788 |
/**/ |
| 789 |
if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distro ("downloads")) && $cf_response["success"]) |
| 790 |
{ |
| 791 |
$cfc = array_merge ($cfc, array ("distro_downloads_id" => $cf_response["distro_downloads_id"], "distro_downloads_dname" => $cf_response["distro_downloads_dname"])); |
| 792 |
$cf_options = array ("ws_plugin__s2member_amazon_cf_files_distro_downloads_id" => $cf_response["distro_downloads_id"], "ws_plugin__s2member_amazon_cf_files_distro_downloads_dname" => $cf_response["distro_downloads_dname"]); |
| 793 |
c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false); |
| 794 |
/**/ |
| 795 |
if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distro ("streaming")) && $cf_response["success"]) |
| 796 |
{ |
| 797 |
$cfc = array_merge ($cfc, array ("distro_streaming_id" => $cf_response["distro_streaming_id"], "distro_streaming_dname" => $cf_response["distro_streaming_dname"])); |
| 798 |
$cf_options = array ("ws_plugin__s2member_amazon_cf_files_distro_streaming_id" => $cf_response["distro_streaming_id"], "ws_plugin__s2member_amazon_cf_files_distro_streaming_dname" => $cf_response["distro_streaming_dname"]); |
| 799 |
c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false); |
| 800 |
/**/ |
| 801 |
if (($s3_response = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls ()) && $s3_response["success"]) |
| 802 |
{ |
| 803 |
$cfc = array_merge ($cfc, array ("distros_auto_config_status" => "success")); |
| 804 |
$cf_options = array ("ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" => "configured"); |
| 805 |
c_ws_plugin__s2member_menu_pages::update_all_options ( /* Now configured! */$cf_options, true, false, false, false, false); |
| 806 |
/**/ |
| 807 |
return array ("success" => true, "code" => null, "message" => null); /* Successfully configured Amazon® S3/CloudFront distros. */ |
| 808 |
} |
| 809 |
/**/ |
| 810 |
else if (isset ($s3_response["code"], $s3_response["message"])) |
| 811 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */ |
| 812 |
return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"])); |
| 813 |
/**/ |
| 814 |
else /* Else, we use a default error code and message. */ |
| 815 |
return array ("success" => false, "code" => -88, "message" => _x ("Unable to update existing Amazon® S3 ACLs. Connection failed.", "s2member-admin", "s2member")); |
| 816 |
} |
| 817 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 818 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 819 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 820 |
/**/ |
| 821 |
else /* Else, we use a default error code and message. */ |
| 822 |
return array ("success" => false, "code" => -89, "message" => _x ("Unable to create Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member")); |
| 823 |
} |
| 824 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 825 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 826 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 827 |
/**/ |
| 828 |
else /* Else, we use a default error code and message. */ |
| 829 |
return array ("success" => false, "code" => -90, "message" => _x ("Unable to create Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member")); |
| 830 |
} |
| 831 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 832 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 833 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 834 |
/**/ |
| 835 |
else /* Else, we use a default error code and message. */ |
| 836 |
return array ("success" => false, "code" => -91, "message" => _x ("Unable to create Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member")); |
| 837 |
} |
| 838 |
else /* Else, we use a default error code and message. */ |
| 839 |
return array ("success" => false, "code" => -92, "message" => _x ("Unable to clear existing Amazon® CloudFront Origin Access Identity.", "s2member-admin", "s2member")); |
| 840 |
} |
| 841 |
else if (isset ($cf_get_response["code"], $cf_get_response["message"])) |
| 842 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 843 |
return array ("success" => false, "code" => $cf_get_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_get_response["message"])); |
| 844 |
/**/ |
| 845 |
else /* Else, we use a default error code and message. */ |
| 846 |
return array ("success" => false, "code" => -93, "message" => _x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member")); |
| 847 |
} |
| 848 |
else /* Else, we use a default error code and message. */ |
| 849 |
return array ("success" => false, "code" => -94, "message" => _x ("Unable to clear existing Amazon® CloudFront Streaming Distro.", "s2member-admin", "s2member")); |
| 850 |
} |
| 851 |
else if (isset ($cf_get_response["code"], $cf_get_response["message"])) |
| 852 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 853 |
return array ("success" => false, "code" => $cf_get_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_get_response["message"])); |
| 854 |
/**/ |
| 855 |
else /* Else, we use a default error code and message. */ |
| 856 |
return array ("success" => false, "code" => -95, "message" => _x ("Unable to acquire existing Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member")); |
| 857 |
} |
| 858 |
else /* Else, we use a default error code and message. */ |
| 859 |
return array ("success" => false, "code" => -96, "message" => _x ("Unable to clear existing Amazon® CloudFront Downloads Distro.", "s2member-admin", "s2member")); |
| 860 |
} |
| 861 |
else if (isset ($cf_get_response["code"], $cf_get_response["message"])) |
| 862 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 863 |
return array ("success" => false, "code" => $cf_get_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_get_response["message"])); |
| 864 |
/**/ |
| 865 |
else /* Else, we use a default error code and message. */ |
| 866 |
return array ("success" => false, "code" => -97, "message" => _x ("Unable to acquire existing Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member")); |
| 867 |
} |
| 868 |
else /* Else, we use a default error code and message. */ |
| 869 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to auto-configure Amazon® CloudFront Distros. Incomplete Amazon® CloudFront configuration options. Missing of one: Amazon® CloudFront Private Key-Pair-ID, or Private Key file contents.", "s2member-admin", "s2member")); |
| 870 |
} |
| 871 |
else /* Else, we use a default error code and message. */ |
| 872 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to auto-configure Amazon® S3/CloudFront Distros. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key. You must provide s2Member with an Amazon® S3 configuration before enabling CloudFront.", "s2member-admin", "s2member")); |
| 873 |
} |
| 874 |
/** |
| 875 |
* Acquires an Amazon® S3/CloudFront Access Origin Identity. |
| 876 |
* |
| 877 |
* @package s2Member\Files |
| 878 |
* @since 110926 |
| 879 |
* |
| 880 |
* @param str $access_id Required. An Origin Access ID. |
| 881 |
* @return array Array containing a true `success` and `etag`, `xml` elements on success, else a failure array. |
| 882 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 883 |
*/ |
| 884 |
public static function amazon_cf_get_access_origin_identity ($access_id = FALSE) |
| 885 |
{ |
| 886 |
if ($access_id && is_string ($access_id)) /* Valid parameters? */ |
| 887 |
{ |
| 888 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 889 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 890 |
$cfc[$option] = $option_value; |
| 891 |
/**/ |
| 892 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 893 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 894 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 895 |
/**/ |
| 896 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 897 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 898 |
$cf_location = "/2010-11-01/origin-access-identity/cloudfront/" . $access_id; |
| 899 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 900 |
$cf_args = array ("method" => "GET", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 901 |
/**/ |
| 902 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && (($cf_response["code"] === 404 && $cf_response["message"]) || ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"])))) |
| 903 |
{ |
| 904 |
if ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"])) |
| 905 |
return array ("success" => true, "code" => null, "message" => null, "etag" => trim ($cf_response["headers"]["etag"]), "xml" => trim ($cf_response["body"])); |
| 906 |
/**/ |
| 907 |
else /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 908 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Existing Amazon® CloudFront Origin Access Identity NOT found. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 909 |
} |
| 910 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 911 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 912 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 913 |
/**/ |
| 914 |
else /* Else, we use a default error code and message. */ |
| 915 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member")); |
| 916 |
} |
| 917 |
else /* Else, we use a default error code and message. */ |
| 918 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Invalid Access ID.", "s2member-admin", "s2member")); |
| 919 |
} |
| 920 |
/** |
| 921 |
* Deletes an Amazon® S3/CloudFront Access Origin Identity. |
| 922 |
* |
| 923 |
* @package s2Member\Files |
| 924 |
* @since 110926 |
| 925 |
* |
| 926 |
* @param str $access_id Required. An Origin Access ID. |
| 927 |
* @param str $access_id_etag Required. An Origin Access ETag header. |
| 928 |
* @param str $access_id_xml Required. An Origin Access Identity's XML configuration. |
| 929 |
* @return array Array containing a true `success` element on success, else a failure array. |
| 930 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 931 |
*/ |
| 932 |
public static function amazon_cf_del_access_origin_identity ($access_id = FALSE, $access_id_etag = FALSE, $access_id_xml = FALSE) |
| 933 |
{ |
| 934 |
if ($access_id && is_string ($access_id) && $access_id_etag && is_string ($access_id_etag) && $access_id_xml && is_string ($access_id_xml)) |
| 935 |
{ |
| 936 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 937 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 938 |
$cfc[$option] = $option_value; |
| 939 |
/**/ |
| 940 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 941 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 942 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 943 |
/**/ |
| 944 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 945 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 946 |
$cf_location = "/2010-11-01/origin-access-identity/cloudfront/" . $access_id; |
| 947 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 948 |
$cf_args = array ("method" => "DELETE", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "If-Match" => $access_id_etag, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 949 |
/**/ |
| 950 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 204 /* Deleted. */)) |
| 951 |
return array ("success" => true, "code" => null, "message" => null); /* Deleted successfully. */ |
| 952 |
/**/ |
| 953 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 954 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 955 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 956 |
/**/ |
| 957 |
else /* Else, we use a default error code and message. */ |
| 958 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member")); |
| 959 |
} |
| 960 |
else /* Else, we use a default error code and message. */ |
| 961 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. Invalid Access ID, ETag, or XML config.", "s2member-admin", "s2member")); |
| 962 |
} |
| 963 |
/** |
| 964 |
* Creates an Amazon® S3/CloudFront Access Origin Identity for all Distros. |
| 965 |
* |
| 966 |
* @package s2Member\Files |
| 967 |
* @since 110926 |
| 968 |
* |
| 969 |
* @return array Array containing a true `success` and `distros_access_id`, `distros_s3_access_id` elements on success, else a failure array. |
| 970 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 971 |
*/ |
| 972 |
public static function amazon_cf_create_distros_access_origin_identity () |
| 973 |
{ |
| 974 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 975 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 976 |
$cfc[$option] = $option_value; |
| 977 |
/**/ |
| 978 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 979 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 980 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 981 |
/**/ |
| 982 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 983 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 984 |
$cf_location = "/2010-11-01/origin-access-identity/cloudfront"; |
| 985 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 986 |
$cf_distros_access_reference = time () . "." . md5 ("access" . $s3c["bucket"] . $s3c["access_key"] . $s3c["secret_key"] . $cfc["private_key"] . $cfc["private_key_id"]); |
| 987 |
$cf_distros_access_xml = '<?xml version="1.0" encoding="UTF-8"?><CloudFrontOriginAccessIdentityConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><CallerReference>' . esc_html ($cf_distros_access_reference) . '</CallerReference><Comment>' . esc_html (sprintf (_x ("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])) . '</Comment></CloudFrontOriginAccessIdentityConfig>'; |
| 988 |
$cf_args = array ("method" => "POST", "body" => $cf_distros_access_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 989 |
/**/ |
| 990 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */)) |
| 991 |
{ |
| 992 |
if (preg_match ("/\<CloudFrontOriginAccessIdentity.*?\>(.+?)\<\/CloudFrontOriginAccessIdentity\>/is", $cf_response["body"], $cf_distros_access_tag) && preg_match ("/\<Id\>(.+?)\<\/Id\>/is", $cf_distros_access_tag[1], $cf_distros_access_id_tag) && preg_match ("/\<S3CanonicalUserId\>(.+?)\<\/S3CanonicalUserId\>/is", $cf_distros_access_tag[1], $cf_distros_s3_access_id_tag)) |
| 993 |
return array ("success" => true, "code" => null, "message" => null, "distros_access_id" => trim ($cf_distros_access_id_tag[1]), "distros_s3_access_id" => trim ($cf_distros_s3_access_id_tag[1])); |
| 994 |
/**/ |
| 995 |
else /* Else, we use a default error code and message. */ |
| 996 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to create/read Amazon® CloudFront Origin Access Identity. Unexpected response.", "s2member-admin", "s2member")); |
| 997 |
} |
| 998 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 999 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1000 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1001 |
/**/ |
| 1002 |
else /* Else, we use a default error code and message. */ |
| 1003 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to create Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member")); |
| 1004 |
} |
| 1005 |
/** |
| 1006 |
* Acquires an Amazon® S3/CloudFront Distro. |
| 1007 |
* |
| 1008 |
* @package s2Member\Files |
| 1009 |
* @since 110926 |
| 1010 |
* |
| 1011 |
* @param str $distro_id Required. A Distro ID. |
| 1012 |
* @param str $distro_type Required: `downloads|streaming`. |
| 1013 |
* @return array Array containing a true `success` and `etag`, `xml`, `deployed` elements on success, else a failure array. |
| 1014 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 1015 |
*/ |
| 1016 |
public static function amazon_cf_get_distro ($distro_id = FALSE, $distro_type = FALSE) |
| 1017 |
{ |
| 1018 |
if ($distro_id && is_string ($distro_id) && $distro_type && is_string ($distro_type) && in_array ($distro_type, array ("downloads", "streaming"))) |
| 1019 |
{ |
| 1020 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 1021 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 1022 |
$cfc[$option] = $option_value; |
| 1023 |
/**/ |
| 1024 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 1025 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 1026 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 1027 |
/**/ |
| 1028 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 1029 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 1030 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 1031 |
$cf_location = ($distro_type === "streaming") ? "/2010-11-01/streaming-distribution/" . $distro_id : "/2010-11-01/distribution/" . $distro_id; |
| 1032 |
$cf_args = array ("method" => "GET", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 1033 |
/**/ |
| 1034 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && (($cf_response["code"] === 404 && $cf_response["message"]) || ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"])))) |
| 1035 |
{ |
| 1036 |
if ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"])) |
| 1037 |
return array ("success" => true, "code" => null, "message" => null, "etag" => trim ($cf_response["headers"]["etag"]), "xml" => trim ($cf_response["body"]), "deployed" => ((stripos ($cf_response["body"], "<Status>Deployed</Status>") !== false) ? true : false)); |
| 1038 |
/**/ |
| 1039 |
else /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1040 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Existing Amazon® CloudFront Distro NOT found. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1041 |
} |
| 1042 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1043 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1044 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1045 |
/**/ |
| 1046 |
else /* Else, we use a default error code and message. */ |
| 1047 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to acquire existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1048 |
} |
| 1049 |
else /* Else, we use a default error code and message. */ |
| 1050 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to acquire existing Amazon® CloudFront Distro. Invalid Distro ID and/or Distro type.", "s2member-admin", "s2member")); |
| 1051 |
} |
| 1052 |
/** |
| 1053 |
* Disables an Amazon® S3/CloudFront Distro. |
| 1054 |
* |
| 1055 |
* @package s2Member\Files |
| 1056 |
* @since 110926 |
| 1057 |
* |
| 1058 |
* @param str $distro_id Required. A Distro ID. |
| 1059 |
* @param str $distro_id_etag Required. A Distro ETag header. |
| 1060 |
* @param str $distro_id_xml Required. A Distro's XML configuration. |
| 1061 |
* @return array Array containing a true `success` and `etag`, `xml`, `deployed` elements on success, else a failure array. |
| 1062 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 1063 |
*/ |
| 1064 |
public static function amazon_cf_disable_distro ($distro_id = FALSE, $distro_id_etag = FALSE, $distro_id_xml = FALSE) |
| 1065 |
{ |
| 1066 |
if ($distro_id && is_string ($distro_id) && $distro_id_etag && is_string ($distro_id_etag) && $distro_id_xml && is_string ($distro_id_xml) /* Parse type/reference too. */ |
| 1067 |
&& ($distro_id_type = (stripos ($distro_id_xml, "<StreamingDistribution") !== false) ? "streaming" : ((stripos ($distro_id_xml, "<Distribution") !== false) ? "downloads" : false)) # |
| 1068 |
&& preg_match ("/\<CallerReference\>(.+?)\<\/CallerReference\>/is", $distro_id_xml, $distro_id_reference_tag) && ($distro_id_reference = $distro_id_reference_tag[1])) |
| 1069 |
{ |
| 1070 |
if (stripos ($distro_id_xml, "<Enabled>false</Enabled>") === false) /* Only if it has NOT already been disabled. We do NOT need to do it again. */ |
| 1071 |
{ |
| 1072 |
if (stripos ($distro_id_xml, "<Status>Deployed</Status>") !== false) /* Check distro status before we even begin processing. */ |
| 1073 |
{ |
| 1074 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 1075 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 1076 |
$cfc[$option] = $option_value; |
| 1077 |
/**/ |
| 1078 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 1079 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 1080 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 1081 |
/**/ |
| 1082 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 1083 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 1084 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 1085 |
$cf_location = ($distro_id_type === "streaming") ? "/2010-11-01/streaming-distribution/" . $distro_id . "/config" : "/2010-11-01/distribution/" . $distro_id . "/config"; |
| 1086 |
$cf_distro_xml = ($distro_id_type === "streaming") ? '<?xml version="1.0" encoding="UTF-8"?><StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName></S3Origin><CallerReference>' . esc_html ($distro_id_reference) . '</CallerReference><Enabled>false</Enabled><TrustedSigners><Self/></TrustedSigners></StreamingDistributionConfig>' : '<?xml version="1.0" encoding="UTF-8"?><DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName></S3Origin><CallerReference>' . esc_html ($distro_id_reference) . '</CallerReference><Enabled>false</Enabled><TrustedSigners><Self/></TrustedSigners></DistributionConfig>'; |
| 1087 |
$cf_args = array ("method" => "PUT", "body" => $cf_distro_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "If-Match" => $distro_id_etag, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 1088 |
/**/ |
| 1089 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && $cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"])) |
| 1090 |
return array ("success" => true, "code" => null, "message" => null, "etag" => trim ($cf_response["headers"]["etag"]), "xml" => trim ($cf_response["body"]), "deployed" => ((stripos ($cf_response["body"], "<Status>Deployed</Status>") !== false) ? true : false)); |
| 1091 |
/**/ |
| 1092 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1093 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1094 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to disable existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1095 |
/**/ |
| 1096 |
else /* Else, we use a default error code and message. */ |
| 1097 |
return array ("success" => false, "code" => -97, "message" => _x ("Unable to disable existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1098 |
} |
| 1099 |
else /* Else, we use a default error code and message. */ |
| 1100 |
return array ("success" => false, "code" => -98, "message" => _x ("Existing Amazon® CloudFront Distro cannot be disabled at this time. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member")); |
| 1101 |
} |
| 1102 |
else /* Else, we use a default error code and message. */ |
| 1103 |
return array ("success" => true, "code" => null, "message" => null, "etag" => $distro_id_etag, "xml" => $distro_id_xml, "deployed" => ((stripos ($distro_id_xml, "<Status>Deployed</Status>") !== false) ? true : false)); |
| 1104 |
} |
| 1105 |
else /* Else, we use a default error code and message. */ |
| 1106 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to disable existing Amazon® CloudFront Distro. Invalid Distro ID, ETag, or XML config.", "s2member-admin", "s2member")); |
| 1107 |
} |
| 1108 |
/** |
| 1109 |
* Deletes an Amazon® S3/CloudFront Distro. |
| 1110 |
* |
| 1111 |
* @package s2Member\Files |
| 1112 |
* @since 110926 |
| 1113 |
* |
| 1114 |
* @param str $distro_id Required. A Distro ID. |
| 1115 |
* @param str $distro_id_etag Required. A Distro ETag header. |
| 1116 |
* @param str $distro_id_xml Required. A Distro's XML configuration. |
| 1117 |
* @return array Array containing a true `success` element on success, else a failure array. |
| 1118 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 1119 |
*/ |
| 1120 |
public static function amazon_cf_del_distro ($distro_id = FALSE, $distro_id_etag = FALSE, $distro_id_xml = FALSE) |
| 1121 |
{ |
| 1122 |
if ($distro_id && is_string ($distro_id) && $distro_id_etag && is_string ($distro_id_etag) && $distro_id_xml && is_string ($distro_id_xml) /* Parse type/reference too. */ |
| 1123 |
&& ($distro_id_type = (stripos ($distro_id_xml, "<StreamingDistribution") !== false) ? "streaming" : ((stripos ($distro_id_xml, "<Distribution") !== false) ? "downloads" : false)) # |
| 1124 |
&& preg_match ("/\<CallerReference\>(.+?)\<\/CallerReference\>/is", $distro_id_xml, $distro_id_reference_tag) && ($distro_id_reference = $distro_id_reference_tag[1])) |
| 1125 |
{ |
| 1126 |
if (stripos ($distro_id_xml, "<Status>Deployed</Status>") !== false) /* Check distro status before we even begin processing this deletion. */ |
| 1127 |
{ |
| 1128 |
if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_disable_distro ($distro_id, $distro_id_etag, $distro_id_xml)) && $cf_response["success"]) |
| 1129 |
{ |
| 1130 |
if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro ($distro_id, $distro_id_type)) && $cf_response["success"] && $cf_response["deployed"]) |
| 1131 |
{ |
| 1132 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 1133 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 1134 |
$cfc[$option] = $option_value; |
| 1135 |
/**/ |
| 1136 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 1137 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 1138 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 1139 |
/**/ |
| 1140 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 1141 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 1142 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 1143 |
$cf_location = ($distro_id_type === "streaming") ? "/2010-11-01/streaming-distribution/" . $distro_id : "/2010-11-01/distribution/" . $distro_id; |
| 1144 |
$cf_args = array ("method" => "DELETE", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "If-Match" => $cf_response["etag"], "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 1145 |
/**/ |
| 1146 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 204 /* Deleted. */)) |
| 1147 |
return array ("success" => true, "code" => null, "message" => null); /* Deleted successfully. */ |
| 1148 |
/**/ |
| 1149 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1150 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1151 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1152 |
/**/ |
| 1153 |
else /* Else, we use a default error code and message. */ |
| 1154 |
return array ("success" => false, "code" => -94, "message" => _x ("Unable to delete existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1155 |
} |
| 1156 |
else if (isset ($cf_response["success"], $cf_response["deployed"]) && $cf_response["success"] && !$cf_response["deployed"]) |
| 1157 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1158 |
return array ("success" => false, "code" => -95, "message" => _x ("Existing Amazon® CloudFront Distro cannot be deleted at this time. Still in a `pending` state after having been disabled by s2Member. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member")); |
| 1159 |
/**/ |
| 1160 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1161 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1162 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to check status of existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1163 |
/**/ |
| 1164 |
else /* Else, we use a default error code and message. */ |
| 1165 |
return array ("success" => false, "code" => -96, "message" => _x ("Unable to check status of existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1166 |
} |
| 1167 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1168 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1169 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to disable existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1170 |
/**/ |
| 1171 |
else /* Else, we use a default error code and message. */ |
| 1172 |
return array ("success" => false, "code" => -97, "message" => _x ("Unable to disable existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1173 |
} |
| 1174 |
else /* Else, we use a default error code and message. */ |
| 1175 |
return array ("success" => false, "code" => -98, "message" => _x ("Existing Amazon® CloudFront Distro cannot be deleted at this time. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member")); |
| 1176 |
} |
| 1177 |
else /* Else, we use a default error code and message. */ |
| 1178 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to delete existing Amazon® CloudFront Distro. Invalid Distro ID or ETag.", "s2member-admin", "s2member")); |
| 1179 |
} |
| 1180 |
/** |
| 1181 |
* Creates an Amazon® S3/CloudFront Distro. |
| 1182 |
* |
| 1183 |
* @package s2Member\Files |
| 1184 |
* @since 110926 |
| 1185 |
* |
| 1186 |
* @param str $distro_type Required: `downloads|streaming`. |
| 1187 |
* @return array Array containing a true `success` and `distro_[distro_type]_id`, `distro_[distro_type]_dname` elements on success, else a failure array. |
| 1188 |
* Failure array will contain a failure `code`, and a failure `message`. |
| 1189 |
*/ |
| 1190 |
public static function amazon_cf_create_distro ($distro_type = FALSE) |
| 1191 |
{ |
| 1192 |
if ($distro_type && is_string ($distro_type) && in_array ($distro_type, array ("downloads", "streaming"))) |
| 1193 |
{ |
| 1194 |
foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) |
| 1195 |
if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option))) |
| 1196 |
$cfc[$option] = $option_value; |
| 1197 |
/**/ |
| 1198 |
$s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]; |
| 1199 |
$cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]; |
| 1200 |
$cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]; |
| 1201 |
/**/ |
| 1202 |
$cf_domain = "cloudfront.amazonaws.com"; |
| 1203 |
$cf_date = gmdate ("D, d M Y H:i:s") . " GMT"; |
| 1204 |
$cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date)); |
| 1205 |
/**/ |
| 1206 |
if ($distro_type === "downloads") /* Create a `downloads` Distro? This uses a different XML schema. */ |
| 1207 |
{ |
| 1208 |
$cf_location = "/2010-11-01/distribution"; /* Create distro. */ |
| 1209 |
$cf_distro_downloads_reference = time () . "." . md5 ("downloads" . $s3c["bucket"] . $s3c["access_key"] . $s3c["secret_key"] . $cfc["private_key"] . $cfc["private_key_id"] . $cfc["distro_downloads_cname"]); |
| 1210 |
$cf_distro_downloads_xml = '<?xml version="1.0" encoding="UTF-8"?><DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName><OriginAccessIdentity>origin-access-identity/cloudfront/' . esc_html ($cfc["distros_access_id"]) . '</OriginAccessIdentity></S3Origin><CallerReference>' . esc_html ($cf_distro_downloads_reference) . '</CallerReference>' . (($cfc["distro_downloads_cname"]) ? '<CNAME>' . esc_html ($cfc["distro_downloads_cname"]) . '</CNAME>' : '') . '<Comment>' . esc_html (sprintf (_x ("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])) . '</Comment><Enabled>true</Enabled><DefaultRootObject>index.html</DefaultRootObject><TrustedSigners><Self/></TrustedSigners></DistributionConfig>'; |
| 1211 |
$cf_args = array ("method" => "POST", "body" => $cf_distro_downloads_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 1212 |
/**/ |
| 1213 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */)) |
| 1214 |
{ |
| 1215 |
if (preg_match ("/\<Distribution.*?\>(.+?)\<\/Distribution\>/is", $cf_response["body"], $cf_distro_downloads_tag) && preg_match ("/\<Id\>(.+?)\<\/Id\>/is", $cf_distro_downloads_tag[1], $cf_distro_downloads_id_tag) && preg_match ("/\<DomainName\>(.+?)\<\/DomainName\>/is", $cf_distro_downloads_tag[1], $cf_distro_downloads_dname_tag)) |
| 1216 |
return array ("success" => true, "code" => null, "message" => null, "distro_downloads_id" => trim ($cf_distro_downloads_id_tag[1]), "distro_downloads_dname" => trim ($cf_distro_downloads_dname_tag[1])); |
| 1217 |
else /* Else, we use a default error code and message. */ |
| 1218 |
return array ("success" => false, "code" => -97, "message" => _x ("Unable to create/read Amazon® CloudFront Downloads Distro. Unexpected response.", "s2member-admin", "s2member")); |
| 1219 |
} |
| 1220 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1221 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1222 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1223 |
else /* Else, we use a default error code and message. */ |
| 1224 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to create Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1225 |
} |
| 1226 |
/**/ |
| 1227 |
else if ($distro_type === "streaming") /* Create a `streaming` Distro? A different XML schema. */ |
| 1228 |
{ |
| 1229 |
$cf_location = "/2010-11-01/streaming-distribution"; /* Create streaming distro. */ |
| 1230 |
$cf_distro_streaming_reference = time () . "." . md5 ("streaming" . $s3c["bucket"] . $s3c["access_key"] . $s3c["secret_key"] . $cfc["private_key"] . $cfc["private_key_id"] . $cfc["distro_streaming_cname"]); |
| 1231 |
$cf_distro_streaming_xml = '<?xml version="1.0" encoding="UTF-8"?><StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName><OriginAccessIdentity>origin-access-identity/cloudfront/' . esc_html ($cfc["distros_access_id"]) . '</OriginAccessIdentity></S3Origin><CallerReference>' . esc_html ($cf_distro_streaming_reference) . '</CallerReference>' . (($cfc["distro_streaming_cname"]) ? '<CNAME>' . esc_html ($cfc["distro_streaming_cname"]) . '</CNAME>' : '') . '<Comment>' . esc_html (sprintf (_x ("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])) . '</Comment><Enabled>true</Enabled><DefaultRootObject>index.html</DefaultRootObject><TrustedSigners><Self/></TrustedSigners></StreamingDistributionConfig>'; |
| 1232 |
$cf_args = array ("method" => "POST", "body" => $cf_distro_streaming_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature)); |
| 1233 |
/**/ |
| 1234 |
if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */)) |
| 1235 |
{ |
| 1236 |
if (preg_match ("/\<StreamingDistribution.*?\>(.+?)\<\/StreamingDistribution\>/is", $cf_response["body"], $cf_distro_streaming_tag) && preg_match ("/\<Id\>(.+?)\<\/Id\>/is", $cf_distro_streaming_tag[1], $cf_distro_streaming_id_tag) && preg_match ("/\<DomainName\>(.+?)\<\/DomainName\>/is", $cf_distro_streaming_tag[1], $cf_distro_streaming_dname_tag)) |
| 1237 |
return array ("success" => true, "code" => null, "message" => null, "distro_streaming_id" => trim ($cf_distro_streaming_id_tag[1]), "distro_streaming_dname" => trim ($cf_distro_streaming_dname_tag[1])); |
| 1238 |
else /* Else, we use a default error code and message. */ |
| 1239 |
return array ("success" => false, "code" => -97, "message" => _x ("Unable to create/read Amazon® CloudFront Streaming Distro. Unexpected response.", "s2member-admin", "s2member")); |
| 1240 |
} |
| 1241 |
else if (isset ($cf_response["code"], $cf_response["message"])) |
| 1242 |
/* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */ |
| 1243 |
return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_response["message"])); |
| 1244 |
else /* Else, we use a default error code and message. */ |
| 1245 |
return array ("success" => false, "code" => -98, "message" => _x ("Unable to create Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member")); |
| 1246 |
} |
| 1247 |
} |
| 1248 |
else /* Else, we use a default error code and message. */ |
| 1249 |
return array ("success" => false, "code" => -99, "message" => _x ("Unable to create Amazon® CloudFront Distro. Invalid Distro type.", "s2member-admin", "s2member")); |
| 1250 |
} |
| 1251 |
} |
| 1252 |
} |
| 1253 |
?> |