/** * Auto-configures an Amazon S3 Bucket's ACLs. * * @package s2Member\Files * @since 110926 * * @return array Array containing a true `success` element on success, else a failure array. * Failure array will contain a failure `code`, and a failure `message`. */ public static function amazon_s3_auto_configure_acls() { foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value) { if (preg_match("/^amazon_s3_files_/", $option) && ($option = preg_replace("/^amazon_s3_files_/", "", $option))) { $s3c[$option] = $option_value; } } $cfc["distros_s3_access_id"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_s3_access_id"]; if ($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"]) { $s3_date = gmdate("D, d M Y H:i:s") . " GMT"; $s3_location = strtolower($s3c["bucket"]) !== $s3c["bucket"] ? "/" . $s3c["bucket"] . "/?acl" : "/?acl"; $s3_domain = strtolower($s3c["bucket"]) !== $s3c["bucket"] ? "s3.amazonaws.com" : $s3c["bucket"] . ".s3.amazonaws.com"; $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("GET\n\n\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?acl")); $s3_args = array("method" => "GET", "redirection" => 0, "headers" => array("Host" => $s3_domain, "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); 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) { 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")))) { $s3_owner = array("access_id" => trim($s3_owner_id_tag[1]), "display_name" => trim($s3_owner_display_name_tag[1])); $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>'; $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("PUT\n\napplication/xml\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?acl")); $s3_args = array("method" => "PUT", "redirection" => 0, "body" => $s3_acls_xml, "headers" => array("Host" => $s3_domain, "Content-Type" => "application/xml", "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); 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) { $s3_location = strtolower($s3c["bucket"]) !== $s3c["bucket"] ? "/" . $s3c["bucket"] . "/?policy" : "/?policy"; ($s3_policy_id = md5(uniqid("s2Member/CloudFront:", true))) . ($s3_policy_sid = md5(uniqid("s2Member/CloudFront:", true))); $s3_policy_json = '{"Version":"2008-10-17","Id":"' . c_ws_plugin__s2member_utils_strings::esc_dq($s3_policy_id) . '","Statement":[{"Sid":"' . c_ws_plugin__s2member_utils_strings::esc_dq($s3_policy_sid) . '","Effect":"Allow","Principal":{"CanonicalUser":"******"distros_s3_access_id"]) . '"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::' . c_ws_plugin__s2member_utils_strings::esc_dq($s3c["bucket"]) . '/*"}]}'; $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("PUT\n\napplication/json\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?policy")); $s3_args = array("method" => "PUT", "redirection" => 0, "body" => $s3_policy_json, "headers" => array("Host" => $s3_domain, "Content-Type" => "application/json", "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature)); 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)) { $s3_location = strtolower($s3c["bucket"]) !== $s3c["bucket"] ? "/" . $s3c["bucket"] . "/crossdomain.xml" : "/crossdomain.xml"; $s3_policy_xml = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/cfg-files/s2-cross-xml.php"))); $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")); $s3_args = array("method" => "PUT", "redirection" => 0, "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)); 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) { return array("success" => true, "code" => null, "message" => null); } else { if (isset($s3_response["code"], $s3_response["message"])) { /* 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. */ 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"])); } else { // Else, we use a default error code and message. return array("success" => false, "code" => -94, "message" => _x("Unable to update existing Amazon S3 Cross-Domain Policy. Connection failed.", "s2member-admin", "s2member")); } } } else { if (isset($s3_response["code"], $s3_response["message"])) { /* 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. */ 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"])); } else { // Else, we use a default error code and message. return array("success" => false, "code" => -95, "message" => _x("Unable to update existing Amazon S3 Bucket Policy. Connection failed.", "s2member-admin", "s2member")); } } } else { if (isset($s3_response["code"], $s3_response["message"])) { /* 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. */ 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"])); } else { // Else, we use a default error code and message. return array("success" => false, "code" => -96, "message" => _x("Unable to update existing Amazon S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member")); } } } else { // Else, we use a default error code and message. return array("success" => false, "code" => -97, "message" => _x("Unable to acquire/read existing Amazon S3 Bucket ACLs. Unexpected response.", "s2member-admin", "s2member")); } } else { if (isset($s3_response["code"], $s3_response["message"])) { /* 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. */ 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"])); } else { // Else, we use a default error code and message. return array("success" => false, "code" => -98, "message" => _x("Unable to acquire existing Amazon S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member")); } } } else { // Else, we use a default error code and message. 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")); } }
/** * Creates an Amazon S3 HMAC-SHA1 signature URL. * * @package s2Member\Files * @since 110926 * * @param string $file Input file path, to be signed by this routine. * @param bool $stream Is this resource file to be served as streaming media? * @param bool $inline Is this resource file to be served inline, or no? * @param bool $ssl Is this resource file to be served via SSL, or no? * @param string $basename The absolute basename of the resource file. * @param string $mimetype The MIME content-type of the resource file. * * @return string An HMAC-SHA1 signature URL for Amazon S3. */ public static function amazon_s3_url($file = '', $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = '', $mimetype = '') { $file = trim((string) $file, '/'); // Trim / force string. $url_e_file = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep(urlencode($file)); $url_e_file = str_ireplace('%2F', '/', $url_e_file); foreach ($GLOBALS['WS_PLUGIN__']['s2member']['o'] as $option => $option_value) { if (preg_match('/^amazon_s3_files_/', $option) && ($option = preg_replace('/^amazon_s3_files_/', '', $option))) { $s3c[$option] = $option_value; } } $s3c['expires'] = strtotime('+' . apply_filters('ws_plugin__s2member_amazon_s3_file_expires_time', '24 hours', get_defined_vars())); $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'))), '/' . $url_e_file); $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), '/' . $url_e_file); $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)); $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; return add_query_arg(c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep(urlencode_deep(array('AWSAccessKeyId' => $s3c['access_key'], 'Expires' => $s3c['expires'], 'Signature' => $s3_signature))), $s3_url); }
/** * Auto-configures an Amazon S3 Bucket's ACLs. * * @package s2Member\Files * @since 110926 * * @return array Array containing a true `success` element on success, else a failure array. * Failure array will contain a failure `code`, and a failure `message`. */ public static function amazon_s3_auto_configure_acls() { foreach ($GLOBALS['WS_PLUGIN__']['s2member']['o'] as $option => $option_value) { if (preg_match('/^amazon_s3_files_/', $option) && ($option = preg_replace('/^amazon_s3_files_/', '', $option))) { $s3c[$option] = $option_value; } } $cfc['distros_s3_access_id'] = $GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distros_s3_access_id']; if (!empty($s3c) && $s3c['bucket'] && $s3c['access_key'] && $s3c['secret_key']) { $s3_date = gmdate('D, d M Y H:i:s') . ' GMT'; $s3_location = strtolower($s3c['bucket']) !== $s3c['bucket'] ? '/' . $s3c['bucket'] . '/?acl' : '/?acl'; $s3_domain = strtolower($s3c['bucket']) !== $s3c['bucket'] ? 's3.amazonaws.com' : $s3c['bucket'] . '.s3.amazonaws.com'; $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign('GET' . "\n\n\n" . $s3_date . "\n" . '/' . $s3c['bucket'] . '/?acl')); $s3_args = array('method' => 'GET', 'redirection' => 5, 'headers' => array('Host' => $s3_domain, 'Date' => $s3_date, 'Authorization' => 'AWS ' . $s3c['access_key'] . ':' . $s3_signature)); 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) { 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')))) { $s3_owner = array('access_id' => trim($s3_owner_id_tag[1]), 'display_name' => trim($s3_owner_display_name_tag[1])); $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>'; $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign('PUT' . "\n\n" . 'application/xml' . "\n" . $s3_date . "\n" . '/' . $s3c['bucket'] . '/?acl')); $s3_args = array('method' => 'PUT', 'redirection' => 5, 'body' => $s3_acls_xml, 'headers' => array('Host' => $s3_domain, 'Content-Type' => 'application/xml', 'Date' => $s3_date, 'Authorization' => 'AWS ' . $s3c['access_key'] . ':' . $s3_signature)); 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) { $s3_location = strtolower($s3c['bucket']) !== $s3c['bucket'] ? '/' . $s3c['bucket'] . '/?policy' : '/?policy'; ($s3_policy_id = md5(uniqid('s2Member/CloudFront:', TRUE))) . ($s3_policy_sid = md5(uniqid('s2Member/CloudFront:', TRUE))); $s3_policy_json = '{"Version":"2008-10-17","Id":"' . c_ws_plugin__s2member_utils_strings::esc_dq($s3_policy_id) . '","Statement":[{"Sid":"' . c_ws_plugin__s2member_utils_strings::esc_dq($s3_policy_sid) . '","Effect":"Allow","Principal":{"CanonicalUser":"******"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::' . c_ws_plugin__s2member_utils_strings::esc_dq($s3c['bucket']) . '/*"}]}'; $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign('PUT' . "\n\n" . 'application/json' . "\n" . $s3_date . "\n" . '/' . $s3c['bucket'] . '/?policy')); $s3_args = array('method' => 'PUT', 'redirection' => 5, 'body' => $s3_policy_json, 'headers' => array('Host' => $s3_domain, 'Content-Type' => 'application/json', 'Date' => $s3_date, 'Authorization' => 'AWS ' . $s3c['access_key'] . ':' . $s3_signature)); 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)) { $s3_location = strtolower($s3c['bucket']) !== $s3c['bucket'] ? '/' . $s3c['bucket'] . '/crossdomain.xml' : '/crossdomain.xml'; $s3_policy_xml = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . '/templates/cfg-files/s2-cross-xml.php'))); $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign('PUT' . "\n\n" . 'text/xml' . "\n" . $s3_date . "\n" . 'x-amz-acl:public-read' . "\n" . '/' . $s3c['bucket'] . '/crossdomain.xml')); $s3_args = array('method' => 'PUT', 'redirection' => 5, '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)); 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) { return array('success' => TRUE, 'code' => NULL, 'message' => NULL); } else { if (isset($s3_response['code'], $s3_response['message'])) { /* 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. */ 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'])); } else { // Else, we use a default error code and message. return array('success' => FALSE, 'code' => -94, 'message' => _x('Unable to update existing Amazon S3 Cross-Domain Policy. Connection failed.', 's2member-admin', 's2member')); } } } else { if (isset($s3_response['code'], $s3_response['message'])) { /* 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. */ 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'])); } else { // Else, we use a default error code and message. return array('success' => FALSE, 'code' => -95, 'message' => _x('Unable to update existing Amazon S3 Bucket Policy. Connection failed.', 's2member-admin', 's2member')); } } } else { if (isset($s3_response['code'], $s3_response['message'])) { /* 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. */ 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'])); } else { // Else, we use a default error code and message. return array('success' => FALSE, 'code' => -96, 'message' => _x('Unable to update existing Amazon S3 Bucket ACLs. Connection failed.', 's2member-admin', 's2member')); } } } else { // Else, we use a default error code and message. return array('success' => FALSE, 'code' => -97, 'message' => _x('Unable to acquire/read existing Amazon S3 Bucket ACLs. Unexpected response.', 's2member-admin', 's2member')); } } else { if (isset($s3_response['code'], $s3_response['message'])) { /* 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. */ 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'])); } else { // Else, we use a default error code and message. return array('success' => FALSE, 'code' => -98, 'message' => _x('Unable to acquire existing Amazon S3 Bucket ACLs. Connection failed.', 's2member-admin', 's2member')); } } } else { // Else, we use a default error code and message. 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')); } }