<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Authentication
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Internal\Authentication;

use GuzzleHttp\Psr7\Request;
use MicrosoftAzure\Storage\Common\Internal\Http\HttpFormatter;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Utilities;

/**
 * Provides shared key authentication scheme for blob and queue. For more info
 * check: http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Authentication
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class SharedKeyAuthScheme implements IAuthScheme
{
    /**
     * The account name
     */
    protected $accountName;

    /**
     * The account key
     */
    protected $accountKey;

    /**
     * The included headers
     */
    protected $includedHeaders;

    /**
     * Constructor.
     *
     * @param string $accountName storage account name.
     * @param string $accountKey  storage account primary or secondary key.
     *
     * @return SharedKeyAuthScheme
     */
    public function __construct($accountName, $accountKey)
    {
        $this->accountKey  = $accountKey;
        $this->accountName = $accountName;

        $this->includedHeaders   = array();
        $this->includedHeaders[] = Resources::CONTENT_ENCODING;
        $this->includedHeaders[] = Resources::CONTENT_LANGUAGE;
        $this->includedHeaders[] = Resources::CONTENT_LENGTH;
        $this->includedHeaders[] = Resources::CONTENT_MD5;
        $this->includedHeaders[] = Resources::CONTENT_TYPE;
        $this->includedHeaders[] = Resources::DATE;
        $this->includedHeaders[] = Resources::IF_MODIFIED_SINCE;
        $this->includedHeaders[] = Resources::IF_MATCH;
        $this->includedHeaders[] = Resources::IF_NONE_MATCH;
        $this->includedHeaders[] = Resources::IF_UNMODIFIED_SINCE;
        $this->includedHeaders[] = Resources::RANGE;
    }

    /**
     * Computes the authorization signature for blob and queue shared key.
     *
     * @param array  $headers     request headers.
     * @param string $url         reuqest url.
     * @param array  $queryParams query variables.
     * @param string $httpMethod  request http method.
     *
     * @see Blob and Queue Services (Shared Key Authentication) at
     *      http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
     *
     * @return string
     */
    protected function computeSignature(
        array $headers,
        $url,
        array $queryParams,
        $httpMethod
    ) {
        $canonicalizedHeaders = $this->computeCanonicalizedHeaders($headers);

        $canonicalizedResource = $this->computeCanonicalizedResource(
            $url,
            $queryParams
        );

        $stringToSign   = array();
        $stringToSign[] = strtoupper($httpMethod);

        foreach ($this->includedHeaders as $header) {
            $stringToSign[] = Utilities::tryGetValue($headers, $header);
        }

        if (count($canonicalizedHeaders) > 0) {
            $stringToSign[] = implode("\n", $canonicalizedHeaders);
        }

        $stringToSign[] = $canonicalizedResource;
        $stringToSign   = implode("\n", $stringToSign);

        return $stringToSign;
    }

    /**
     * Returns authorization header to be included in the request.
     *
     * @param array  $headers     request headers.
     * @param string $url         reuqest url.
     * @param array  $queryParams query variables.
     * @param string $httpMethod  request http method.
     *
     * @see Specifying the Authorization Header section at
     *      http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
     *
     * @return string
     */
    public function getAuthorizationHeader(
        array $headers,
        $url,
        array $queryParams,
        $httpMethod
    ) {
        $signature = $this->computeSignature(
            $headers,
            $url,
            $queryParams,
            $httpMethod
        );

        return 'SharedKey ' . $this->accountName . ':' . base64_encode(
            hash_hmac('sha256', $signature, base64_decode($this->accountKey), true)
        );
    }

    /**
     * Computes canonicalized headers for headers array.
     *
     * @param array $headers request headers.
     *
     * @see Constructing the Canonicalized Headers String section at
     *      http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
     *
     * @return array
     */
    protected function computeCanonicalizedHeaders($headers)
    {
        $canonicalizedHeaders = array();
        $normalizedHeaders    = array();
        $validPrefix          =  Resources::X_MS_HEADER_PREFIX;

        if (is_null($normalizedHeaders)) {
            return $canonicalizedHeaders;
        }

        foreach ($headers as $header => $value) {
            // Convert header to lower case.
            $header = strtolower($header);

            // Retrieve all headers for the resource that begin with x-ms-,
            // including the x-ms-date header.
            if (Utilities::startsWith($header, $validPrefix)) {
                // Unfold the string by replacing any breaking white space
                // (meaning what splits the headers, which is \r\n) with a single
                // space.
                $value = str_replace("\r\n", ' ', $value);

                // Trim any white space around the colon in the header.
                $value  = ltrim($value);
                $header = rtrim($header);

                $normalizedHeaders[$header] = $value;
            }
        }

        // Sort the headers lexicographically by header name, in ascending order.
        // Note that each header may appear only once in the string.
        ksort($normalizedHeaders);

        foreach ($normalizedHeaders as $key => $value) {
            $canonicalizedHeaders[] = $key . ':' . $value;
        }

        return $canonicalizedHeaders;
    }

    /**
     * Computes canonicalized resources from URL using Table formar
     *
     * @param string $url         request url.
     * @param array  $queryParams request query variables.
     *
     * @see Constructing the Canonicalized Resource String section at
     *      http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
     *
     * @return string
     */
    protected function computeCanonicalizedResourceForTable($url, $queryParams)
    {
        $queryParams = array_change_key_case($queryParams);

        // 1. Beginning with an empty string (""), append a forward slash (/),
        //    followed by the name of the account that owns the accessed resource.
        $canonicalizedResource = '/' . $this->accountName;

        // 2. Append the resource's encoded URI path, without any query parameters.
        $canonicalizedResource .= parse_url($url, PHP_URL_PATH);

        // 3. The query string should include the question mark and the comp
        //    parameter (for example, ?comp=metadata). No other parameters should
        //    be included on the query string.
        if (array_key_exists(Resources::QP_COMP, $queryParams)) {
            $canonicalizedResource .= '?' . Resources::QP_COMP . '=';
            $canonicalizedResource .= $queryParams[Resources::QP_COMP];
        }

        return $canonicalizedResource;
    }

    /**
     * Computes canonicalized resources from URL.
     *
     * @param string $url         request url.
     * @param array  $queryParams request query variables.
     *
     * @see Constructing the Canonicalized Resource String section at
     *      http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
     *
     * @return string
     */
    protected function computeCanonicalizedResource($url, $queryParams)
    {
        $queryParams = array_change_key_case($queryParams);

        // 1. Beginning with an empty string (""), append a forward slash (/),
        //    followed by the name of the account that owns the accessed resource.
        $canonicalizedResource = '/' . $this->accountName;

        // 2. Append the resource's encoded URI path, without any query parameters.
        $canonicalizedResource .= parse_url($url, PHP_URL_PATH);

        // 3. Retrieve all query parameters on the resource URI, including the comp
        //    parameter if it exists.
        // 4. Sort the query parameters lexicographically by parameter name, in
        //    ascending order.
        if (count($queryParams) > 0) {
            ksort($queryParams);
        }

        // 5. Convert all parameter names to lowercase.
        // 6. URL-decode each query parameter name and value.
        // 7. Append each query parameter name and value to the string in the
        //    following format:
        //      parameter-name:parameter-value
        // 9. Group query parameters
        // 10. Append a new line character (\n) after each name-value pair.
        foreach ($queryParams as $key => $value) {
            // $value must already be ordered lexicographically
            // See: ServiceRestProxy::groupQueryValues
            $canonicalizedResource .= "\n" . $key . ':' . $value;
        }

        return $canonicalizedResource;
    }

    /**
     * Adds authentication header to the request headers.
     *
     * @param  \GuzzleHttp\Psr7\Request $request HTTP request object.
     *
     * @abstract
     *
     * @return \GuzzleHttp\Psr7\Request
     */
    public function signRequest(Request $request)
    {
        $requestHeaders = HttpFormatter::formatHeaders($request->getHeaders());

        $signedKey = $this->getAuthorizationHeader(
            $requestHeaders,
            $request->getUri(),
            \GuzzleHttp\Psr7\parse_query(
                $request->getUri()->getQuery()
            ),
            $request->getMethod()
        );

        return $request->withHeader(Resources::AUTHENTICATION, $signedKey);
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Internal;

use MicrosoftAzure\Storage\Common\Models\AccessPolicy;
use MicrosoftAzure\Storage\Common\Models\SignedIdentifier;
use MicrosoftAzure\Storage\Common\Internal\Serialization\XmlSerializer;

/**
 * Provide base class for service ACLs.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
abstract class ACLBase
{
    private $signedIdentifiers = array();
    private $resourceType = '';

    /**
     * Create an AccessPolicy object by resource type.
     *
     * @return AccessPolicy
     */
    abstract protected static function createAccessPolicy();

    /**
     * Validate if the resource type for the class.
     *
     * @param  string $resourceType the resource type to be validated.
     *
     * @throws \InvalidArgumentException
     *
     * @internal
     *
     * @return void
     */
    abstract protected static function validateResourceType($resourceType);

    /**
     * Converts signed identifiers to array representation for XML serialization
     *
     * @internal
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();

        foreach ($this->getSignedIdentifiers() as $value) {
            $array[] = $value->toArray();
        }

        return $array;
    }

    /**
     * Converts this signed identifiers to XML representation.
     *
     * @param  XmlSerializer $xmlSerializer The XML serializer.
     *
     * @internal
     *
     * @return string
     */
    public function toXml(XmlSerializer $serializer)
    {
        $properties = array(
            XmlSerializer::DEFAULT_TAG => Resources::XTAG_SIGNED_IDENTIFIER,
            XmlSerializer::ROOT_NAME   => Resources::XTAG_SIGNED_IDENTIFIERS
        );

        return $serializer->serialize($this->toArray(), $properties);
    }

    /**
     * Construct the signed identifiers from a given parsed XML in array
     * representation.
     *
     * @param array|null  $parsed The parsed XML into array representation.
     *
     * @internal
     *
     * @return void
     */
    public function fromXmlArray(array $parsed = null)
    {
        $this->setSignedIdentifiers(array());

        // Initialize signed identifiers.
        if (!empty($parsed) &&
                is_array($parsed[Resources::XTAG_SIGNED_IDENTIFIER])
        ) {
            $entries = $parsed[Resources::XTAG_SIGNED_IDENTIFIER];
            $temp    = Utilities::getArray($entries);

            foreach ($temp as $value) {
                $accessPolicy = $value[Resources::XTAG_ACCESS_POLICY];
                $startString  = urldecode(
                    $accessPolicy[Resources::XTAG_SIGNED_START]
                );
                $expiryString = urldecode(
                    $accessPolicy[Resources::XTAG_SIGNED_EXPIRY]
                );
                $start        = Utilities::convertToDateTime($startString);
                $expiry       = Utilities::convertToDateTime($expiryString);
                $permission   = $accessPolicy[Resources::XTAG_SIGNED_PERMISSION];
                $id           = $value[Resources::XTAG_SIGNED_ID];
                $this->addSignedIdentifier($id, $start, $expiry, $permission);
            }
        }
    }

    /**
     * Gets the type of resource this ACL relate to.
     *
     * @internal
     *
     * @return string
     */
    protected function getResourceType()
    {
        return $this->resourceType;
    }

    /**
     * Set the type of resource this ACL relate to.
     *
     * @internal
     *
     * @return void
     */
    protected function setResourceType($resourceType)
    {
        static::validateResourceType($resourceType);
        $this->resourceType = $resourceType;
    }

    /**
     * Add a signed identifier to the ACL.
     *
     * @param string    $id          A unique id for this signed identifier.
     * @param \DateTime $start       The time at which the Shared Access
     *                               Signature becomes valid. If omitted, start
     *                               time for this call is assumed to be the
     *                               time when the service receives the
     *                               request.
     * @param \DateTime $expiry      The time at which the Shared Access
     *                               Signature becomes invalid.
     * @param string    $permissions The permissions associated with the Shared
     *                               Access Signature. The user is restricted to
     *                               operations allowed by the permissions.
     *
     * @return void
     *
     * @see https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/establishing-a-stored-access-policy
     */
    public function addSignedIdentifier(
        $id,
        \DateTime $start,
        \DateTime $expiry,
        $permissions
    ) {
        Validate::canCastAsString($id, 'id');
        if ($start != null) {
            Validate::isDate($start);
        }
        Validate::isDate($expiry);
        Validate::canCastAsString($permissions, 'permissions');

        $accessPolicy = static::createAccessPolicy();
        $accessPolicy->setStart($start);
        $accessPolicy->setExpiry($expiry);
        $accessPolicy->setPermission($permissions);

        $signedIdentifier = new SignedIdentifier();
        $signedIdentifier->setId($id);
        $signedIdentifier->setAccessPolicy($accessPolicy);

        // Remove the signed identifier with the same ID.
        $this->removeSignedIdentifier($id);

        // There can be no more than 5 signed identifiers at the same time.
        Validate::isTrue(
            count($this->getSignedIdentifiers()) < 5,
            Resources::ERROR_TOO_MANY_SIGNED_IDENTIFIERS
        );

        $this->signedIdentifiers[] = $signedIdentifier;
    }

    /**
     * Remove the signed identifier with given ID.
     *
     * @param  string $id The ID of the signed identifier to be removed.
     *
     * @return boolean
     */
    public function removeSignedIdentifier($id)
    {
        Validate::canCastAsString($id, 'id');
        //var_dump($this->signedIdentifiers);
        for ($i = 0; $i < count($this->signedIdentifiers); ++$i) {
            if ($this->signedIdentifiers[$i]->getId() == $id) {
                array_splice($this->signedIdentifiers, $i, 1);
                return true;
            }
        }

        return false;
    }

    /**
     * Gets signed identifiers.
     *
     * @return array
     */
    public function getSignedIdentifiers()
    {
        return $this->signedIdentifiers;
    }

    public function setSignedIdentifiers(array $signedIdentifiers)
    {
        // There can be no more than 5 signed identifiers at the same time.
        Validate::isTrue(
            count($signedIdentifiers) <= 5,
            Resources::ERROR_TOO_MANY_SIGNED_IDENTIFIERS
        );
        $this->signedIdentifiers = $signedIdentifiers;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Table\Models;

use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Table\Internal\TableResources as Resources;

/**
 * Holds batch operation change set.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class BatchOperations
{
    private $_operations;

    /**
     * Default constructor.
     */
    public function __construct()
    {
        $this->_operations = array();
    }

    /**
     * Gets the batch operations.
     *
     * @return array
     */
    public function getOperations()
    {
        return $this->_operations;
    }

    /**
     * Sets the batch operations.
     *
     * @param array $operations The batch operations.
     *
     * @return void
     */
    public function setOperations(array $operations)
    {
        $this->_operations = array();
        foreach ($operations as $operation) {
            $this->addOperation($operation);
        }
    }

    /**
     * Adds operation to the batch operations.
     *
     * @param mixed $operation The operation to add.
     *
     * @return void
     */
    public function addOperation($operation)
    {
        Validate::isTrue(
            $operation instanceof BatchOperation,
            Resources::INVALID_BO_TYPE_MSG
        );

        $this->_operations[] = $operation;
    }

    /**
     * Adds insertEntity operation.
     *
     * @param string $table  The table name.
     * @param Entity $entity The entity instance.
     *
     * @return void
     */
    public function addInsertEntity($table, Entity $entity)
    {
        Validate::canCastAsString($table, 'table');
        Validate::notNullOrEmpty($entity, 'entity');

        $operation = new BatchOperation();
        $type      = BatchOperationType::INSERT_ENTITY_OPERATION;
        $operation->setType($type);
        $operation->addParameter(BatchOperationParameterName::BP_TABLE, $table);
        $operation->addParameter(BatchOperationParameterName::BP_ENTITY, $entity);
        $this->addOperation($operation);
    }

    /**
     * Adds updateEntity operation.
     *
     * @param string $table  The table name.
     * @param Entity $entity The entity instance.
     *
     * @return void
     */
    public function addUpdateEntity($table, Entity $entity)
    {
        Validate::canCastAsString($table, 'table');
        Validate::notNullOrEmpty($entity, 'entity');

        $operation = new BatchOperation();
        $type      = BatchOperationType::UPDATE_ENTITY_OPERATION;
        $operation->setType($type);
        $operation->addParameter(BatchOperationParameterName::BP_TABLE, $table);
        $operation->addParameter(BatchOperationParameterName::BP_ENTITY, $entity);
        $this->addOperation($operation);
    }

    /**
     * Adds mergeEntity operation.
     *
     * @param string $table  The table name.
     * @param Entity $entity The entity instance.
     *
     * @return void
     */
    public function addMergeEntity($table, Entity $entity)
    {
        Validate::canCastAsString($table, 'table');
        Validate::notNullOrEmpty($entity, 'entity');

        $operation = new BatchOperation();
        $type      = BatchOperationType::MERGE_ENTITY_OPERATION;
        $operation->setType($type);
        $operation->addParameter(BatchOperationParameterName::BP_TABLE, $table);
        $operation->addParameter(BatchOperationParameterName::BP_ENTITY, $entity);
        $this->addOperation($operation);
    }

    /**
     * Adds insertOrReplaceEntity operation.
     *
     * @param string $table  The table name.
     * @param Entity $entity The entity instance.
     *
     * @return void
     */
    public function addInsertOrReplaceEntity($table, Entity $entity)
    {
        Validate::canCastAsString($table, 'table');
        Validate::notNullOrEmpty($entity, 'entity');

        $operation = new BatchOperation();
        $type      = BatchOperationType::INSERT_REPLACE_ENTITY_OPERATION;
        $operation->setType($type);
        $operation->addParameter(BatchOperationParameterName::BP_TABLE, $table);
        $operation->addParameter(BatchOperationParameterName::BP_ENTITY, $entity);
        $this->addOperation($operation);
    }

    /**
     * Adds insertOrMergeEntity operation.
     *
     * @param string $table  The table name.
     * @param Entity $entity The entity instance.
     *
     * @return void
     */
    public function addInsertOrMergeEntity($table, Entity $entity)
    {
        Validate::canCastAsString($table, 'table');
        Validate::notNullOrEmpty($entity, 'entity');

        $operation = new BatchOperation();
        $type      = BatchOperationType::INSERT_MERGE_ENTITY_OPERATION;
        $operation->setType($type);
        $operation->addParameter(BatchOperationParameterName::BP_TABLE, $table);
        $operation->addParameter(BatchOperationParameterName::BP_ENTITY, $entity);
        $this->addOperation($operation);
    }

    /**
     * Adds deleteEntity operation.
     *
     * @param string $table        The table name.
     * @param string $partitionKey The entity partition key.
     * @param string $rowKey       The entity row key.
     * @param string $etag         The entity etag.
     *
     * @return void
     */
    public function addDeleteEntity($table, $partitionKey, $rowKey, $etag = null)
    {
        Validate::canCastAsString($table, 'table');
        Validate::isTrue(!is_null($partitionKey), Resources::NULL_TABLE_KEY_MSG);
        Validate::isTrue(!is_null($rowKey), Resources::NULL_TABLE_KEY_MSG);

        $operation = new BatchOperation();
        $type      = BatchOperationType::DELETE_ENTITY_OPERATION;
        $operation->setType($type);
        $operation->addParameter(BatchOperationParameterName::BP_TABLE, $table);
        $operation->addParameter(BatchOperationParameterName::BP_ROW_KEY, $rowKey);
        $operation->addParameter(BatchOperationParameterName::BP_ETAG, $etag);
        $operation->addParameter(
            BatchOperationParameterName::BP_PARTITION_KEY,
            $partitionKey
        );
        $this->addOperation($operation);
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\File\Models;

use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\File\Internal\FileResources as Resources;

/**
 * Holds result of calling CopyFileResult wrapper
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class CopyFileResult
{
    private $lastModified;
    private $etag;
    private $copyID;
    private $copyStatus;

    /**
     * Creates CopyFileResult object from parsed response header.
     *
     * @param array $headers HTTP response headers
     *
     * @internal
     *
     * @return CopyFileResult
     */
    public static function create(array $headers)
    {
        $result  = new CopyFileResult();
        $headers = array_change_key_case($headers);

        $date          = $headers[Resources::LAST_MODIFIED];
        $date          = Utilities::rfc1123ToDateTime($date);

        $result->setCopyStatus($headers[Resources::X_MS_COPY_STATUS]);
        $result->setCopyID($headers[Resources::X_MS_COPY_ID]);
        $result->setETag($headers[Resources::ETAG]);
        $result->setLastModified($date);

        return $result;
    }

    /**
     * Gets file lastModified.
     *
     * @return \DateTime
     */
    public function getLastModified()
    {
        return $this->lastModified;
    }

    /**
     * Sets file lastModified.
     *
     * @param \DateTime $lastModified value.
     *
     * @return void
     */
    protected function setLastModified(\DateTime $lastModified)
    {
        Validate::isDate($lastModified);
        $this->lastModified = $lastModified;
    }

    /**
     * Gets file etag.
     *
     * @return string
     */
    public function getETag()
    {
        return $this->etag;
    }

    /**
     * Sets file etag.
     *
     * @param string $etag value.
     *
     * @return void
     */
    protected function setETag($etag)
    {
        Validate::canCastAsString($etag, 'etag');
        $this->etag = $etag;
    }

    /**
     * Gets file copyID.
     *
     * @return string
     */
    public function getCopyID()
    {
        return $this->copyID;
    }

    /**
     * Sets file copyID.
     *
     * @param string $copyID value.
     *
     * @return void
     */
    protected function setCopyID($copyID)
    {
        Validate::canCastAsString($copyID, 'copyID');
        $this->copyID = $copyID;
    }

    /**
     * Gets copyStatus
     *
     * @return string
     */
    public function getCopyStatus()
    {
        return $this->copyStatus;
    }

    /**
     * Sets copyStatus
     *
     * @param string $copyStatus copyStatus to set
     *
     * @return void
     */
    protected function setCopyStatus($copyStatus)
    {
        Validate::canCastAsString($copyStatus, 'copyStatus');
        $this->copyStatus = $copyStatus;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Queue\Models;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Common\Internal\Serialization\XmlSerializer;

/**
 * Holds data for single queue message.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class QueueMessage
{
    private $messageId;
    private $insertionDate;
    private $expirationDate;
    private $popReceipt;
    private $timeNextVisible;
    private $dequeueCount;
    private $_messageText;
    private static $xmlRootName = 'QueueMessage';

    /**
     * Creates QueueMessage object from parsed XML response of
     * ListMessages.
     *
     * @param array $parsedResponse XML response parsed into array.
     *
     * @internal
     *
     * @return QueueMessage
     */
    public static function createFromListMessages(array $parsedResponse)
    {
        $timeNextVisible = $parsedResponse['TimeNextVisible'];

        $msg  = self::createFromPeekMessages($parsedResponse);
        $date = Utilities::rfc1123ToDateTime($timeNextVisible);
        $msg->setTimeNextVisible($date);
        $msg->setPopReceipt($parsedResponse['PopReceipt']);

        return $msg;
    }

    /**
     * Creates QueueMessage object from parsed XML response of
     * PeekMessages.
     *
     * @param array $parsedResponse XML response parsed into array.
     *
     * @internal
     *
     * @return QueueMessage
     */
    public static function createFromPeekMessages(array $parsedResponse)
    {
        $msg            = new QueueMessage();
        $expirationDate = $parsedResponse['ExpirationTime'];
        $insertionDate  = $parsedResponse['InsertionTime'];

        $msg->setDequeueCount(intval($parsedResponse['DequeueCount']));

        $date = Utilities::rfc1123ToDateTime($expirationDate);
        $msg->setExpirationDate($date);

        $date = Utilities::rfc1123ToDateTime($insertionDate);
        $msg->setInsertionDate($date);

        $msg->setMessageId($parsedResponse['MessageId']);
        $msg->setMessageText($parsedResponse['MessageText']);

        return $msg;
    }

    /**
     * Creates QueueMessage object from parsed XML response of
     * createMessage.
     *
     * @param array $parsedResponse XML response parsed into array.
     *
     * @internal
     *
     * @return QueueMessage
     */
    public static function createFromCreateMessage(array $parsedResponse)
    {
        $msg = new QueueMessage();

        $expirationDate  = $parsedResponse['ExpirationTime'];
        $insertionDate   = $parsedResponse['InsertionTime'];
        $timeNextVisible = $parsedResponse['TimeNextVisible'];

        $date = Utilities::rfc1123ToDateTime($expirationDate);
        $msg->setExpirationDate($date);

        $date = Utilities::rfc1123ToDateTime($insertionDate);
        $msg->setInsertionDate($date);

        $date = Utilities::rfc1123ToDateTime($timeNextVisible);
        $msg->setTimeNextVisible($date);

        $msg->setMessageId($parsedResponse['MessageId']);
        $msg->setPopReceipt($parsedResponse['PopReceipt']);

        return $msg;
    }

    /**
     * Gets message text field.
     *
     * @return string
     */
    public function getMessageText()
    {
        return $this->_messageText;
    }

    /**
     * Sets message text field.
     *
     * @param string $messageText message contents.
     *
     * @return void
     */
    public function setMessageText($messageText)
    {
        $this->_messageText = $messageText;
    }

    /**
     * Gets messageId field.
     *
     * @return string
     */
    public function getMessageId()
    {
        return $this->messageId;
    }

    /**
     * Sets messageId field.
     *
     * @param string $messageId message contents.
     *
     * @return void
     */
    public function setMessageId($messageId)
    {
        $this->messageId = $messageId;
    }

    /**
     * Gets insertionDate field.
     *
     * @return \DateTime
     */
    public function getInsertionDate()
    {
        return $this->insertionDate;
    }

    /**
     * Sets insertionDate field.
     *
     * @param \DateTime $insertionDate message contents.
     *
     * @internal
     *
     * @return void
     */
    public function setInsertionDate(\DateTime $insertionDate)
    {
        $this->insertionDate = $insertionDate;
    }

    /**
     * Gets expirationDate field.
     *
     * @return \DateTime
     */
    public function getExpirationDate()
    {
        return $this->expirationDate;
    }

    /**
     * Sets expirationDate field.
     *
     * @param \DateTime $expirationDate the expiration date of the message.
     *
     * @return void
     */
    public function setExpirationDate(\DateTime $expirationDate)
    {
        $this->expirationDate = $expirationDate;
    }

    /**
     * Gets timeNextVisible field.
     *
     * @return \DateTime
     */
    public function getTimeNextVisible()
    {
        return $this->timeNextVisible;
    }

    /**
     * Sets timeNextVisible field.
     *
     * @param \DateTime $timeNextVisible next visibile time for the message.
     *
     * @return void
     */
    public function setTimeNextVisible($timeNextVisible)
    {
        $this->timeNextVisible = $timeNextVisible;
    }

    /**
     * Gets popReceipt field.
     *
     * @return string
     */
    public function getPopReceipt()
    {
        return $this->popReceipt;
    }

    /**
     * Sets popReceipt field.
     *
     * @param string $popReceipt used when deleting the message.
     *
     * @return void
     */
    public function setPopReceipt($popReceipt)
    {
        $this->popReceipt = $popReceipt;
    }

    /**
     * Gets dequeueCount field.
     *
     * @return integer
     */
    public function getDequeueCount()
    {
        return $this->dequeueCount;
    }

    /**
     * Sets dequeueCount field.
     *
     * @param integer $dequeueCount number of dequeues for that message.
     *
     * @internal
     *
     * @return void
     */
    public function setDequeueCount($dequeueCount)
    {
        $this->dequeueCount = $dequeueCount;
    }

    /**
     * Converts this current object to XML representation.
     *
     * @param XmlSerializer $xmlSerializer The XML serializer.
     *
     * @internal
     *
     * @return string
     */
    public function toXml(XmlSerializer $xmlSerializer)
    {
        $array      = array('MessageText' => $this->_messageText);
        $properties = array(XmlSerializer::ROOT_NAME => self::$xmlRootName);

        return $xmlSerializer->serialize($array, $properties);
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Internal;

/**
 * Represents the settings used to sign and access a request against the storage
 * service. For more information about storage service connection strings check this
 * page: http://msdn.microsoft.com/en-us/library/ee758697
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class StorageServiceSettings extends ServiceSettings
{
    private $name;
    private $key;
    private $sas;
    private $blobEndpointUri;
    private $queueEndpointUri;
    private $tableEndpointUri;
    private $fileEndpointUri;
    private $blobSecondaryEndpointUri;
    private $queueSecondaryEndpointUri;
    private $tableSecondaryEndpointUri;
    private $fileSecondaryEndpointUri;

    private static $devStoreAccount;
    private static $useDevelopmentStorageSetting;
    private static $developmentStorageProxyUriSetting;
    private static $defaultEndpointsProtocolSetting;
    private static $accountNameSetting;
    private static $accountKeySetting;
    private static $sasTokenSetting;
    private static $blobEndpointSetting;
    private static $queueEndpointSetting;
    private static $tableEndpointSetting;
    private static $fileEndpointSetting;
    private static $endpointSuffixSetting;

    /**
     * If initialized or not
     * @internal
     */
    protected static $isInitialized = false;

    /**
     * Valid setting keys
     * @internal
     */
    protected static $validSettingKeys = array();

    /**
     * Initializes static members of the class.
     *
     * @return void
     */
    protected static function init()
    {
        self::$useDevelopmentStorageSetting = self::setting(
            Resources::USE_DEVELOPMENT_STORAGE_NAME,
            'true'
        );

        self::$developmentStorageProxyUriSetting = self::settingWithFunc(
            Resources::DEVELOPMENT_STORAGE_PROXY_URI_NAME,
            Validate::getIsValidUri()
        );

        self::$defaultEndpointsProtocolSetting = self::setting(
            Resources::DEFAULT_ENDPOINTS_PROTOCOL_NAME,
            'http',
            'https'
        );

        self::$accountNameSetting = self::setting(Resources::ACCOUNT_NAME_NAME);

        self::$accountKeySetting = self::settingWithFunc(
            Resources::ACCOUNT_KEY_NAME,
            // base64_decode will return false if the $key is not in base64 format.
            function ($key) {
                $isValidBase64String = base64_decode($key, true);
                if ($isValidBase64String) {
                    return true;
                } else {
                    throw new \RuntimeException(
                        sprintf(Resources::INVALID_ACCOUNT_KEY_FORMAT, $key)
                    );
                }
            }
        );

        self::$sasTokenSetting = self::setting(Resources::SAS_TOKEN_NAME);

        self::$blobEndpointSetting = self::settingWithFunc(
            Resources::BLOB_ENDPOINT_NAME,
            Validate::getIsValidUri()
        );

        self::$queueEndpointSetting = self::settingWithFunc(
            Resources::QUEUE_ENDPOINT_NAME,
            Validate::getIsValidUri()
        );

        self::$tableEndpointSetting = self::settingWithFunc(
            Resources::TABLE_ENDPOINT_NAME,
            Validate::getIsValidUri()
        );

        self::$fileEndpointSetting = self::settingWithFunc(
            Resources::FILE_ENDPOINT_NAME,
            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;
        self::$validSettingKeys[] = Resources::ACCOUNT_NAME_NAME;
        self::$validSettingKeys[] = Resources::ACCOUNT_KEY_NAME;
        self::$validSettingKeys[] = Resources::SAS_TOKEN_NAME;
        self::$validSettingKeys[] = Resources::BLOB_ENDPOINT_NAME;
        self::$validSettingKeys[] = Resources::QUEUE_ENDPOINT_NAME;
        self::$validSettingKeys[] = Resources::TABLE_ENDPOINT_NAME;
        self::$validSettingKeys[] = Resources::FILE_ENDPOINT_NAME;
        self::$validSettingKeys[] = Resources::ENDPOINT_SUFFIX_NAME;
    }

    /**
     * Creates new storage service settings instance.
     *
     * @param string $name                      The storage service name.
     * @param string $key                       The storage service key.
     * @param string $blobEndpointUri           The storage service blob
     *                                          endpoint.
     * @param string $queueEndpointUri          The storage service queue
     *                                          endpoint.
     * @param string $tableEndpointUri          The storage service table
     *                                          endpoint.
     * @param string $fileEndpointUri           The storage service file
     *                                          endpoint.
     * @param string $blobSecondaryEndpointUri  The storage service secondary
     *                                          blob endpoint.
     * @param string $queueSecondaryEndpointUri The storage service secondary
     *                                          queue endpoint.
     * @param string $tableSecondaryEndpointUri The storage service secondary
     *                                          table endpoint.
     * @param string $fileSecondaryEndpointUri  The storage service secondary
     *                                          file endpoint.
     * @param string $sas                       The storage service SAS token.
     */
    public function __construct(
        $name,
        $key,
        $blobEndpointUri,
        $queueEndpointUri,
        $tableEndpointUri,
        $fileEndpointUri,
        $blobSecondaryEndpointUri = null,
        $queueSecondaryEndpointUri = null,
        $tableSecondaryEndpointUri = null,
        $fileSecondaryEndpointUri = null,
        $sas = null
    ) {
        $this->name                      = $name;
        $this->key                       = $key;
        $this->sas                       = $sas;
        $this->blobEndpointUri           = $blobEndpointUri;
        $this->queueEndpointUri          = $queueEndpointUri;
        $this->tableEndpointUri          = $tableEndpointUri;
        $this->fileEndpointUri           = $fileEndpointUri;
        $this->blobSecondaryEndpointUri  = $blobSecondaryEndpointUri;
        $this->queueSecondaryEndpointUri = $queueSecondaryEndpointUri;
        $this->tableSecondaryEndpointUri = $tableSecondaryEndpointUri;
        $this->fileSecondaryEndpointUri  = $fileSecondaryEndpointUri;
    }

    /**
     * Returns a StorageServiceSettings with development storage credentials using
     * the specified proxy Uri.
     *
     * @param string $proxyUri The proxy endpoint to use.
     *
     * @return StorageServiceSettings
     */
    private static function getDevelopmentStorageAccount($proxyUri)
    {
        if (is_null($proxyUri)) {
            return self::developmentStorageAccount();
        }

        $scheme = parse_url($proxyUri, PHP_URL_SCHEME);
        $host   = parse_url($proxyUri, PHP_URL_HOST);
        $prefix = $scheme . "://" . $host;

        return new StorageServiceSettings(
            Resources::DEV_STORE_NAME,
            Resources::DEV_STORE_KEY,
            $prefix . ':10000/devstoreaccount1/',
            $prefix . ':10001/devstoreaccount1/',
            $prefix . ':10002/devstoreaccount1/',
            null
        );
    }

    /**
     * Gets a StorageServiceSettings object that references the development storage
     * account.
     *
     * @return StorageServiceSettings
     */
    public static function developmentStorageAccount()
    {
        if (is_null(self::$devStoreAccount)) {
            self::$devStoreAccount = self::getDevelopmentStorageAccount(
                Resources::DEV_STORE_URI
            );
        }

        return self::$devStoreAccount;
    }

    /**
     * Gets the default service endpoint using the specified protocol and account
     * name.
     *
     * @param string $scheme      The scheme of the service end point.
     * @param string $accountName The account name of the service.
     * @param string $dnsPrefix   The service DNS prefix.
     * @param string $dnsSuffix   The service DNS suffix.
     * @param bool   $isSecondary If generating secondary endpoint.
     *
     * @return string
     */
    private static function getServiceEndpoint(
        $scheme,
        $accountName,
        $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,
            $dnsPrefix.$dnsSuffix
        );
    }

    /**
     * Creates StorageServiceSettings object given endpoints uri.
     *
     * @param array  $settings                  The service settings.
     * @param string $blobEndpointUri           The blob endpoint uri.
     * @param string $queueEndpointUri          The queue endpoint uri.
     * @param string $tableEndpointUri          The table endpoint uri.
     * @param string $fileEndpointUri           The file endpoint uri.
     * @param string $blobSecondaryEndpointUri  The blob secondary endpoint uri.
     * @param string $queueSecondaryEndpointUri The queue secondary endpoint uri.
     * @param string $tableSecondaryEndpointUri The table secondary endpoint uri.
     * @param string $fileSecondaryEndpointUri  The file secondary endpoint uri.
     *
     * @return StorageServiceSettings
     */
    private static function createStorageServiceSettings(
        array $settings,
        $blobEndpointUri = null,
        $queueEndpointUri = null,
        $tableEndpointUri = null,
        $fileEndpointUri = null,
        $blobSecondaryEndpointUri = null,
        $queueSecondaryEndpointUri = null,
        $tableSecondaryEndpointUri = null,
        $fileSecondaryEndpointUri = null
    ) {
        $blobEndpointUri  = Utilities::tryGetValueInsensitive(
            Resources::BLOB_ENDPOINT_NAME,
            $settings,
            $blobEndpointUri
        );
        $queueEndpointUri = Utilities::tryGetValueInsensitive(
            Resources::QUEUE_ENDPOINT_NAME,
            $settings,
            $queueEndpointUri
        );
        $tableEndpointUri = Utilities::tryGetValueInsensitive(
            Resources::TABLE_ENDPOINT_NAME,
            $settings,
            $tableEndpointUri
        );
        $fileEndpointUri = Utilities::tryGetValueInsensitive(
            Resources::FILE_ENDPOINT_NAME,
            $settings,
            $fileEndpointUri
        );
        $accountName      = Utilities::tryGetValueInsensitive(
            Resources::ACCOUNT_NAME_NAME,
            $settings
        );
        $accountKey       = Utilities::tryGetValueInsensitive(
            Resources::ACCOUNT_KEY_NAME,
            $settings
        );
        $sasToken         = Utilities::tryGetValueInsensitive(
            Resources::SAS_TOKEN_NAME,
            $settings
        );

        return new StorageServiceSettings(
            $accountName,
            $accountKey,
            $blobEndpointUri,
            $queueEndpointUri,
            $tableEndpointUri,
            $fileEndpointUri,
            $blobSecondaryEndpointUri,
            $queueSecondaryEndpointUri,
            $tableSecondaryEndpointUri,
            $fileSecondaryEndpointUri,
            $sasToken
        );
    }

    /**
     * Creates a StorageServiceSettings object from the given connection string.
     *
     * @param string $connectionString The storage settings connection string.
     *
     * @return StorageServiceSettings
     */
    public static function createFromConnectionString($connectionString)
    {
        $tokenizedSettings = self::parseAndValidateKeys($connectionString);

        // Devstore case
        $matchedSpecs = self::matchedSpecification(
            $tokenizedSettings,
            self::allRequired(self::$useDevelopmentStorageSetting),
            self::optional(self::$developmentStorageProxyUriSetting)
        );
        if ($matchedSpecs) {
            $proxyUri = Utilities::tryGetValueInsensitive(
                Resources::DEVELOPMENT_STORAGE_PROXY_URI_NAME,
                $tokenizedSettings
            );

            return self::getDevelopmentStorageAccount($proxyUri);
        }

        // Automatic case
        $matchedSpecs = self::matchedSpecification(
            $tokenizedSettings,
            self::allRequired(
                self::$defaultEndpointsProtocolSetting,
                self::$accountNameSetting,
                self::$accountKeySetting
            ),
            self::optional(
                self::$blobEndpointSetting,
                self::$queueEndpointSetting,
                self::$tableEndpointSetting,
                self::$fileEndpointSetting,
                self::$endpointSuffixSetting
            )
        );
        if ($matchedSpecs) {
            $scheme         = Utilities::tryGetValueInsensitive(
                Resources::DEFAULT_ENDPOINTS_PROTOCOL_NAME,
                $tokenizedSettings
            );
            $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_DNS_PREFIX,
                    $endpointSuffix
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::QUEUE_DNS_PREFIX,
                    $endpointSuffix
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::TABLE_DNS_PREFIX,
                    $endpointSuffix
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::FILE_DNS_PREFIX,
                    $endpointSuffix
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::BLOB_DNS_PREFIX,
                    $endpointSuffix,
                    true
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::QUEUE_DNS_PREFIX,
                    $endpointSuffix,
                    true
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::TABLE_DNS_PREFIX,
                    $endpointSuffix,
                    true
                ),
                self::getServiceEndpoint(
                    $scheme,
                    $accountName,
                    Resources::FILE_DNS_PREFIX,
                    $endpointSuffix,
                    true
                )
            );
        }

        // Explicit case for AccountName/AccountKey combination
        $matchedSpecs = self::matchedSpecification(
            $tokenizedSettings,
            self::atLeastOne(
                self::$blobEndpointSetting,
                self::$queueEndpointSetting,
                self::$tableEndpointSetting,
                self::$fileEndpointSetting
            ),
            self::allRequired(
                self::$accountNameSetting,
                self::$accountKeySetting
            )
        );
        if ($matchedSpecs) {
            return self::createStorageServiceSettings($tokenizedSettings);
        }

        // Explicit case for SAS token
        $matchedSpecs = self::matchedSpecification(
            $tokenizedSettings,
            self::atLeastOne(
                self::$blobEndpointSetting,
                self::$queueEndpointSetting,
                self::$tableEndpointSetting,
                self::$fileEndpointSetting
            ),
            self::allRequired(
                self::$sasTokenSetting
            )
        );
        if ($matchedSpecs) {
            return self::createStorageServiceSettings($tokenizedSettings);
        }

        self::noMatch($connectionString);
    }

    /**
     * Creates a StorageServiceSettings object from the given connection string.
     * Note this is only for AAD connection string, it should at least contain
     * the account name.
     *
     * @param string $connectionString The storage settings connection string.
     *
     * @return StorageServiceSettings
     */
    public static function createFromConnectionStringForTokenCredential($connectionString)
    {
        // Explicit case for AAD token, Connection string could only have account
        // name.
        $tokenizedSettings = self::parseAndValidateKeys($connectionString);

        $scheme         = Utilities::tryGetValueInsensitive(
            Resources::DEFAULT_ENDPOINTS_PROTOCOL_NAME,
            $tokenizedSettings
        );
        $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_DNS_PREFIX,
                $endpointSuffix
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::QUEUE_DNS_PREFIX,
                $endpointSuffix
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::TABLE_DNS_PREFIX,
                $endpointSuffix
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::FILE_DNS_PREFIX,
                $endpointSuffix
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::BLOB_DNS_PREFIX,
                $endpointSuffix,
                true
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::QUEUE_DNS_PREFIX,
                $endpointSuffix,
                true
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::TABLE_DNS_PREFIX,
                $endpointSuffix,
                true
            ),
            self::getServiceEndpoint(
                $scheme,
                $accountName,
                Resources::FILE_DNS_PREFIX,
                $endpointSuffix,
                true
            )
        );
    }

    /**
     * Gets storage service name.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Gets storage service key.
     *
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * Checks if there is a SAS token.
     *
     * @return boolean
     */
    public function hasSasToken()
    {
        return !empty($this->sas);
    }

    /**
     * Gets storage service SAS token.
     *
     * @return string
     */
    public function getSasToken()
    {
        return $this->sas;
    }

    /**
     * Gets storage service blob endpoint uri.
     *
     * @return string
     */
    public function getBlobEndpointUri()
    {
        return $this->blobEndpointUri;
    }

    /**
     * Gets storage service queue endpoint uri.
     *
     * @return string
     */
    public function getQueueEndpointUri()
    {
        return $this->queueEndpointUri;
    }

    /**
     * Gets storage service table endpoint uri.
     *
     * @return string
     */
    public function getTableEndpointUri()
    {
        return $this->tableEndpointUri;
    }

    /**
     * Gets storage service file endpoint uri.
     *
     * @return string
     */
    public function getFileEndpointUri()
    {
        return $this->fileEndpointUri;
    }

    /**
     * Gets storage service secondary blob endpoint uri.
     *
     * @return string
     */
    public function getBlobSecondaryEndpointUri()
    {
        return $this->blobSecondaryEndpointUri;
    }

    /**
     * Gets storage service secondary queue endpoint uri.
     *
     * @return string
     */
    public function getQueueSecondaryEndpointUri()
    {
        return $this->queueSecondaryEndpointUri;
    }

    /**
     * Gets storage service secondary table endpoint uri.
     *
     * @return string
     */
    public function getTableSecondaryEndpointUri()
    {
        return $this->tableSecondaryEndpointUri;
    }

    /**
     * Gets storage service secondary file endpoint uri.
     *
     * @return string
     */
    public function getFileSecondaryEndpointUri()
    {
        return $this->fileSecondaryEndpointUri;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Table\Internal;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Table\Internal\TableResources as Resources;

/**
 * Reads and writes MIME for batch API.
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class MimeReaderWriter implements IMimeReaderWriter
{
    /**
     * Given array of MIME parts in raw string, this function converts them into MIME
     * representation.
     *
     * @param array $bodyPartContents The MIME body parts.
     *
     * @return array Returns array with two elements 'headers' and 'body' which
     * represents the MIME message.
     */
    public function encodeMimeMultipart(array $bodyPartContents)
    {
        $count         = count($bodyPartContents);
        $mimeType      = Resources::MULTIPART_MIXED_TYPE;
        $batchGuid     = Utilities::getGuid();
        $batchId       = sprintf('batch_%s', $batchGuid);
        $contentType1  = array('content_type' => "$mimeType");
        $changeSetGuid = Utilities::getGuid();
        $changeSetId   = sprintf('changeset_%s', $changeSetGuid);
        $contentType2  = array('content_type' => "$mimeType; boundary=$changeSetId");
        $options       = array(
            'encoding'     => 'binary',
            'content_type' => Resources::HTTP_TYPE
        );

        $eof = "\r\n";

        $result            = array();
        $result['body']    = Resources::EMPTY_STRING;
        $result['headers'] = array();

        $batchBody         =& $result['body'];
        $batchHeaders      =& $result['headers'];

        $batchHeaders['Content-Type'] = $mimeType . "; $eof boundary=\"$batchId\"";

        $batchBody .= "--" . $batchId . $eof;
        $batchBody .= "Content-Type: $mimeType; boundary=\"$changeSetId\"" . $eof;

        $batchBody .= $eof;
        for ($i = 0; $i < count($bodyPartContents); $i++) {
            $batchBody .= "--" . $changeSetId . $eof;

            $batchBody .= "Content-Transfer-Encoding: binary" . $eof;
            $batchBody .= "Content-Type: " . Resources::HTTP_TYPE . $eof;

            $batchBody .= $eof . $bodyPartContents[$i] . $eof;
        }
        $batchBody .= "--" . $changeSetId . "--" . $eof;
        $batchBody .= $eof;
        $batchBody .= "--" . $batchId . "--" . $eof;

        return $result;
    }

    /**
     * Parses given mime HTTP response body into array. Each array element
     * represents a change set result.
     *
     * @param string $mimeBody The raw MIME body result.
     *
     * @return array
     */
    public function decodeMimeMultipart($mimeBody)
    {
        // Find boundary
        $boundaryRegex = '~boundary=(changesetresponse_.*)~';
        preg_match($boundaryRegex, $mimeBody, $matches);

        $boundary = trim($matches[1]);

        // Split the requests
        $requests = explode('--' . $boundary, $mimeBody);

        // Get the body of each request
        $result = array();

        // The first and last element are not request
        for ($i = 1; $i < count($requests) - 1; $i++) {
            // Split the request header and body
            preg_match("/^.*?\r?\n\r?\n(.*)/s", $requests[$i], $matches);
            $result[] = $matches[1];
        }

        return $result;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\File\Models;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Common\Models\MarkerContinuationToken;
use MicrosoftAzure\Storage\Common\MarkerContinuationTokenTrait;
use MicrosoftAzure\Storage\File\Internal\FileResources as Resources;

/**
 * Share to hold list Share response object.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ListSharesResult
{
    use MarkerContinuationTokenTrait;

    private $shares;
    private $prefix;
    private $marker;
    private $maxResults;
    private $accountName;

    /**
     * Creates ListSharesResult object from parsed XML response.
     *
     * @param array  $parsedResponse XML response parsed into array.
     * @param string $location       Contains the location for the previous
     *                               request.
     *
     * @internal
     *
     * @return ListSharesResult
     */
    public static function create(array $parsedResponse, $location = '')
    {
        $result               = new ListSharesResult();
        $serviceEndpoint      = Utilities::tryGetKeysChainValue(
            $parsedResponse,
            Resources::XTAG_ATTRIBUTES,
            Resources::XTAG_SERVICE_ENDPOINT
        );
        $result->setAccountName(Utilities::tryParseAccountNameFromUrl(
            $serviceEndpoint
        ));
        $result->setPrefix(Utilities::tryGetValue(
            $parsedResponse,
            Resources::QP_PREFIX
        ));
        $result->setMarker(Utilities::tryGetValue(
            $parsedResponse,
            Resources::QP_MARKER
        ));

        $nextMarker = Utilities::tryGetValue(
            $parsedResponse,
            Resources::QP_NEXT_MARKER
        );

        if ($nextMarker != null) {
            $result->setContinuationToken(
                new MarkerContinuationToken(
                    $nextMarker,
                    $location
                )
            );
        }

        $result->setMaxResults(Utilities::tryGetValue(
            $parsedResponse,
            Resources::QP_MAX_RESULTS
        ));
        $shares = array();
        $shareArrays = array();

        if (!empty($parsedResponse[Resources::QP_SHARES])) {
            $array = $parsedResponse[Resources::QP_SHARES][Resources::QP_SHARE];
            $shareArrays    = Utilities::getArray($array);
        }

        foreach ($shareArrays as $shareArray) {
            $shares[] = Share::create($shareArray);
        }

        $result->setShares($shares);
        return $result;
    }

    /**
     * Sets shares.
     *
     * @param array $shares list of shares.
     *
     * @return void
     */
    protected function setShares(array $shares)
    {
        $this->shares = array();
        foreach ($shares as $share) {
            $this->shares[] = clone $share;
        }
    }

    /**
     * Gets shares.
     *
     * @return Share[]
     */
    public function getShares()
    {
        return $this->shares;
    }

    /**
     * Gets prefix.
     *
     * @return string
     */
    public function getPrefix()
    {
        return $this->prefix;
    }

    /**
     * Sets prefix.
     *
     * @param string $prefix value.
     *
     * @return void
     */
    protected function setPrefix($prefix)
    {
        $this->prefix = $prefix;
    }

    /**
     * Gets marker.
     *
     * @return string
     */
    public function getMarker()
    {
        return $this->marker;
    }

    /**
     * Sets marker.
     *
     * @param string $marker value.
     *
     * @return void
     */
    protected function setMarker($marker)
    {
        $this->marker = $marker;
    }

    /**
     * Gets max results.
     *
     * @return string
     */
    public function getMaxResults()
    {
        return $this->maxResults;
    }

    /**
     * Sets max results.
     *
     * @param string $maxResults value.
     *
     * @return void
     */
    protected function setMaxResults($maxResults)
    {
        $this->maxResults = $maxResults;
    }

    /**
     * Gets account name.
     *
     * @return string
     */
    public function getAccountName()
    {
        return $this->accountName;
    }

    /**
     * Sets account name.
     *
     * @param string $accountName value.
     *
     * @return void
     */
    protected function setAccountName($accountName)
    {
        $this->accountName = $accountName;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Middlewares
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Middlewares;

use MicrosoftAzure\Storage\Common\LocationMode;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Utilities;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\Promise\RejectedPromise;

/**
 * This class provides the functionality of a middleware that handles all the
 * retry logic for the request.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Middlewares
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class RetryMiddleware extends MiddlewareBase
{
    private $intervalCalculator;
    private $decider;

    public function __construct(
        callable $intervalCalculator,
        callable $decider
    ) {
        $this->intervalCalculator = $intervalCalculator;
        $this->decider            = $decider;
    }

    /**
     * This function will be invoked after the request is sent, if
     * the promise is fulfilled.
     *
     * @param  RequestInterface $request the request sent.
     * @param  array            $options the options that the request sent with.
     *
     * @return callable
     */
    protected function onFulfilled(RequestInterface $request, array $options)
    {
        return function (ResponseInterface $response) use ($request, $options) {
            $isSecondary = Utilities::requestSentToSecondary($request, $options);
            if (!isset($options['retries'])) {
                $options['retries'] = 0;
            }
            if (call_user_func(
                $this->decider,
                $options['retries'],
                $request,
                $response,
                null,
                $isSecondary
            )) {
                return $this->retry($request, $options, $response);
            }
            //Add the header that indicates the endpoint to be used if
            //continuation token is used for subsequent request.
            if ($isSecondary) {
                $response = $response->withHeader(
                    Resources::X_MS_CONTINUATION_LOCATION_MODE,
                    LocationMode::SECONDARY_ONLY
                );
            } else {
                $response = $response->withHeader(
                    Resources::X_MS_CONTINUATION_LOCATION_MODE,
                    LocationMode::PRIMARY_ONLY
                );
            }
            return $response;
        };
    }

    /**
     * This function will be executed after the request is sent, if
     * the promise is rejected.
     *
     * @param  RequestInterface $request the request sent.
     * @param  array            $options the options that the request sent with.
     *
     * @return callable
     */
    protected function onRejected(RequestInterface $request, array $options)
    {
        return function ($reason) use ($request, $options) {
            $isSecondary = Utilities::requestSentToSecondary($request, $options);
            if (!isset($options['retries'])) {
                $options['retries'] = 0;
            }

            if (call_user_func(
                $this->decider,
                $options['retries'],
                $request,
                null,
                $reason,
                $isSecondary
            )) {
                return $this->retry($request, $options);
            }
            return new RejectedPromise($reason);
        };
    }

    /**
     * This function does the real retry job.
     *
     * @param  RequestInterface  $request  the request sent.
     * @param  array             $options  the options that the request sent with.
     * @param  ResponseInterface $response the response of the request
     *
     * @return callable
     */
    private function retry(
        RequestInterface $request,
        array $options,
        ResponseInterface $response = null
    ) {
        $options['delay'] = call_user_func(
            $this->intervalCalculator,
            ++$options['retries']
        );

        //Change the request URI according to the location mode.
        if (array_key_exists(Resources::ROS_LOCATION_MODE, $options)) {
            $locationMode = $options[Resources::ROS_LOCATION_MODE];
            //If have RA-GRS enabled for the request, switch between
            //primary and secondary.
            if ($locationMode == LocationMode::PRIMARY_THEN_SECONDARY ||
                $locationMode == LocationMode::SECONDARY_THEN_PRIMARY) {
                $primaryUri = $options[Resources::ROS_PRIMARY_URI];
                $secondaryUri = $options[Resources::ROS_SECONDARY_URI];

                $target = $request->getRequestTarget();
                if (Utilities::startsWith($target, '/')) {
                    $target = substr($target, 1);
                    $primaryUri = new Uri($primaryUri . $target);
                    $secondaryUri = new Uri($secondaryUri . $target);
                }

                //substitute the uri.
                if ((string)$request->getUri() == (string)$primaryUri) {
                    $request = $request->withUri($secondaryUri);
                } elseif ((string)$request->getUri() == (string)$secondaryUri) {
                    $request = $request->withUri($primaryUri);
                }
            }
        }
        $handler = $options[Resources::ROS_HANDLER];

        return \call_user_func($handler, $request, $options);
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Models\Filters
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Table\Models\Filters;

/**
 * Filter operations
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Models\Filters
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class Filter
{
    /**
     * Apply and operation between two filters
     *
     * @param Filter $left  The left filter
     * @param Filter $right The right filter
     *
     * @return \MicrosoftAzure\Storage\Table\Models\Filters\BinaryFilter
     */
    public static function applyAnd(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'and', $right);
        return $filter;
    }

    /**
     * Applies not operation on $operand
     *
     * @param Filter $operand The operand
     *
     * @return \MicrosoftAzure\Storage\Table\Models\Filters\UnaryFilter
     */
    public static function applyNot(Filter $operand)
    {
        $filter = new UnaryFilter('not', $operand);
        return $filter;
    }

    /**
     * Apply or operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyOr(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'or', $right);
        return $filter;
    }

    /**
     * Apply eq operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyEq(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'eq', $right);
        return $filter;
    }

    /**
     * Apply ne operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyNe(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'ne', $right);
        return $filter;
    }

    /**
     * Apply ge operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyGe(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'ge', $right);
        return $filter;
    }

    /**
     * Apply gt operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyGt(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'gt', $right);
        return $filter;
    }

    /**
     * Apply lt operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyLt(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'lt', $right);
        return $filter;
    }

    /**
     * Apply le operation on the passed filers
     *
     * @param Filter $left  The left operand
     * @param Filter $right The right operand
     *
     * @return BinaryFilter
     */
    public static function applyLe(Filter $left, Filter $right)
    {
        $filter = new BinaryFilter($left, 'le', $right);
        return $filter;
    }

    /**
     * Apply constant filter on value.
     *
     * @param mixed  $value   The filter value
     * @param string $edmType The value EDM type.
     *
     * @return \MicrosoftAzure\Storage\Table\Models\Filters\ConstantFilter
     */
    public static function applyConstant($value, $edmType = null)
    {
        $filter = new ConstantFilter($edmType, $value);
        return $filter;
    }

    /**
     * Apply propertyName filter on $value
     *
     * @param string $value The filter value
     *
     * @return \MicrosoftAzure\Storage\Table\Models\Filters\PropertyNameFilter
     */
    public static function applyPropertyName($value)
    {
        $filter = new PropertyNameFilter($value);
        return $filter;
    }

    /**
     * Takes raw string filter
     *
     * @param string $value The raw string filter expression
     *
     * @return \MicrosoftAzure\Storage\Table\Models\Filters\QueryStringFilter
     */
    public static function applyQueryString($value)
    {
        $filter = new QueryStringFilter($value);
        return $filter;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Authentication
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2019 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Internal\Authentication;

use GuzzleHttp\Psr7\Request;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Validate;

/**
 * Azure authentication scheme for token credential.
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Authentication
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2019 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class TokenAuthScheme implements IAuthScheme
{
    /**
     * The authentication token
     */
    protected $tokenRef;

    /**
     * Constructor.
     *
     * @param string $token the token used for AAD authentication.
     */
    public function __construct(&$token)
    {
        $this->tokenRef =& $token;
    }

    /**
     * Adds authentication header to the request headers.
     *
     * @param \GuzzleHttp\Psr7\Request $request HTTP request object.
     *
     * @abstract
     *
     * @return \GuzzleHttp\Psr7\Request
     */
    public function signRequest(Request $request)
    {
        $bearerToken = "Bearer ". $this->tokenRef;
        return $request->withHeader(Resources::AUTHENTICATION, $bearerToken);
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\File\Models;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\File\Internal\FileResources as Resources;

/**
 * Holds result of getShareStats.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class GetShareStatsResult
{
    /**
     * The approximate size of the data stored on the share, rounded up to the
     * nearest gigabyte. Note that this value may not include all recently
     * created or recently resized files.
     *
     * @var int
     */
    private $shareUsage;

    /**
     * Gets file shareUsage.
     *
     * @return int
     */
    public function getShareUsage()
    {
        return $this->shareUsage;
    }

    /**
     * Sets file shareUsage.
     *
     * @param int $shareUsage value.
     *
     * @return void
     */
    protected function setShareUsage($shareUsage)
    {
        $this->shareUsage = $shareUsage;
    }

    /**
     * Create an instance using the response headers from the API call.
     *
     * @param  array  $parsed          The array contains parsed response body
     *
     * @internal
     *
     * @return GetShareStatsResult
     */
    public static function create(array $parsed)
    {
        $result   = new GetShareStatsResult();

        $result->setShareUsage(\intval(Utilities::tryGetValueInsensitive(
            Resources::XTAG_SHARE_USAGE,
            $parsed
        )));

        return $result;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Models;

use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\LocationMode;

/**
 * Provides functionality and data structure for continuation token.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ContinuationToken
{
    private $location;

    public function __construct(
        $location = ''
    ) {
        $this->setLocation($location);
    }

    /**
     * Setter for location
     *
     * @param string $location the location to be set.
     */
    public function setLocation($location)
    {
        Validate::canCastAsString($location, 'location');
        Validate::isTrue(
            $location == LocationMode::PRIMARY_ONLY ||
            $location == LocationMode::SECONDARY_ONLY ||
            $location == '',
            sprintf(
                Resources::INVALID_VALUE_MSG,
                'location',
                LocationMode::PRIMARY_ONLY . ' or ' . LocationMode::SECONDARY_ONLY
            )
        );

        $this->location = $location;
    }

    /**
     * Getter for location
     *
     * @return string
     */
    public function getLocation()
    {
        return $this->location;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Serialization
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Internal\Serialization;

use MicrosoftAzure\Storage\Common\Internal\Validate;

/**
 * Perform JSON serialization / deserialization
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Serialization
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class JsonSerializer implements ISerializer
{
    /**
     * Serialize an object with specified root element name.
     *
     * @param object $targetObject The target object.
     * @param string $rootName     The name of the root element.
     *
     * @return string
     */
    public static function objectSerialize($targetObject, $rootName)
    {
        Validate::notNull($targetObject, 'targetObject');
        Validate::canCastAsString($rootName, 'rootName');

        $contianer = new \stdClass();

        $contianer->$rootName = $targetObject;

        return json_encode($contianer);
    }

    /**
     * Serializes given array. The array indices must be string to use them as
     * as element name.
     *
     * @param array $array      The object to serialize represented in array.
     * @param array $properties The used properties in the serialization process.
     *
     * @return string
     */
    public function serialize(array $array = null, array $properties = null)
    {
        Validate::isArray($array, 'array');

        return json_encode($array);
    }

    /**
     * Unserializes given serialized string to array.
     *
     * @param string $serialized The serialized object in string representation.
     *
     * @return array
     */
    public function unserialize($serialized)
    {
        Validate::canCastAsString($serialized, 'serialized');

        $json = json_decode($serialized);
        if ($json && !is_array($json)) {
            return get_object_vars($json);
        } else {
            return $json;
        }
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Queue\Models;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Queue\Internal\QueueResources as Resources;

/**
 * Holds results of listMessages wrapper.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class PeekMessagesResult
{
    private $queueMessages;

    /**
     * Creates PeekMessagesResult object from parsed XML response.
     *
     * @param array $parsedResponse XML response parsed into array.
     *
     * @internal
     *
     * @return PeekMessagesResult
     */
    public static function create($parsedResponse)
    {
        $result        = new PeekMessagesResult();
        $queueMessages = array();

        if (!empty($parsedResponse)) {
            $rawMessages = Utilities::getArray(
                $parsedResponse[Resources::QP_QUEUE_MESSAGE]
            );
            foreach ($rawMessages as $value) {
                $message = QueueMessage::createFromPeekMessages($value);

                $queueMessages[] = $message;
            }
        }
        $result->setQueueMessages($queueMessages);

        return $result;
    }

    /**
     * Gets queueMessages field.
     *
     * @return QueueMessage[]
     */
    public function getQueueMessages()
    {
        $clonedMessages = array();

        foreach ($this->queueMessages as $value) {
            $clonedMessages[] = clone $value;
        }

        return $clonedMessages;
    }

    /**
     * Sets queueMessages field.
     *
     * @param QueueMessage[] $queueMessages value to use.
     *
     * @internal
     *
     * @return void
     */
    protected function setQueueMessages($queueMessages)
    {
        $this->queueMessages = $queueMessages;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Table\Models;

use MicrosoftAzure\Storage\Table\Internal\IODataReaderWriter;

/**
 * Holds result of calling getEntity wrapper.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class GetEntityResult
{
    private $_entity;

    /**
     * Gets table entity.
     *
     * @return Entity
     */
    public function getEntity()
    {
        return $this->_entity;
    }

    /**
     * Sets table entity.
     *
     * @param Entity $entity The table entity instance.
     *
     * @return void
     */
    protected function setEntity($entity)
    {
        $this->_entity = $entity;
    }

    /**
     * Create GetEntityResult object from HTTP response parts.
     *
     * @param string             $body            The HTTP response body.
     * @param IODataReaderWriter $odataSerializer The OData reader and writer.
     *
     * @internal
     *
     * @return GetEntityResult
     */
    public static function create($body, IODataReaderWriter $serializer)
    {
        $result = new GetEntityResult();
        $result->setEntity($serializer->parseEntity($body));

        return $result;
    }
}