<?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 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\Serialization;

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

/**
 * Short description
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Serialization
 * @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 XmlSerializer implements ISerializer
{
    const STANDALONE  = 'standalone';
    const ROOT_NAME   = 'rootName';
    const DEFAULT_TAG = 'defaultTag';

    /**
     * Converts a SimpleXML object to an Array recursively
     * ensuring all sub-elements are arrays as well.
     *
     * @param string $sxml The SimpleXML object.
     * @param array  $arr  The array into which to store results.
     *
     * @return array
     */
    private function sxml2arr($sxml, array $arr = null)
    {
        foreach ((array) $sxml as $key => $value) {
            if (is_object($value) || (is_array($value))) {
                $arr[$key] = $this->sxml2arr($value);
            } else {
                $arr[$key] = $value;
            }
        }

        return $arr;
    }

    /**
     * Takes an array and produces XML based on it.
     *
     * @param XMLWriter $xmlw       XMLWriter object that was previously instanted
     * and is used for creating the XML.
     * @param array     $data       Array to be converted to XML.
     * @param string    $defaultTag Default XML tag to be used if none specified.
     *
     * @return void
     */
    private function arr2xml(\XMLWriter $xmlw, array $data, $defaultTag = null)
    {
        foreach ($data as $key => $value) {
            if ($key === Resources::XTAG_ATTRIBUTES) {
                foreach ($value as $attributeName => $attributeValue) {
                    $xmlw->writeAttribute($attributeName, $attributeValue);
                }
            } elseif (is_array($value)) {
                if (!is_int($key)) {
                    if ($key != Resources::EMPTY_STRING) {
                        $xmlw->startElement($key);
                    } else {
                        $xmlw->startElement($defaultTag);
                    }
                }

                $this->arr2xml($xmlw, $value);

                if (!is_int($key)) {
                    $xmlw->endElement();
                }
            } else {
                $xmlw->writeElement($key, $value);
            }
        }
    }

    /**
     * Gets the attributes of a specified object if get attributes
     * method is exposed.
     *
     * @param object $targetObject The target object.
     * @param array  $methodArray  The array of method of the target object.
     *
     * @return mixed
     */
    private static function getInstanceAttributes($targetObject, array $methodArray)
    {
        foreach ($methodArray as $method) {
            if ($method->name == 'getAttributes') {
                $classProperty = $method->invoke($targetObject);
                return $classProperty;
            }
        }
        return null;
    }

    /**
     * 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');
        $xmlWriter = new \XmlWriter();
        $xmlWriter->openMemory();
        $xmlWriter->setIndent(true);
        $reflectionClass = new \ReflectionClass($targetObject);
        $methodArray     = $reflectionClass->getMethods();
        $attributes      = self::getInstanceAttributes(
            $targetObject,
            $methodArray
        );

        $xmlWriter->startElement($rootName);
        if (!is_null($attributes)) {
            foreach (array_keys($attributes) as $attributeKey) {
                $xmlWriter->writeAttribute(
                    $attributeKey,
                    $attributes[$attributeKey]
                );
            }
        }

        foreach ($methodArray as $method) {
            if ((strpos($method->name, 'get') === 0)
                && $method->isPublic()
                && ($method->name != 'getAttributes')
            ) {
                $variableName  = substr($method->name, 3);
                $variableValue = $method->invoke($targetObject);
                if (!empty($variableValue)) {
                    if (gettype($variableValue) === 'object') {
                        $xmlWriter->writeRaw(
                            XmlSerializer::objectSerialize(
                                $variableValue,
                                $variableName
                            )
                        );
                    } else {
                        $xmlWriter->writeElement($variableName, $variableValue);
                    }
                }
            }
        }
        $xmlWriter->endElement();
        return $xmlWriter->outputMemory(true);
    }

    /**
     * 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, array $properties = null)
    {
        $xmlVersion   = '1.0';
        $xmlEncoding  = 'UTF-8';
        $standalone   = Utilities::tryGetValue($properties, self::STANDALONE);
        $defaultTag   = Utilities::tryGetValue($properties, self::DEFAULT_TAG);
        $rootName     = Utilities::tryGetValue($properties, self::ROOT_NAME);
        $docNamespace = Utilities::tryGetValue(
            $array,
            Resources::XTAG_NAMESPACE,
            null
        );

        if (!is_array($array)) {
            return false;
        }

        $xmlw = new \XmlWriter();
        $xmlw->openMemory();
        $xmlw->setIndent(true);
        $xmlw->startDocument($xmlVersion, $xmlEncoding, $standalone);

        if (is_null($docNamespace)) {
            $xmlw->startElement($rootName);
        } else {
            foreach ($docNamespace as $uri => $prefix) {
                $xmlw->startElementNS($prefix, $rootName, $uri);
                break;
            }
        }

        unset($array[Resources::XTAG_NAMESPACE]);
        self::arr2xml($xmlw, $array, $defaultTag);

        $xmlw->endElement();

        return $xmlw->outputMemory(true);
    }

    /**
     * Unserializes given serialized string.
     *
     * @param string $serialized The serialized object in string representation.
     *
     * @return array
     */
    public function unserialize($serialized)
    {
        $sxml = new \SimpleXMLElement($serialized);

        return $this->sxml2arr($sxml);
    }
}


<?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 2016 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\Resources;
use MicrosoftAzure\Storage\Common\Internal\Validate;

/**
 * Provides functionality and data structure for Cross-Origin Resource Sharing
 * rules.
 *
 * @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 CORS
{
    private $allowedOrigins;
    private $allowedMethods;
    private $allowedHeaders;
    private $exposedHeaders;
    private $maxAgeInSeconds;

    /**
     * Constructor of the class.
     *
     * @param string[] $allowedOrigins  The origin domains that are permitted
     *                                  to make request against the storage
     *                                  service via CORS.
     * @param string[] $allowedMethods  The methods (HTTP request verbs) that
     *                                  the origin domain may use for a CORS
     *                                  request.
     * @param string[] $allowedHeaders  The request headers that the origin
     *                                  domain may specify on the CORS request.
     * @param string[] $exposedHeaders  The response headers that may be sent in
     *                                  the response to the CORS request and
     *                                  exposed by the browser to the request
     *                                  issuer.
     * @param int      $maxAgeInSeconds The maximum amount of time that a
     *                                  browser should cache the preflight
     *                                  OPTIONS request.
     */
    public function __construct(
        array $allowedOrigins,
        array $allowedMethods,
        array $allowedHeaders,
        array $exposedHeaders,
        $maxAgeInSeconds
    ) {
        $this->setAllowedOrigins($allowedOrigins);
        $this->setAllowedMethods($allowedMethods);
        $this->setAllowedHeaders($allowedHeaders);
        $this->setExposedHeaders($exposedHeaders);
        $this->setMaxedAgeInSeconds($maxAgeInSeconds);
    }

    /**
     * Create an instance with parsed XML response with 'CORS' root.
     *
     * @param  array  $parsedResponse The response used to create an instance.
     *
     * @internal
     *
     * @return CORS
     */
    public static function create(array $parsedResponse)
    {
        Validate::hasKey(
            Resources::XTAG_ALLOWED_ORIGINS,
            'parsedResponse',
            $parsedResponse
        );
        Validate::hasKey(
            Resources::XTAG_ALLOWED_METHODS,
            'parsedResponse',
            $parsedResponse
        );
        Validate::hasKey(
            Resources::XTAG_ALLOWED_HEADERS,
            'parsedResponse',
            $parsedResponse
        );
        Validate::hasKey(
            Resources::XTAG_EXPOSED_HEADERS,
            'parsedResponse',
            $parsedResponse
        );
        Validate::hasKey(
            Resources::XTAG_MAX_AGE_IN_SECONDS,
            'parsedResponse',
            $parsedResponse
        );

        // Get the values from the parsed response.
        $allowedOrigins  = array_filter(explode(
            ',',
            $parsedResponse[Resources::XTAG_ALLOWED_ORIGINS]
        ));
        $allowedMethods  = array_filter(explode(
            ',',
            $parsedResponse[Resources::XTAG_ALLOWED_METHODS]
        ));
        $allowedHeaders  = array_filter(explode(
            ',',
            $parsedResponse[Resources::XTAG_ALLOWED_HEADERS]
        ));
        $exposedHeaders  = array_filter(explode(
            ',',
            $parsedResponse[Resources::XTAG_EXPOSED_HEADERS]
        ));
        $maxAgeInSeconds = intval(
            $parsedResponse[Resources::XTAG_MAX_AGE_IN_SECONDS]
        );

        return new CORS(
            $allowedOrigins,
            $allowedMethods,
            $allowedHeaders,
            $exposedHeaders,
            $maxAgeInSeconds
        );
    }

    /**
     * Converts this object to array with XML tags
     *
     * @return array
     */
    public function toArray()
    {
        return array(
            Resources::XTAG_ALLOWED_ORIGINS    =>
                implode(',', $this->getAllowedOrigins()),
            Resources::XTAG_ALLOWED_METHODS    =>
                implode(',', $this->getAllowedMethods()),
            Resources::XTAG_ALLOWED_HEADERS    =>
                implode(',', $this->getAllowedHeaders()),
            Resources::XTAG_EXPOSED_HEADERS    =>
                implode(',', $this->getExposedHeaders()),
            Resources::XTAG_MAX_AGE_IN_SECONDS =>
                $this->getMaxedAgeInSeconds()
        );
    }

    /**
     * Setter for allowedOrigins
     *
     * @param string[] $allowedOrigins the allowed origins to be set.
     */
    public function setAllowedOrigins(array $allowedOrigins)
    {
        $this->allowedOrigins = $allowedOrigins;
    }

    /**
     * Getter for allowedOrigins
     *
     * @return string[]
     */
    public function getAllowedOrigins()
    {
        return $this->allowedOrigins;
    }

    /**
     * Setter for allowedMethods
     *
     * @param string[] $allowedMethods the allowed methods to be set.
     */
    public function setAllowedMethods(array $allowedMethods)
    {
        $this->allowedMethods = $allowedMethods;
    }

    /**
     * Getter for allowedMethods
     *
     * @return string[]
     */
    public function getAllowedMethods()
    {
        return $this->allowedMethods;
    }

    /**
     * Setter for allowedHeaders
     *
     * @param string[] $allowedHeaders the allowed headers to be set.
     */
    public function setAllowedHeaders(array $allowedHeaders)
    {
        $this->allowedHeaders = $allowedHeaders;
    }

    /**
     * Getter for allowedHeaders
     *
     * @return string[]
     */
    public function getAllowedHeaders()
    {
        return $this->allowedHeaders;
    }

    /**
     * Setter for exposedHeaders
     *
     * @param string[] $exposedHeaders the exposed headers to be set.
     */
    public function setExposedHeaders(array $exposedHeaders)
    {
        $this->exposedHeaders = $exposedHeaders;
    }

    /**
     * Getter for exposedHeaders
     *
     * @return string[]
     */
    public function getExposedHeaders()
    {
        return $this->exposedHeaders;
    }

    /**
     * Setter for maxAgeInSeconds
     *
     * @param int $maxAgeInSeconds the max age in seconds to be set.
     */
    public function setMaxedAgeInSeconds($maxAgeInSeconds)
    {
        $this->maxAgeInSeconds = $maxAgeInSeconds;
    }

    /**
     * Getter for maxAgeInSeconds
     *
     * @return int
     */
    public function getMaxedAgeInSeconds()
    {
        return $this->maxAgeInSeconds;
    }
}


<?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\Internal
 * @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\LocationMode;
use MicrosoftAzure\Storage\Common\Models\ServiceOptions;
use MicrosoftAzure\Storage\Common\Models\ServiceProperties;
use MicrosoftAzure\Storage\Common\Models\GetServicePropertiesResult;
use MicrosoftAzure\Storage\Common\Models\GetServiceStatsResult;

/**
 * Trait implementing common REST API for all the services, including the
 * following:
 * Get/Set Service Properties
 * Get service stats
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @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
 */
trait ServiceRestTrait
{
    /**
     * Gets the properties of the service.
     *
     * @param ServiceOptions $options The optional parameters.
     *
     * @return \MicrosoftAzure\Storage\Common\Models\GetServicePropertiesResult
     *
     * @see http://msdn.microsoft.com/en-us/library/windowsazure/hh452239.aspx
     */
    public function getServiceProperties(
        ServiceOptions $options = null
    ) {
        return $this->getServicePropertiesAsync($options)->wait();
    }

    /**
     * Creates promise to get the properties of the service.
     *
     * @param ServiceOptions $options The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * @see http://msdn.microsoft.com/en-us/library/windowsazure/hh452239.aspx
     */
    public function getServicePropertiesAsync(
        ServiceOptions $options = null
    ) {
        $method      = Resources::HTTP_GET;
        $headers     = array();
        $queryParams = array();
        $postParams  = array();
        $path        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new ServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_REST_TYPE,
            'service'
        );
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_COMP,
            'properties'
        );

        $dataSerializer = $this->dataSerializer;

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            Resources::EMPTY_STRING,
            $options
        )->then(function ($response) use ($dataSerializer) {
            $parsed = $dataSerializer->unserialize($response->getBody());
            return GetServicePropertiesResult::create($parsed);
        }, null);
    }

    /**
     * Sets the properties of the service.
     *
     * It's recommended to use getServiceProperties, alter the returned object and
     * then use setServiceProperties with this altered object.
     *
     * @param ServiceProperties $serviceProperties The service properties.
     * @param ServiceOptions    $options           The optional parameters.
     *
     * @return void
     *
     * @see http://msdn.microsoft.com/en-us/library/windowsazure/hh452235.aspx
     */
    public function setServiceProperties(
        ServiceProperties $serviceProperties,
        ServiceOptions $options = null
    ) {
        $this->setServicePropertiesAsync($serviceProperties, $options)->wait();
    }

    /**
     * Creates the promise to set the properties of the service.
     *
     * It's recommended to use getServiceProperties, alter the returned object and
     * then use setServiceProperties with this altered object.
     *
     * @param ServiceProperties $serviceProperties The service properties.
     * @param ServiceOptions    $options           The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * @see http://msdn.microsoft.com/en-us/library/windowsazure/hh452235.aspx
     */
    public function setServicePropertiesAsync(
        ServiceProperties $serviceProperties,
        ServiceOptions $options = null
    ) {
        Validate::isTrue(
            $serviceProperties instanceof ServiceProperties,
            Resources::INVALID_SVC_PROP_MSG
        );

        $method      = Resources::HTTP_PUT;
        $headers     = array();
        $queryParams = array();
        $postParams  = array();
        $path        = Resources::EMPTY_STRING;
        $body        = $serviceProperties->toXml($this->dataSerializer);

        if (is_null($options)) {
            $options = new ServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_REST_TYPE,
            'service'
        );
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_COMP,
            'properties'
        );
        $this->addOptionalHeader(
            $headers,
            Resources::CONTENT_TYPE,
            Resources::URL_ENCODED_CONTENT_TYPE
        );

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_ACCEPTED,
            $body,
            $options
        );
    }

    /**
     * Retrieves statistics related to replication for the service. The operation
     * will only be sent to secondary location endpoint.
     *
     * @param  ServiceOptions|null $options The options this operation sends with.
     *
     * @return GetServiceStatsResult
     */
    public function getServiceStats(ServiceOptions $options = null)
    {
        return $this->getServiceStatsAsync($options)->wait();
    }

    /**
     * Creates promise that retrieves statistics related to replication for the
     * service. The operation will only be sent to secondary location endpoint.
     *
     * @param  ServiceOptions|null $options The options this operation sends with.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getServiceStatsAsync(ServiceOptions $options = null)
    {
        $method      = Resources::HTTP_GET;
        $headers     = array();
        $queryParams = array();
        $postParams  = array();
        $path        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new ServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_REST_TYPE,
            'service'
        );
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_COMP,
            'stats'
        );

        $dataSerializer = $this->dataSerializer;

        $options->setLocationMode(LocationMode::SECONDARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            Resources::EMPTY_STRING,
            $options
        )->then(function ($response) use ($dataSerializer) {
            $parsed = $dataSerializer->unserialize($response->getBody());
            return GetServiceStatsResult::create($parsed);
        }, null);
    }
}


<?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\Models\MarkerContinuationToken;
use MicrosoftAzure\Storage\Common\MarkerContinuationTokenTrait;
use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Queue\Internal\QueueResources as Resources;

/**
 * Container to hold list queue response object.
 *
 * @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 ListQueuesResult
{
    use MarkerContinuationTokenTrait;

    private $_queues;
    private $_prefix;
    private $_marker;
    private $_maxResults;
    private $_accountName;

    /**
     * Creates ListQueuesResult 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 ListQueuesResult
     */
    public static function create(array $parsedResponse, $location = '')
    {
        $result               = new ListQueuesResult();
        $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
        ));
        $queues      = array();
        $rawQueues            = array();

        if (!empty($parsedResponse['Queues'])) {
            $rawQueues = Utilities::getArray($parsedResponse['Queues']['Queue']);
        }

        foreach ($rawQueues as $value) {
            $queue    = new Queue($value['Name'], $serviceEndpoint . $value['Name']);
            $metadata = Utilities::tryGetValue($value, Resources::QP_METADATA);
            $queue->setMetadata(is_null($metadata) ? array() : $metadata);
            $queues[] = $queue;
        }
        $result->setQueues($queues);
        return $result;
    }

    /**
     * Gets queues.
     *
     * @return array
     */
    public function getQueues()
    {
        return $this->_queues;
    }

    /**
     * Sets queues.
     *
     * @param array $queues list of queues
     *
     * @internal
     *
     * @return void
     */
    protected function setQueues(array $queues)
    {
        $this->_queues = array();
        foreach ($queues as $queue) {
            $this->_queues[] = clone $queue;
        }
    }

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

    /**
     * Sets prefix.
     *
     * @param string $prefix value.
     *
     * @internal
     *
     * @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.
     *
     * @internal
     *
     * @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.
     *
     * @internal
     *
     * @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.
     *
     * @internal
     *
     * @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
 *
 * @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
 */

namespace MicrosoftAzure\Storage\Common\Internal;

use GuzzleHttp\Psr7\Stream;

/**
 * Utilities for the project
 *
 * @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 Utilities
{
    /**
     * Returns the specified value of the $key passed from $array and in case that
     * this $key doesn't exist, the default value is returned.
     *
     * @param array $array   The array to be used.
     * @param mixed $key     The array key.
     * @param mixed $default The value to return if $key is not found in $array.
     *
     * @return mixed
     */
    public static function tryGetValue($array, $key, $default = null)
    {
        return (!is_null($array)) && is_array($array) && array_key_exists($key, $array)
            ? $array[$key]
            : $default;
    }

    /**
     * Adds a url scheme if there is no scheme. Return null if input URL is null.
     *
     * @param string $url    The URL.
     * @param string $scheme The scheme. By default HTTP
     *
     * @return string
     */
    public static function tryAddUrlScheme($url, $scheme = 'http')
    {
        if ($url == null) {
            return $url;
        }

        $urlScheme = parse_url($url, PHP_URL_SCHEME);

        if (empty($urlScheme)) {
            $url = "$scheme://" . $url;
        }

        return $url;
    }

    /**
     * Parse storage account name from an endpoint url.
     *
     * @param string $url The endpoint $url
     *
     * @return string
     */
    public static function tryParseAccountNameFromUrl($url)
    {
        $host = parse_url($url, PHP_URL_HOST);

        // first token of the url host is account name
        return explode('.', $host)[0];
    }

    /**
     * Parse secondary endpoint url string from a primary endpoint url.
     *
     * Return null if the primary endpoint url is invalid.
     *
     * @param string $uri The primary endpoint url string.
     *
     * @return null|string
     */
    public static function tryGetSecondaryEndpointFromPrimaryEndpoint($uri)
    {
        $splitTokens = explode('.', $uri);
        if (count($splitTokens) > 0 && $splitTokens[0] != '') {
            $schemaAccountToken = $splitTokens[0];
            $schemaAccountSplitTokens = explode('/', $schemaAccountToken);
            if (count($schemaAccountSplitTokens) > 0 &&
                $schemaAccountSplitTokens[0] != '') {
                $accountName = $schemaAccountSplitTokens[
                    count($schemaAccountSplitTokens) - 1
                ];
                $schemaAccountSplitTokens[count($schemaAccountSplitTokens) - 1] =
                    $accountName . Resources::SECONDARY_STRING;

                $splitTokens[0] = implode('/', $schemaAccountSplitTokens);
                $secondaryUri = implode('.', $splitTokens);
                return $secondaryUri;
            }
        }
        return null;
    }

    /**
     * tries to get nested array with index name $key from $array.
     *
     * Returns empty array object if the value is NULL.
     *
     * @param string $key   The index name.
     * @param array  $array The array object.
     *
     * @return array
     */
    public static function tryGetArray($key, array $array)
    {
        return Utilities::getArray(Utilities::tryGetValue($array, $key));
    }

    /**
     * Adds the given key/value pair into array if the value doesn't satisfy empty().
     *
     * This function just validates that the given $array is actually array. If it's
     * NULL the function treats it as array.
     *
     * @param string $key    The key.
     * @param string $value  The value.
     * @param array  &$array The array. If NULL will be used as array.
     *
     * @return void
     */
    public static function addIfNotEmpty($key, $value, array &$array)
    {
        if (!is_null($array)) {
            Validate::isArray($array, 'array');
        }

        if (!empty($value)) {
            $array[$key] = $value;
        }
    }

    /**
     * Returns the specified value of the key chain passed from $array and in case
     * that key chain doesn't exist, null is returned.
     *
     * @param array $array Array to be used.
     *
     * @return mixed
     */
    public static function tryGetKeysChainValue(array $array)
    {
        $arguments    = func_get_args();
        $numArguments = func_num_args();

        $currentArray = $array;
        for ($i = 1; $i < $numArguments; $i++) {
            if (is_array($currentArray)) {
                if (array_key_exists($arguments[$i], $currentArray)) {
                    $currentArray = $currentArray[$arguments[$i]];
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }

        return $currentArray;
    }

    /**
     * Checks if the passed $string starts with $prefix
     *
     * @param string  $string     word to seaech in
     * @param string  $prefix     prefix to be matched
     * @param boolean $ignoreCase true to ignore case during the comparison;
     * otherwise, false
     *
     * @return boolean
     */
    public static function startsWith($string, $prefix, $ignoreCase = false)
    {
        if ($ignoreCase) {
            $string = strtolower($string);
            $prefix = strtolower($prefix);
        }
        return ($prefix == substr($string, 0, strlen($prefix)));
    }

    /**
     * Returns grouped items from passed $var
     *
     * @param array $var item to group
     *
     * @return array
     */
    public static function getArray(array $var)
    {
        if (is_null($var) || empty($var)) {
            return array();
        }

        foreach ($var as $value) {
            if ((gettype($value) == 'object')
                && (get_class($value) == 'SimpleXMLElement')
            ) {
                return (array) $var;
            } elseif (!is_array($value)) {
                return array($var);
            }
        }

        return $var;
    }

    /**
     * Unserializes the passed $xml into array.
     *
     * @param string $xml XML to be parsed.
     *
     * @return array
     */
    public static function unserialize($xml)
    {
        $sxml = new \SimpleXMLElement($xml);

        return self::_sxml2arr($sxml);
    }

    /**
     * Converts a SimpleXML object to an Array recursively
     * ensuring all sub-elements are arrays as well.
     *
     * @param string $sxml SimpleXML object
     * @param array  $arr  Array into which to store results
     *
     * @return array
     */
    private static function _sxml2arr($sxml, array $arr = null)
    {
        foreach ((array) $sxml as $key => $value) {
            if (is_object($value) || (is_array($value))) {
                $arr[$key] = self::_sxml2arr($value);
            } else {
                $arr[$key] = $value;
            }
        }

        return $arr;
    }

    /**
     * Serializes given array into xml. The array indices must be string to use
     * them as XML tags.
     *
     * @param array  $array      object to serialize represented in array.
     * @param string $rootName   name of the XML root element.
     * @param string $defaultTag default tag for non-tagged elements.
     * @param string $standalone adds 'standalone' header tag, values 'yes'/'no'
     *
     * @return string
     */
    public static function serialize(
        array $array,
        $rootName,
        $defaultTag = null,
        $standalone = null
    ) {
        $xmlVersion  = '1.0';
        $xmlEncoding = 'UTF-8';

        if (!is_array($array)) {
            return false;
        }

        $xmlw = new \XmlWriter();
        $xmlw->openMemory();
        $xmlw->startDocument($xmlVersion, $xmlEncoding, $standalone);

        $xmlw->startElement($rootName);

        self::_arr2xml($xmlw, $array, $defaultTag);

        $xmlw->endElement();

        return $xmlw->outputMemory(true);
    }

    /**
     * Takes an array and produces XML based on it.
     *
     * @param XMLWriter $xmlw       XMLWriter object that was previously instanted
     * and is used for creating the XML.
     * @param array     $data       Array to be converted to XML
     * @param string    $defaultTag Default XML tag to be used if none specified.
     *
     * @return void
     */
    private static function _arr2xml(
        \XMLWriter $xmlw,
        array $data,
        $defaultTag = null
    ) {
        foreach ($data as $key => $value) {
            if (strcmp($key, '@attributes') == 0) {
                foreach ($value as $attributeName => $attributeValue) {
                    $xmlw->writeAttribute($attributeName, $attributeValue);
                }
            } elseif (is_array($value)) {
                if (!is_int($key)) {
                    if ($key != Resources::EMPTY_STRING) {
                        $xmlw->startElement($key);
                    } else {
                        $xmlw->startElement($defaultTag);
                    }
                }

                self::_arr2xml($xmlw, $value);

                if (!is_int($key)) {
                    $xmlw->endElement();
                }
                continue;
            } else {
                $xmlw->writeElement($key, $value);
            }
        }
    }

    /**
     * Converts string into boolean value.
     *
     * @param string $obj       boolean value in string format.
     * @param bool   $skipNull  If $skipNull is set, will return NULL directly
     *                          when $obj is NULL.
     *
     * @return bool
     */
    public static function toBoolean($obj, $skipNull = false)
    {
        if ($skipNull && is_null($obj)) {
            return null;
        }

        return filter_var($obj, FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * Converts string into boolean value.
     *
     * @param bool $obj boolean value to convert.
     *
     * @return string
     */
    public static function booleanToString($obj)
    {
        return $obj ? 'true' : 'false';
    }

    /**
     * Converts a given date string into \DateTime object
     *
     * @param string $date windows azure date ins string representation.
     *
     * @return \DateTime
     */
    public static function rfc1123ToDateTime($date)
    {
        $timeZone = new \DateTimeZone('GMT');
        $format   = Resources::AZURE_DATE_FORMAT;

        return \DateTime::createFromFormat($format, $date, $timeZone);
    }

    /**
     * Generate ISO 8601 compliant date string in UTC time zone
     *
     * @param \DateTimeInterface $date The date value to convert
     *
     * @return string
     */
    public static function isoDate(\DateTimeInterface $date)
    {
        $date = clone $date;
        $date = $date->setTimezone(new \DateTimeZone('UTC'));

        return str_replace('+00:00', 'Z', $date->format('c'));
    }

    /**
     * Converts a DateTime object into an Edm.DaeTime value in UTC timezone,
     * represented as a string.
     *
     * @param mixed $value The datetime value.
     *
     * @return string
     */
    public static function convertToEdmDateTime($value)
    {
        if (empty($value)) {
            return $value;
        }

        if (is_string($value)) {
            $value =  self::convertToDateTime($value);
        }

        Validate::isDate($value);

        $cloned = clone $value;
        $cloned->setTimezone(new \DateTimeZone('UTC'));
        return str_replace('+0000', 'Z', $cloned->format("Y-m-d\TH:i:s.u0O"));
    }

    /**
     * Converts a string to a \DateTime object. Returns false on failure.
     *
     * @param string $value The string value to parse.
     *
     * @return \DateTime
     */
    public static function convertToDateTime($value)
    {
        if ($value instanceof \DateTime) {
            return $value;
        }

        if (substr($value, -1) == 'Z') {
            $value = substr($value, 0, strlen($value) - 1);
        }

        return new \DateTime($value, new \DateTimeZone('UTC'));
    }

    /**
     * Converts string to stream handle.
     *
     * @param string $string The string contents.
     *
     * @return resource
     */
    public static function stringToStream($string)
    {
        return fopen('data://text/plain,' . urlencode($string), 'rb');
    }

    /**
     * Sorts an array based on given keys order.
     *
     * @param array $array The array to sort.
     * @param array $order The keys order array.
     *
     * @return array
     */
    public static function orderArray(array $array, array $order)
    {
        $ordered = array();

        foreach ($order as $key) {
            if (array_key_exists($key, $array)) {
                $ordered[$key] = $array[$key];
            }
        }

        return $ordered;
    }

    /**
     * Checks if a value exists in an array. The comparison is done in a case
     * insensitive manner.
     *
     * @param string $needle   The searched value.
     * @param array  $haystack The array.
     *
     * @return boolean
     */
    public static function inArrayInsensitive($needle, array $haystack)
    {
        return in_array(strtolower($needle), array_map('strtolower', $haystack));
    }

    /**
     * Checks if the given key exists in the array. The comparison is done in a case
     * insensitive manner.
     *
     * @param string $key    The value to check.
     * @param array  $search The array with keys to check.
     *
     * @return boolean
     */
    public static function arrayKeyExistsInsensitive($key, array $search)
    {
        return array_key_exists(strtolower($key), array_change_key_case($search));
    }

    /**
     * Returns the specified value of the $key passed from $array and in case that
     * this $key doesn't exist, the default value is returned. The key matching is
     * done in a case insensitive manner.
     *
     * @param string $key      The array key.
     * @param array  $haystack The array to be used.
     * @param mixed  $default  The value to return if $key is not found in $array.
     *
     * @return mixed
     */
    public static function tryGetValueInsensitive($key, $haystack, $default = null)
    {
        $array = array_change_key_case($haystack);
        return Utilities::tryGetValue($array, strtolower($key), $default);
    }

    /**
     * Returns a string representation of a version 4 GUID, which uses random
     * numbers.There are 6 reserved bits, and the GUIDs have this format:
     *     xxxxxxxx-xxxx-4xxx-[8|9|a|b]xxx-xxxxxxxxxxxx
     * where 'x' is a hexadecimal digit, 0-9a-f.
     *
     * See http://tools.ietf.org/html/rfc4122 for more information.
     *
     * Note: This function is available on all platforms, while the
     * com_create_guid() is only available for Windows.
     *
     * @return string A new GUID.
     */
    public static function getGuid()
    {
        // @codingStandardsIgnoreStart

        return sprintf(
            '%04x%04x-%04x-%04x-%02x%02x-%04x%04x%04x',
            mt_rand(0, 65535),
            mt_rand(0, 65535),          // 32 bits for "time_low"
            mt_rand(0, 65535),          // 16 bits for "time_mid"
            mt_rand(0, 4096) + 16384,   // 16 bits for "time_hi_and_version", with
                                        // the most significant 4 bits being 0100
                                        // to indicate randomly generated version
            mt_rand(0, 64) + 128,       // 8 bits  for "clock_seq_hi", with
                                        // the most significant 2 bits being 10,
                                        // required by version 4 GUIDs.
            mt_rand(0, 256),            // 8 bits  for "clock_seq_low"
            mt_rand(0, 65535),          // 16 bits for "node 0" and "node 1"
            mt_rand(0, 65535),          // 16 bits for "node 2" and "node 3"
            mt_rand(0, 65535)           // 16 bits for "node 4" and "node 5"
        );

        // @codingStandardsIgnoreEnd
    }

    /**
     * Creates a list of objects of type $class from the provided array using static
     * create method.
     *
     * @param array  $parsed The object in array representation
     * @param string $class  The class name. Must have static method create.
     *
     * @return array
     */
    public static function createInstanceList(array $parsed, $class)
    {
        $list = array();

        foreach ($parsed as $value) {
            $list[] = $class::create($value);
        }

        return $list;
    }

    /**
     * Takes a string and return if it ends with the specified character/string.
     *
     * @param string  $haystack   The string to search in.
     * @param string  $needle     postfix to match.
     * @param boolean $ignoreCase Set true to ignore case during the comparison;
     * otherwise, false
     *
     * @return boolean
     */
    public static function endsWith($haystack, $needle, $ignoreCase = false)
    {
        if ($ignoreCase) {
            $haystack = strtolower($haystack);
            $needle   = strtolower($needle);
        }
        $length = strlen($needle);
        if ($length == 0) {
            return true;
        }

        return (substr($haystack, -$length) === $needle);
    }

    /**
     * Get id from entity object or string.
     * If entity is object than validate type and return $entity->$method()
     * If entity is string than return this string
     *
     * @param object|string $entity Entity with id property
     * @param string        $type   Entity type to validate
     * @param string        $method Methods that gets id (getId by default)
     *
     * @return string
     */
    public static function getEntityId($entity, $type, $method = 'getId')
    {
        if (is_string($entity)) {
            return $entity;
        } else {
            Validate::isA($entity, $type, 'entity');
            Validate::methodExists($entity, $method, $type);

            return $entity->$method();
        }
    }

    /**
     * Generate a pseudo-random string of bytes using a cryptographically strong
     * algorithm.
     *
     * @param int $length Length of the string in bytes
     *
     * @return string|boolean Generated string of bytes on success, or FALSE on
     *                        failure.
     */
    public static function generateCryptoKey($length)
    {
        return openssl_random_pseudo_bytes($length);
    }

    /**
     * Convert base 256 number to decimal number.
     *
     * @param string $number Base 256 number
     *
     * @return string Decimal number
     */
    public static function base256ToDec($number)
    {
        Validate::canCastAsString($number, 'number');

        $result = 0;
        $base   = 1;
        for ($i = strlen($number) - 1; $i >= 0; $i--) {
            $result = bcadd($result, bcmul(ord($number[$i]), $base));
            $base   = bcmul($base, 256);
        }

        return $result;
    }

    /**
     * To evaluate if the stream is larger than a certain size. To restore
     * the stream, it has to be seekable, so will return true if the stream
     * is not seekable.
     * @param  Stream          $stream The stream to be evaluated.
     * @param  int             $size   The size if the string is larger than.
     *
     * @return boolean         true if the stream is larger than the given size.
     */
    public static function isStreamLargerThanSizeOrNotSeekable(Stream $stream, $size)
    {
        Validate::isInteger($size, 'size');
        Validate::isTrue(
            $stream instanceof Stream,
            sprintf(Resources::INVALID_PARAM_MSG, 'stream', 'Guzzle\Stream')
        );
        $result = true;
        if ($stream->isSeekable()) {
            $position = $stream->tell();
            try {
                $stream->seek($size);
            } catch (\RuntimeException $e) {
                $pos = strpos(
                    $e->getMessage(),
                    'to seek to stream position '
                );
                if ($pos == null) {
                    throw $e;
                }
                $result = false;
            }
            if ($stream->eof()) {
                $result = false;
            } elseif ($stream->read(1) == '') {
                $result = false;
            }
            $stream->seek($position);
        }
        return $result;
    }

    /**
     * Gets metadata array by parsing them from given headers.
     *
     * @param array $headers HTTP headers containing metadata elements.
     *
     * @return array
     */
    public static function getMetadataArray(array $headers)
    {
        $metadata = array();
        foreach ($headers as $key => $value) {
            $isMetadataHeader = Utilities::startsWith(
                strtolower($key),
                Resources::X_MS_META_HEADER_PREFIX
            );

            if ($isMetadataHeader) {
                // Metadata name is case-presrved and case insensitive
                $MetadataName = str_ireplace(
                    Resources::X_MS_META_HEADER_PREFIX,
                    Resources::EMPTY_STRING,
                    $key
                );
                $metadata[$MetadataName] = $value;
            }
        }

        return $metadata;
    }

    /**
     * Validates the provided metadata array.
     *
     * @param array $metadata The metadata array.
     *
     * @return void
     */
    public static function validateMetadata(array $metadata = null)
    {
        if (!is_null($metadata)) {
            Validate::isArray($metadata, 'metadata');
        } else {
            $metadata = array();
        }

        foreach ($metadata as $key => $value) {
            Validate::canCastAsString($key, 'metadata key');
            Validate::canCastAsString($value, 'metadata value');
        }
    }

    /**
     * Append the content to file.
     * @param  string $path    The file to append to.
     * @param  string $content The content to append.
     *
     * @return void
     */
    public static function appendToFile($path, $content)
    {
        $resource = @fopen($path, 'a+');
        if ($resource != null) {
            fwrite($resource, $content);
            fclose($resource);
        }
    }

    /**
     * Check if all the bytes are zero.
     *
     * @param string $content The content.
     * @return bool
     */
    public static function allZero($content)
    {
        $size = strlen($content);

        // If all Zero, skip this range
        for ($i = 0; $i < $size; $i++) {
            if (ord($content[$i]) != 0) {
                return false;
            }
        }

        return true;
    }

    /**
     * Append the delimiter to the string. The delimiter will not be added if
     * the string already ends with this delimiter.
     *
     * @param string $string    The string to add delimiter to.
     * @param string $delimiter The delimiter to be added.
     *
     * @return string
     */
    public static function appendDelimiter($string, $delimiter)
    {
        if (!self::endsWith($string, $delimiter)) {
            $string .= $delimiter;
        }

        return $string;
    }

    /**
     * Static function used to determine if the request is performed against
     * secondary endpoint.
     *
     * @param  Psr\Http\Message\RequestInterface $request The request performed.
     * @param  array                             $options The options of the
     *                                                    request. Must contain
     *                                                    Resources::ROS_SECONDARY_URI
     *
     * @return boolean
     */
    public static function requestSentToSecondary(
        \Psr\Http\Message\RequestInterface $request,
        array $options
    ) {
        $uri = $request->getUri();
        $secondaryUri = $options[Resources::ROS_SECONDARY_URI];
        $isSecondary = false;
        if (strpos((string)$uri, (string)$secondaryUri) !== false) {
            $isSecondary = true;
        }
        return $isSecondary;
    }

    /**
     * Gets the location value from the headers.
     *
     * @param  array  $headers request/response headers.
     *
     * @return string
     */
    public static function getLocationFromHeaders(array $headers)
    {
        $value = Utilities::tryGetValue(
            $headers,
            Resources::X_MS_CONTINUATION_LOCATION_MODE
        );

        $result = '';
        if (\is_string($value)) {
            $result = $value;
        } elseif (!empty($value)) {
            $result = $value[0];
        }
        return $result;
    }

    /**
     * Gets if the value is a double value or string representation of a double
     * value
     *
     * @param  mixed  $value The value to be verified.
     *
     * @return boolean
     */
    public static function isDouble($value)
    {
        return is_numeric($value) && is_double($value + 0);
    }

    /**
     * Calculates the content MD5 which is base64 encoded. This should be align
     * with the server calculated MD5.
     *
     * @param  string $content the content to be calculated.
     *
     * @return string
     */
    public static function calculateContentMD5($content)
    {
        Validate::notNull($content, 'content');
        Validate::canCastAsString($content, 'content');

        return base64_encode(md5($content, true));
    }

    /**
     * Return if the environment is in 64 bit PHP.
     *
     * @return bool
     */
    public static function is64BitPHP()
    {
        return PHP_INT_SIZE == 8;
    }
}


<?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 2016 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\Utilities;

/**
 * Holds elements of queue properties retention policy field.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\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 RetentionPolicy
{
    private $_enabled;
    private $_days;

    /**
     * Creates object from $parsedResponse.
     *
     * @param array $parsedResponse XML response parsed into array.
     *
     * @internal
     *
     * @return MicrosoftAzure\Storage\Common\Models\RetentionPolicy
     */
    public static function create(array $parsedResponse = null)
    {
        $result = new RetentionPolicy();
        $result->setEnabled(Utilities::toBoolean($parsedResponse['Enabled']));
        if ($result->getEnabled()) {
            $result->setDays(intval($parsedResponse['Days']));
        }

        return $result;
    }

    /**
     * Gets enabled.
     *
     * @return bool
     */
    public function getEnabled()
    {
        return $this->_enabled;
    }

    /**
     * Sets enabled.
     *
     * @param bool $enabled value to use.
     *
     * @return void
     */
    public function setEnabled($enabled)
    {
        $this->_enabled = $enabled;
    }

    /**
     * Gets days field.
     *
     * @return int
     */
    public function getDays()
    {
        return $this->_days;
    }

    /**
     * Sets days field.
     *
     * @param int $days value to use.
     *
     * @return void
     */
    public function setDays($days)
    {
        $this->_days = $days;
    }

    /**
     * Converts this object to array with XML tags
     *
     * @internal
     *
     * @return array
     */
    public function toArray()
    {
        $array = array('Enabled' => Utilities::booleanToString($this->_enabled));
        if (isset($this->_days)) {
            $array['Days'] = strval($this->_days);
        }

        return $array;
    }
}


<?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\ACLBase;
use MicrosoftAzure\Storage\File\Internal\FileResources as Resources;

/**
 * Holds share ACL members.
 *
 * @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 ShareACL extends ACLBase
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        //setting the resource type to a default value.
        $this->setResourceType(Resources::RESOURCE_TYPE_SHARE);
    }

    /**
     * Parses the given array into signed identifiers and create an instance of
     * ShareACL
     *
     * @param array  $parsed       The parsed response into array representation.
     *
     * @internal
     *
     * @return ShareACL
     */
    public static function create(array $parsed = null)
    {
        $result = new ShareACL();
        $result->fromXmlArray($parsed);

        return $result;
    }

    /**
     * Validate if the resource type is for the class.
     *
     * @param  string $resourceType the resource type to be validated.
     *
     * @throws \InvalidArgumentException
     *
     * @internal
     *
     * @return void
     */
    protected static function validateResourceType($resourceType)
    {
        Validate::isTrue(
            $resourceType == Resources::RESOURCE_TYPE_SHARE ||
            $resourceType == Resources::RESOURCE_TYPE_FILE,
            Resources::INVALID_RESOURCE_TYPE
        );
    }

    /**
     * Create a ShareAccessPolicy object.
     *
     * @return ShareAccessPolicy
     */
    protected static function createAccessPolicy()
    {
        return new ShareAccessPolicy();
    }
}


<?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\Validate;
use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Queue\Internal\QueueResources as Resources;

/**
 * Holds results of updateMessage 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 UpdateMessageResult
{
    private $_popReceipt;
    private $_timeNextVisible;

    /**
     * Creates an instance with the given response headers.
     *
     * @param  array  $headers The response headers used to create the instance.
     *
     * @internal
     *
     * @return UpdateMessageResult
     */
    public static function create(array $headers)
    {
        $result = new UpdateMessageResult();
        $result->setPopReceipt(Utilities::tryGetValueInsensitive(
            Resources::X_MS_POPRECEIPT,
            $headers
        ));
        $timeNextVisible = Utilities::tryGetValueInsensitive(
            Resources::X_MS_TIME_NEXT_VISIBLE,
            $headers
        );
        $date   = Utilities::rfc1123ToDateTime($timeNextVisible);
        $result->setTimeNextVisible($date);

        return $result;
    }

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

    /**
     * Sets timeNextVisible field.
     *
     * @param \DateTime $timeNextVisible A UTC date/time value that represents when
     * the message will be visible on the queue.
     *
     * @internal
     *
     * @return void
     */
    protected function setTimeNextVisible(\DateTime $timeNextVisible)
    {
        Validate::isDate($timeNextVisible);

        $this->_timeNextVisible = $timeNextVisible;
    }

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

    /**
     * Sets popReceipt field.
     *
     * @param string $popReceipt The pop receipt of the queue message.
     *
     * @internal
     *
     * @return void
     */
    protected function setPopReceipt($popReceipt)
    {
        Validate::canCastAsString($popReceipt, 'popReceipt');
        $this->_popReceipt = $popReceipt;
    }
}


<?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 2016 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\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Validate;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;

/**
 * This class provides static functions that creates retry handlers for Guzzle
 * HTTP clients to handle retry policy.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Middlewares
 * @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 RetryMiddlewareFactory
{
    //The interval will be increased linearly, the nth retry will have a
    //wait time equal to n * interval.
    const LINEAR_INTERVAL_ACCUMULATION      = 'Linear';
    //The interval will be increased exponentially, the nth retry will have a
    //wait time equal to pow(2, n) * interval.
    const EXPONENTIAL_INTERVAL_ACCUMULATION = 'Exponential';
    //This is for the general type of logic that handles retry.
    const GENERAL_RETRY_TYPE                = 'General';
    //This is for the append blob retry only.
    const APPEND_BLOB_RETRY_TYPE            = 'Append Blob Retry';

    /**
     * Create the retry handler for the Guzzle client, according to the given
     * attributes.
     *
     * @param  string $type                The type that controls the logic of
     *                                     the decider of the retry handler.
     *                                     Possible value can be
     *                                     self::GENERAL_RETRY_TYPE or
     *                                     self::APPEND_BLOB_RETRY_TYPE
     * @param  int    $numberOfRetries     The maximum number of retries.
     * @param  int    $interval            The minimum interval between each retry
     * @param  string $accumulationMethod  If the interval increases linearly or
     *                                     exponentially.
     *                                     Possible value can be
     *                                     self::LINEAR_INTERVAL_ACCUMULATION or
     *                                     self::EXPONENTIAL_INTERVAL_ACCUMULATION
     * @param  bool   $retryConnect        Whether to retry on connection failures.
     * @return RetryMiddleware             A RetryMiddleware object that contains
     *                                     the logic of how the request should be
     *                                     handled after a response.
     */
    public static function create(
        $type = self::GENERAL_RETRY_TYPE,
        $numberOfRetries = Resources::DEFAULT_NUMBER_OF_RETRIES,
        $interval = Resources::DEFAULT_RETRY_INTERVAL,
        $accumulationMethod = self::LINEAR_INTERVAL_ACCUMULATION,
        $retryConnect = false
    ) {
        //Validate the input parameters
        //type
        Validate::isTrue(
            $type == self::GENERAL_RETRY_TYPE ||
            $type == self::APPEND_BLOB_RETRY_TYPE,
            sprintf(
                Resources::INVALID_PARAM_GENERAL,
                'type'
            )
        );
        //numberOfRetries
        Validate::isTrue(
            $numberOfRetries > 0,
            sprintf(
                Resources::INVALID_NEGATIVE_PARAM,
                'numberOfRetries'
            )
        );
        //interval
        Validate::isTrue(
            $interval > 0,
            sprintf(
                Resources::INVALID_NEGATIVE_PARAM,
                'interval'
            )
        );
        //accumulationMethod
        Validate::isTrue(
            $accumulationMethod == self::LINEAR_INTERVAL_ACCUMULATION ||
            $accumulationMethod == self::EXPONENTIAL_INTERVAL_ACCUMULATION,
            sprintf(
                Resources::INVALID_PARAM_GENERAL,
                'accumulationMethod'
            )
        );
        //retryConnect
        Validate::isBoolean($retryConnect);

        //Get the interval calculator according to the type of the
        //accumulation method.
        $intervalCalculator =
            $accumulationMethod == self::LINEAR_INTERVAL_ACCUMULATION ?
            self::createLinearDelayCalculator($interval) :
            self::createExponentialDelayCalculator($interval);

        //Get the retry decider according to the type of the retry and
        //the number of retries.
        $retryDecider = self::createRetryDecider($type, $numberOfRetries, $retryConnect);

        //construct the retry middle ware.
        return new RetryMiddleware($intervalCalculator, $retryDecider);
    }

    /**
     * Create the retry decider for the retry handler. It will return a callable
     * that accepts the number of retries, the request, the response and the
     * exception, and return the decision for a retry.
     *
     * @param  string $type         The type of the retry handler.
     * @param  int    $maxRetries   The maximum number of retries to be done.
     * @param  bool   $retryConnect Whether to retry on connection failures.
     *
     * @return callable     The callable that will return if the request should
     *                      be retried.
     */
    protected static function createRetryDecider($type, $maxRetries, $retryConnect)
    {
        return function (
            $retries,
            $request,
            $response = null,
            $exception = null,
            $isSecondary = false
        ) use (
            $type,
            $maxRetries,
            $retryConnect
        ) {
            //Exceeds the retry limit. No retry.
            if ($retries >= $maxRetries) {
                return false;
            }

            if (!$response) {
                if (!$exception || !($exception instanceof RequestException)) {
                    return false;
                } elseif ($exception instanceof ConnectException) {
                    return $retryConnect;
                } else {
                    $response = $exception->getResponse();
                }
            }

            if ($type == self::GENERAL_RETRY_TYPE) {
                return self::generalRetryDecider(
                    $response->getStatusCode(),
                    $isSecondary
                );
            } else {
                return self::appendBlobRetryDecider(
                    $response->getStatusCode(),
                    $isSecondary
                );
            }

            return true;
        };
    }

    /**
     * Decide if the given status code indicate the request should be retried.
     *
     * @param  int $statusCode status code of the previous request.
     *
     * @return bool            true if the request should be retried.
     */
    protected static function generalRetryDecider($statusCode, $isSecondary)
    {
        $retry = false;
        if ($statusCode == 408) {
            $retry = true;
        } elseif ($statusCode >= 500) {
            if ($statusCode != 501 && $statusCode != 505) {
                $retry = true;
            }
        } elseif ($isSecondary && $statusCode == 404) {
            $retry = true;
        }
        return $retry;
    }

    /**
     * Decide if the given status code indicate the request should be retried.
     * This is for append blob.
     *
     * @param  int $statusCode status code of the previous request.
     *
     * @return bool            true if the request should be retried.
     */
    protected static function appendBlobRetryDecider($statusCode)
    {
        //The retry logic is different for append blob.
        //First it will need to record the former status code if it is
        //server error. Then if the following request is 412 then it
        //needs to be retried. Currently this is not implemented so will
        //only adapt to the general retry decider.
        //TODO: add logic for append blob's retry when implemented.
        $retry = self::generalRetryDecider($statusCode);
        return $retry;
    }

    /**
     * Create the delay calculator that increases the interval linearly
     * according to the number of retries.
     *
     * @param  int $interval the minimum interval of the retry.
     *
     * @return callable      a calculator that will return the interval
     *                       according to the number of retries.
     */
    protected static function createLinearDelayCalculator($interval)
    {
        return function ($retries) use ($interval) {
            return $retries * $interval;
        };
    }

    /**
     * Create the delay calculator that increases the interval exponentially
     * according to the number of retries.
     *
     * @param  int $interval the minimum interval of the retry.
     *
     * @return callable      a calculator that will return the interval
     *                       according to the number of retries.
     */
    protected static function createExponentialDelayCalculator($interval)
    {
        return function ($retries) use ($interval) {
            return $interval * ((int)\pow(2, $retries));
        };
    }
}


<?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\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;

use MicrosoftAzure\Storage\Common\Internal\IMiddleware;

/**
 * Base class for all REST proxies.
 *
 * @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 RestProxy
{
    /**
     * @var array
     */
    private $middlewares;

    /**
     * @var Serialization\ISerializer
     */
    protected $dataSerializer;

    /**
     * Initializes new RestProxy object.
     *
     * @param Serialization\ISerializer $dataSerializer The data serializer.
     */
    public function __construct(Serialization\ISerializer $dataSerializer = null)
    {
        $this->middlewares    = array();
        $this->dataSerializer = $dataSerializer;
        //For logging the request and responses.
        // $this->middlewares[] = new HistoryMiddleware('.\\messages.log');
    }

    /**
     * Gets middlewares that will be handling the request and response.
     *
     * @return array
     */
    public function getMiddlewares()
    {
        return $this->middlewares;
    }

    /**
     * Push a new middleware into the middlewares array. The newly added
     * middleware will be the most inner middleware when executed.
     *
     * @param  callable|IMiddleware $middleware the middleware to be added.
     *
     * @return void
     */
    public function pushMiddleware($middleware)
    {
        $this->middlewares[] = $middleware;
    }

    /**
     * Adds optional query parameter.
     *
     * Doesn't add the value if it satisfies empty().
     *
     * @param array  &$queryParameters The query parameters.
     * @param string $key              The query variable name.
     * @param string $value            The query variable value.
     *
     * @return void
     */
    protected function addOptionalQueryParam(array &$queryParameters, $key, $value)
    {
        Validate::isArray($queryParameters, 'queryParameters');
        Validate::canCastAsString($key, 'key');
        Validate::canCastAsString($value, 'value');

        if (!is_null($value) && Resources::EMPTY_STRING !== $value) {
            $queryParameters[$key] = $value;
        }
    }

    /**
     * Adds optional header.
     *
     * Doesn't add the value if it satisfies empty().
     *
     * @param array  &$headers The HTTP header parameters.
     * @param string $key      The HTTP header name.
     * @param string $value    The HTTP header value.
     *
     * @return void
     */
    protected function addOptionalHeader(array &$headers, $key, $value)
    {
        Validate::isArray($headers, 'headers');
        Validate::canCastAsString($key, 'key');
        Validate::canCastAsString($value, 'value');

        if (!is_null($value) && Resources::EMPTY_STRING !== $value) {
            $headers[$key] = $value;
        }
    }
}


<?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 2016 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 Psr\Http\Message\StreamInterface;

/**
 * Holds result of GetFile API.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\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 GetFileResult
{
    private $properties;
    private $metadata;
    private $contentStream;

    /**
     * Creates GetFileResult from getFile call.
     *
     * @param array           $headers  The HTTP response headers.
     * @param StreamInterface $body     The response body.
     * @param array           $metadata The file metadata.
     *
     * @internal
     *
     * @return GetFileResult
     */
    public static function create(
        array $headers,
        StreamInterface $body,
        array $metadata
    ) {
        $result = new GetFileResult();
        $result->setContentStream($body->detach());
        $result->setProperties(FileProperties::createFromHttpHeaders($headers));
        $result->setMetadata(is_null($metadata) ? array() : $metadata);

        return $result;
    }

    /**
     * Gets file metadata.
     *
     * @return array
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * Sets file metadata.
     *
     * @param array $metadata value.
     *
     * @return void
     */
    protected function setMetadata(array $metadata)
    {
        $this->metadata = $metadata;
    }

    /**
     * Gets file properties.
     *
     * @return FileProperties
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * Sets file properties.
     *
     * @param FileProperties $properties value.
     *
     * @return void
     */
    protected function setProperties(FileProperties $properties)
    {
        $this->properties = $properties;
    }

    /**
     * Gets file contentStream.
     *
     * @return resource
     */
    public function getContentStream()
    {
        return $this->contentStream;
    }

    /**
     * Sets file contentStream.
     *
     * @param resource $contentStream The stream handle.
     *
     * @return void
     */
    protected function setContentStream($contentStream)
    {
        $this->contentStream = $contentStream;
    }
}


<?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\Internal
 * @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;

/**
 * Trait implementing common logic for metadata, last-modified and etag. The
 * code is shared for multiple REST APIs.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @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
 */
trait MetadataTrait
{
    private $lastModified;
    private $etag;
    private $metadata;

    /**
     * Any operation that modifies the share or its properties or metadata
     * updates the last modified time. Operations on files do not affect the
     * last modified time of the share.
     *
     * @return \DateTime.
     */
    public function getLastModified()
    {
        return $this->lastModified;
    }

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

    /**
     * The entity tag for the share. If the request version is 2011-08-18 or
     * newer, the ETag value will be in quotes.
     *
     * @return string
     */
    public function getETag()
    {
        return $this->etag;
    }

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

    /**
     * Gets user defined metadata.
     *
     * @return array
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * Sets user defined metadata. This metadata should be added without the
     * header prefix (x-ms-meta-*).
     *
     * @param array $metadata user defined metadata object in array form.
     *
     * @return void
     */
    protected function setMetadata(array $metadata)
    {
        $this->metadata = $metadata;
    }

    /**
     * Create an instance using the response headers from the API call.
     *
     * @param  array  $responseHeaders The array contains all the response headers
     *
     * @internal
     *
     * @return GetShareMetadataResult
     */
    public static function createMetadataResult(array $responseHeaders)
    {
        $result   = new static();
        $metadata = Utilities::getMetadataArray($responseHeaders);
        $date     = Utilities::tryGetValueInsensitive(
            Resources::LAST_MODIFIED,
            $responseHeaders
        );
        $date     = Utilities::rfc1123ToDateTime($date);
        $result->setETag(Utilities::tryGetValueInsensitive(
            Resources::ETAG,
            $responseHeaders
        ));
        $result->setMetadata($metadata);
        $result->setLastModified($date);

        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\Internal\Serialization
 * @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\Serialization;

use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use GuzzleHttp\Exception\RequestException;

/**
 * Provides functionality to serialize a message to a string.
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Serialization
 * @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 MessageSerializer
{
    /**
     * Serialize a message to a string. The message object must be either a type
     * of \Exception, or have following methods implemented.
     * getHeaders()
     * getProtocolVersion()
     * (getUri() && getMethod()) || (getStatusCode() && getReasonPhrase())
     *
     * @param object $message The message to be serialized.
     *
     * @return string
     */
    public static function objectSerialize($targetObject)
    {
        //if the object is of exception type, serialize it using the methods
        //without checking the methods.
        if ($targetObject instanceof RequestException) {
            return self::serializeRequestException($targetObject);
        } elseif ($targetObject instanceof \Exception) {
            return self::serializeException($targetObject);
        }

        Validate::methodExists($targetObject, 'getHeaders', 'targetObject');
        Validate::methodExists($targetObject, 'getProtocolVersion', 'targetObject');

        // Serialize according to the implemented method.
        if (method_exists($targetObject, 'getUri') &&
            method_exists($targetObject, 'getMethod')) {
            return self::serializeRequest($targetObject);
        } elseif (method_exists($targetObject, 'getStatusCode') &&
                   method_exists($targetObject, 'getReasonPhrase')) {
            return self::serializeResponse($targetObject);
        } else {
            throw new \InvalidArgumentException(
                Resources::INVALID_MESSAGE_OBJECT_TO_SERIALIZE
            );
        }
    }

    /**
     * Serialize the request type that implemented the following methods:
     * getHeaders()
     * getProtocolVersion()
     * getUri()
     * getMethod()
     *
     * @param  object $request The request to be serialized.
     *
     * @return string
     */
    private static function serializeRequest($request)
    {
        $headers = $request->getHeaders();
        $version = $request->getProtocolVersion();
        $uri     = $request->getUri();
        $method  = $request->getMethod();

        $resultString = "Request:\n";
        $resultString .= "URI: {$uri}\nHTTP Version: {$version}\nMethod: {$method}\n";
        $resultString .= self::serializeHeaders($headers);

        return $resultString;
    }

    /**
     * Serialize the response type that implemented the following methods:
     * getHeaders()
     * getProtocolVersion()
     * getStatusCode()
     * getReasonPhrase()
     *
     * @param  object $response The response to be serialized
     *
     * @return string
     */
    private static function serializeResponse($response)
    {
        $headers = $response->getHeaders();
        $version = $response->getProtocolVersion();
        $status  = $response->getStatusCode();
        $reason  = $response->getReasonPhrase();

        $resultString = "Response:\n";
        $resultString .= "Status Code: {$status}\nReason: {$reason}\n";
        $resultString .= "HTTP Version: {$version}\n";
        $resultString .= self::serializeHeaders($headers);

        return $resultString;
    }

    /**
     * Serialize the message headers.
     *
     * @param  array  $headers The headers to be serialized.
     *
     * @return string
     */
    private static function serializeHeaders(array $headers)
    {
        $resultString = "Headers:\n";
        foreach ($headers as $key => $value) {
            $resultString .= sprintf("%s: %s\n", $key, $value[0]);
        }

        return $resultString;
    }

    /**
     * Serialize the request exception.
     *
     * @param  RequestException $e the request exception to be serialized.
     *
     * @return string
     */
    private static function serializeRequestException(RequestException $e)
    {
        $resultString = sprintf("Reason:\n%s\n", $e);
        if ($e->hasResponse()) {
            $resultString .= self::serializeResponse($e->getResponse());
        }

        return $resultString;
    }

    /**
     * Serialize the general exception
     *
     * @param  \Exception $e general exception to be serialized.
     *
     * @return string
     */
    private static function serializeException(\Exception $e)
    {
        return sprintf("Reason:\n%s\n", $e);
    }
}


<?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 2017 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 CreateMessage wrapper.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue\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 CreateMessageResult
{
    private $queueMessage;

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

        if (!empty($parsedResponse) &&
            !empty($parsedResponse[Resources::QP_QUEUE_MESSAGE])
        ) {
            $result->setQueueMessage(
                QueueMessage::createFromCreateMessage(
                    $parsedResponse[Resources::QP_QUEUE_MESSAGE]
                )
            );
        }

        return $result;
    }

    /**
     * Gets queueMessage field.
     *
     * @return QueueMessage
     */
    public function getQueueMessage()
    {
        return $this->queueMessage;
    }

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


<?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\Utilities;
use MicrosoftAzure\Storage\Table\Internal\TableResources as Resources;
use MicrosoftAzure\Storage\Table\Internal\IODataReaderWriter;

/**
 * Holds result of calling insertEntity 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 InsertEntityResult
{
    private $entity;

    /**
     * Create InsertEntityResult object from HTTP response parts.
     *
     * @param string              $body            The HTTP response body.
     * @param array               $headers         The HTTP response headers.
     * @param IODataReaderWriter  $odataSerializer The OData reader and writer.
     *
     * @internal
     *
     * @return InsertEntityResult
     */
    public static function create($body, $headers, $odataSerializer)
    {
        $result = new InsertEntityResult();
        $entity = $odataSerializer->parseEntity($body);
        $entity->setETag(Utilities::tryGetValue($headers, Resources::ETAG));
        $result->setEntity($entity);

        return $result;
    }

    /**
     * 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;
    }
}