diff --git a/ChangeLog.md b/ChangeLog.md index 9dd6d39..430f6dd 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,6 @@ +2019.03 - version 1.3.0 +* Documentation refinement. + 2018.08 - version 1.2.0 * Fixed a bug `generateCanonicalResource` returns an empty string if `$resource` starts with "/". diff --git a/composer.json b/composer.json index 7ff5ba3..f225d8c 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "microsoft/azure-storage-common", - "version": "1.2.0", + "version": "1.3.0", "description": "This project provides a set of common code shared by Azure Storage Blob, Table, Queue and File PHP client libraries.", "keywords": [ "php", "azure", "storage", "sdk", "common" ], "license": "MIT", diff --git a/src/Common/Internal/Resources.php b/src/Common/Internal/Resources.php index 557ba47..128236b 100644 --- a/src/Common/Internal/Resources.php +++ b/src/Common/Internal/Resources.php @@ -51,12 +51,18 @@ class Resources const TABLE_ENDPOINT_NAME = 'TableEndpoint'; const FILE_ENDPOINT_NAME = 'FileEndpoint'; const SHARED_ACCESS_SIGNATURE_NAME = 'SharedAccessSignature'; + const ENDPOINT_SUFFIX_NAME = 'EndpointSuffix'; + const DEFAULT_ENDPOINT_SUFFIX = 'core.windows.net'; const DEV_STORE_NAME = 'devstoreaccount1'; const DEV_STORE_KEY = 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=='; const BLOB_BASE_DNS_NAME = 'blob.core.windows.net'; + const BLOB_DNS_PREFIX = 'blob.'; const QUEUE_BASE_DNS_NAME = 'queue.core.windows.net'; + const QUEUE_DNS_PREFIX = 'queue.'; const TABLE_BASE_DNS_NAME = 'table.core.windows.net'; + const TABLE_DNS_PREFIX = 'table.'; const FILE_BASE_DNS_NAME = 'file.core.windows.net'; + const FILE_DNS_PREFIX = 'file.'; const DEV_STORE_CONNECTION_STRING = 'BlobEndpoint=127.0.0.1:10000;QueueEndpoint=127.0.0.1:10001;TableEndpoint=127.0.0.1:10002;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=='; const SUBSCRIPTION_ID_NAME = 'SubscriptionID'; const CERTIFICATE_PATH_NAME = 'CertificatePath'; @@ -83,6 +89,7 @@ class Resources const INVALID_CREATE_SERVICE_OPTIONS_MSG = 'Must provide valid location or affinity group.'; const INVALID_UPDATE_SERVICE_OPTIONS_MSG = 'Must provide either description or label.'; const INVALID_CONFIG_MSG = 'Config object must be of type Configuration'; + const INVALID_CONFIG_HOSTNAME = "The provided hostname '%s' is invalid."; const INVALID_CONFIG_URI = "The provided URI '%s' is invalid. It has to pass the check 'filter_var(, FILTER_VALIDATE_URL)'."; const INVALID_CONFIG_VALUE = "The provided config value '%s' does not belong to the valid values subset:\n%s"; const INVALID_ACCOUNT_KEY_FORMAT = "The provided account key '%s' is not a valid base64 string. It has to pass the check 'base64_decode(, true)'."; @@ -230,7 +237,7 @@ class Resources const DEFAULT_RETRY_INTERVAL = 1000;//Milliseconds // Header values - const COMMON_SDK_VERSION = '1.2.0'; + const COMMON_SDK_VERSION = '1.3.0'; const INT32_MAX = 2147483647; const INT32_MIN = -2147483648; diff --git a/src/Common/Internal/StorageServiceSettings.php b/src/Common/Internal/StorageServiceSettings.php index 67ad65a..b36a13d 100644 --- a/src/Common/Internal/StorageServiceSettings.php +++ b/src/Common/Internal/StorageServiceSettings.php @@ -62,6 +62,7 @@ class StorageServiceSettings extends ServiceSettings private static $queueEndpointSetting; private static $tableEndpointSetting; private static $fileEndpointSetting; + private static $endpointSuffixSetting; /** * If initialized or not @@ -137,6 +138,11 @@ function ($key) { Validate::getIsValidUri() ); + self::$endpointSuffixSetting = self::settingWithFunc( + Resources::ENDPOINT_SUFFIX_NAME, + Validate::getIsValidHostname() + ); + self::$validSettingKeys[] = Resources::USE_DEVELOPMENT_STORAGE_NAME; self::$validSettingKeys[] = Resources::DEVELOPMENT_STORAGE_PROXY_URI_NAME; self::$validSettingKeys[] = Resources::DEFAULT_ENDPOINTS_PROTOCOL_NAME; @@ -147,6 +153,7 @@ function ($key) { self::$validSettingKeys[] = Resources::QUEUE_ENDPOINT_NAME; self::$validSettingKeys[] = Resources::TABLE_ENDPOINT_NAME; self::$validSettingKeys[] = Resources::FILE_ENDPOINT_NAME; + self::$validSettingKeys[] = Resources::ENDPOINT_SUFFIX_NAME; } /** @@ -249,7 +256,8 @@ public static function developmentStorageAccount() * * @param string $scheme The scheme of the service end point. * @param string $accountName The account name of the service. - * @param string $dns The service DNS. + * @param string $dnsPrefix The service DNS prefix. + * @param string $dnsSuffix The service DNS suffix. * @param bool $isSecondary If generating secondary endpoint. * * @return string @@ -257,17 +265,21 @@ public static function developmentStorageAccount() private static function getServiceEndpoint( $scheme, $accountName, - $dns, + $dnsPrefix, + $dnsSuffix = null, $isSecondary = false ) { if ($isSecondary) { $accountName .= Resources::SECONDARY_STRING; } + if ($dnsSuffix === null) { + $dnsSuffix = Resources::DEFAULT_ENDPOINT_SUFFIX; + } return sprintf( Resources::SERVICE_URI_FORMAT, $scheme, $accountName, - $dns + $dnsPrefix.$dnsSuffix ); } @@ -383,62 +395,75 @@ public static function createFromConnectionString($connectionString) self::$blobEndpointSetting, self::$queueEndpointSetting, self::$tableEndpointSetting, - self::$fileEndpointSetting + self::$fileEndpointSetting, + self::$endpointSuffixSetting ) ); if ($matchedSpecs) { - $scheme = Utilities::tryGetValueInsensitive( + $scheme = Utilities::tryGetValueInsensitive( Resources::DEFAULT_ENDPOINTS_PROTOCOL_NAME, $tokenizedSettings ); - $accountName = Utilities::tryGetValueInsensitive( + $accountName = Utilities::tryGetValueInsensitive( Resources::ACCOUNT_NAME_NAME, $tokenizedSettings ); + $endpointSuffix = Utilities::tryGetValueInsensitive( + Resources::ENDPOINT_SUFFIX_NAME, + $tokenizedSettings + ); return self::createStorageServiceSettings( $tokenizedSettings, self::getServiceEndpoint( $scheme, $accountName, - Resources::BLOB_BASE_DNS_NAME + Resources::BLOB_DNS_PREFIX, + $endpointSuffix ), self::getServiceEndpoint( $scheme, $accountName, - Resources::QUEUE_BASE_DNS_NAME + Resources::QUEUE_DNS_PREFIX, + $endpointSuffix ), self::getServiceEndpoint( $scheme, $accountName, - Resources::TABLE_BASE_DNS_NAME + Resources::TABLE_DNS_PREFIX, + $endpointSuffix ), self::getServiceEndpoint( $scheme, $accountName, - Resources::FILE_BASE_DNS_NAME + Resources::FILE_DNS_PREFIX, + $endpointSuffix ), self::getServiceEndpoint( $scheme, $accountName, - Resources::BLOB_BASE_DNS_NAME, + Resources::BLOB_DNS_PREFIX, + $endpointSuffix, true ), self::getServiceEndpoint( $scheme, $accountName, - Resources::QUEUE_BASE_DNS_NAME, + Resources::QUEUE_DNS_PREFIX, + $endpointSuffix, true ), self::getServiceEndpoint( $scheme, $accountName, - Resources::TABLE_BASE_DNS_NAME, + Resources::TABLE_DNS_PREFIX, + $endpointSuffix, true ), self::getServiceEndpoint( $scheme, $accountName, - Resources::FILE_BASE_DNS_NAME, + Resources::FILE_DNS_PREFIX, + $endpointSuffix, true ) ); diff --git a/src/Common/Internal/Validate.php b/src/Common/Internal/Validate.php index f7e7362..4517e7d 100644 --- a/src/Common/Internal/Validate.php +++ b/src/Common/Internal/Validate.php @@ -101,7 +101,7 @@ public static function isBoolean($var) */ public static function notNullOrEmpty($var, $name) { - if (is_null($var) || empty($var)) { + if (is_null($var) || (empty($var) && $var != '0')) { throw new \InvalidArgumentException( sprintf(Resources::NULL_OR_EMPTY_MSG, $name) ); @@ -248,6 +248,45 @@ public static function isInstanceOf($objectInstance, $classInstance, $name) } } + /** + * Creates an anonymous function that checks if the given hostname is valid or not. + * + * @return callable + */ + public static function getIsValidHostname() + { + return function ($hostname) { + return Validate::isValidHostname($hostname); + }; + } + + /** + * Throws an exception if the string is not of a valid hostname. + * + * @param string $hostname String to check. + * + * @throws \InvalidArgumentException + * + * @return boolean + */ + public static function isValidHostname($hostname) + { + if (defined('FILTER_VALIDATE_DOMAIN')) { + $isValid = filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME); + } else { + // (less accurate) fallback for PHP < 7.0 + $isValid = preg_match('/^[a-z0-9_-]+(\.[a-z0-9_-]+)*$/i', $hostname); + } + + if ($isValid) { + return true; + } else { + throw new \RuntimeException( + sprintf(Resources::INVALID_CONFIG_HOSTNAME, $hostname) + ); + } + } + /** * Creates a anonymous function that check if the given uri is valid or not. *