<?php

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

namespace MicrosoftAzure\Storage\Common\Internal;

/**
 * Helper methods for parsing connection strings. The rules for formatting connection
 * strings are defined here:
 * www.connectionstrings.com/articles/show/important-rules-for-connection-strings
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ConnectionStringParser
{
    const EXPECT_KEY        = 'ExpectKey';
    const EXPECT_ASSIGNMENT = 'ExpectAssignment';
    const EXPECT_VALUE      = 'ExpectValue';
    const EXPECT_SEPARATOR  = 'ExpectSeparator';

    private $_argumentName;
    private $_value;
    private $_pos;
    private $_state;

    /**
     * Parses the connection string into a collection of key/value pairs.
     *
     * @param string $argumentName     Name of the argument to be used in error
     * messages.
     * @param string $connectionString Connection string.
     *
     * @return array
     */
    public static function parseConnectionString($argumentName, $connectionString)
    {
        Validate::canCastAsString($argumentName, 'argumentName');
        Validate::notNullOrEmpty($argumentName, 'argumentName');
        Validate::canCastAsString($connectionString, 'connectionString');
        Validate::notNullOrEmpty($connectionString, 'connectionString');

        $parser = new ConnectionStringParser($argumentName, $connectionString);
        return $parser->_parse();
    }

    /**
     * Initializes the object.
     *
     * @param string $argumentName Name of the argument to be used in error
     * messages.
     * @param string $value        Connection string.
     */
    private function __construct($argumentName, $value)
    {
        $this->_argumentName = $argumentName;
        $this->_value        = $value;
        $this->_pos          = 0;
        $this->_state        = ConnectionStringParser::EXPECT_KEY;
    }

    /**
     * Parses the connection string.
     *
     * @return array
     *
     * @throws \RuntimeException
     */
    private function _parse()
    {
        $key                    = null;
        $value                  = null;
        $connectionStringValues = array();

        while (true) {
            $this->_skipWhiteSpaces();

            if ($this->_pos == strlen($this->_value)
                && $this->_state != ConnectionStringParser::EXPECT_VALUE
            ) {
                // Not stopping after the end has been reached and a value is
                // expected results in creating an empty value, which we expect.
                break;
            }

            switch ($this->_state) {
                case ConnectionStringParser::EXPECT_KEY:
                    $key          = $this->_extractKey();
                    $this->_state = ConnectionStringParser::EXPECT_ASSIGNMENT;
                    break;

                case ConnectionStringParser::EXPECT_ASSIGNMENT:
                    $this->_skipOperator('=');
                    $this->_state = ConnectionStringParser::EXPECT_VALUE;
                    break;

                case ConnectionStringParser::EXPECT_VALUE:
                    $value                        = $this->_extractValue();
                    $this->_state                 =
                    ConnectionStringParser::EXPECT_SEPARATOR;
                    $connectionStringValues[$key] = $value;
                    $key                          = null;
                    $value                        = null;
                    break;

                default:
                    $this->_skipOperator(';');
                    $this->_state = ConnectionStringParser::EXPECT_KEY;
                    break;
            }
        }

        // Must end parsing in the valid state (expected key or separator)
        if ($this->_state == ConnectionStringParser::EXPECT_ASSIGNMENT) {
            throw $this->_createException(
                $this->_pos,
                Resources::MISSING_CONNECTION_STRING_CHAR,
                '='
            );
        }

        return $connectionStringValues;
    }

    /**
     *Generates an invalid connection string exception with the detailed error
     * message.
     *
     * @param integer $position    The position of the error.
     * @param string  $errorString The short error formatting string.
     *
     * @return \RuntimeException
     */
    private function _createException($position, $errorString)
    {
        $arguments = func_get_args();

        // Remove first and second arguments (position and error string)
        unset($arguments[0], $arguments[1]);

        // Create a short error message.
        $errorString = vsprintf($errorString, $arguments);

        // Add position.
        $errorString = sprintf(
            Resources::ERROR_PARSING_STRING,
            $errorString,
            $position
        );

        // Create final error message.
        $errorString = sprintf(
            Resources::INVALID_CONNECTION_STRING,
            $this->_argumentName,
            $errorString
        );

        return new \RuntimeException($errorString);
    }

    /**
     * Skips whitespaces at the current position.
     *
     * @return void
     */
    private function _skipWhiteSpaces()
    {
        while ($this->_pos < strlen($this->_value)
              &&  ctype_space($this->_value[$this->_pos])
        ) {
            $this->_pos++;
        }
    }

    /**
     * Extracts the key's value.
     *
     * @return string
     */
    private function _extractValue()
    {
        $value = Resources::EMPTY_STRING;

        if ($this->_pos < strlen($this->_value)) {
            $ch = $this->_value[$this->_pos];

            if ($ch == '"' || $ch == '\'') {
                // Value is contained between double quotes or skipped single quotes.
                $this->_pos++;
                $value = $this->_extractString($ch);
            } else {
                $firstPos = $this->_pos;
                $isFound  = false;

                while ($this->_pos < strlen($this->_value) && !$isFound) {
                    $ch = $this->_value[$this->_pos];

                    if ($ch == ';') {
                        $isFound = true;
                    } else {
                        $this->_pos++;
                    }
                }

                $value = rtrim(
                    substr($this->_value, $firstPos, $this->_pos - $firstPos)
                );
            }
        }

        return $value;
    }

    /**
     * Extracts key at the current position.
     *
     * @return string
     */
    private function _extractKey()
    {
        $key      = null;
        $firstPos = $this->_pos;
        $ch       = $this->_value[$this->_pos];

        if ($ch == '"' || $ch == '\'') {
            $this->_pos++;
            $key = $this->_extractString($ch);
        } elseif ($ch == ';' || $ch == '=') {
            // Key name was expected.
            throw $this->_createException(
                $firstPos,
                Resources::ERROR_CONNECTION_STRING_MISSING_KEY
            );
        } else {
            while ($this->_pos < strlen($this->_value)) {
                $ch = $this->_value[$this->_pos];

                // At this point we've read the key, break.
                if ($ch == '=') {
                    break;
                }

                $this->_pos++;
            }
            $key = rtrim(substr($this->_value, $firstPos, $this->_pos - $firstPos));
        }

        if (strlen($key) == 0) {
            // Empty key name.
            throw $this->_createException(
                $firstPos,
                Resources::ERROR_CONNECTION_STRING_EMPTY_KEY
            );
        }

        return $key;
    }

    /**
     * Extracts the string until the given quotation mark.
     *
     * @param string $quote The quotation mark terminating the string.
     *
     * @return string
     */
    private function _extractString($quote)
    {
        $firstPos = $this->_pos;

        while ($this->_pos < strlen($this->_value)
              &&  $this->_value[$this->_pos] != $quote
        ) {
            $this->_pos++;
        }

        if ($this->_pos == strlen($this->_value)) {
            // Runaway string.
            throw $this->_createException(
                $this->_pos,
                Resources::ERROR_CONNECTION_STRING_MISSING_CHARACTER,
                $quote
            );
        }

        return substr($this->_value, $firstPos, $this->_pos++ - $firstPos);
    }

    /**
     * Skips specified operator.
     *
     * @param string $operatorChar The operator character.
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    private function _skipOperator($operatorChar)
    {
        if ($this->_value[$this->_pos] != $operatorChar) {
            // Character was expected.
            throw $this->_createException(
                $this->_pos,
                Resources::MISSING_CONNECTION_STRING_CHAR,
                $operatorChar
            );
        }

        $this->_pos++;
    }
}


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

/**
 * Holds share ACL
 *
 * @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 GetShareACLResult
{
    private $shareACL;
    private $lastModified;
    private $etag;

    /**
     * Parses the given array into signed identifiers
     *
     * @param string    $etag         share etag
     * @param \DateTime $lastModified last modification date
     * @param array     $parsed       parsed response into array
     * representation
     *
     * @internal
     *
     * @return self
     */
    public static function create(
        $etag,
        \DateTime $lastModified,
        array $parsed = null
    ) {
        $result = new GetShareAclResult();
        $result->setETag($etag);
        $result->setLastModified($lastModified);
        $acl = ShareACL::create($parsed);
        $result->setShareAcl($acl);

        return $result;
    }

    /**
     * Gets share ACL
     *
     * @return ShareACL
     */
    public function getShareAcl()
    {
        return $this->shareACL;
    }

    /**
     * Sets share ACL
     *
     * @param ShareACL $shareACL value.
     *
     * @return void
     */
    protected function setShareAcl(ShareACL $shareACL)
    {
        $this->shareACL = $shareACL;
    }

    /**
     * Gets share lastModified.
     *
     * @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;
    }

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

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


<?php

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

namespace MicrosoftAzure\Storage\File\Models;

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

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

    /**
     * Creates ListFileRangesResult object from $parsed response and
     * $headers in array representation
     *
     * @param array $headers HTTP response headers
     * @param array $parsed  parsed response in array format.
     *
     * @internal
     *
     * @return ListFileRangesResult
     */
    public static function create(array $headers, array $parsed = null)
    {
        $result  = new ListFileRangesResult();
        $headers = array_change_key_case($headers);

        $date          = $headers[Resources::LAST_MODIFIED];
        $date          = Utilities::rfc1123ToDateTime($date);
        $fileLength    = intval($headers[Resources::X_MS_CONTENT_LENGTH]);
        $rawRanges = array();
        if (!empty($parsed['Range'])) {
            $rawRanges = Utilities::getArray($parsed['Range']);
        }

        $ranges = array();
        foreach ($rawRanges as $value) {
            $ranges[] = new Range(
                intval($value['Start']),
                intval($value['End'])
            );
        }
        $result->setRanges($ranges);
        $result->setContentLength($fileLength);
        $result->setETag($headers[Resources::ETAG]);
        $result->setLastModified($date);

        return $result;
    }

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

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

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

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

    /**
     * Gets file contentLength.
     *
     * @return integer
     */
    public function getContentLength()
    {
        return $this->contentLength;
    }

    /**
     * Sets file contentLength.
     *
     * @param integer $contentLength value.
     *
     * @return void
     */
    protected function setContentLength($contentLength)
    {
        Validate::isInteger($contentLength, 'contentLength');
        $this->contentLength = $contentLength;
    }

    /**
     * Gets ranges
     *
     * @return array
     */
    public function getRanges()
    {
        return $this->ranges;
    }

    /**
     * Sets ranges
     *
     * @param array $ranges ranges to set
     *
     * @return void
     */
    protected function setRanges(array $ranges)
    {
        $this->ranges = array();
        foreach ($ranges as $range) {
            $this->ranges[] = clone $range;
        }
    }
}


<?php

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

namespace MicrosoftAzure\Storage\Common\Models;

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

/**
 * Result from calling get service stats REST wrapper.
 *
 * @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 GetServiceStatsResult
{
    private $status;
    private $lastSyncTime;

    /**
     * Creates object from $parsedResponse.
     *
     * @internal
     * @param array $parsedResponse XML response parsed into array.
     *
     * @return \MicrosoftAzure\Storage\Common\Models\GetServiceStatsResult
     */
    public static function create(array $parsedResponse)
    {
        $result = new GetServiceStatsResult();
        if (Utilities::arrayKeyExistsInsensitive(
            Resources::XTAG_GEO_REPLICATION,
            $parsedResponse
        )) {
            $geoReplication = $parsedResponse[Resources::XTAG_GEO_REPLICATION];
            if (Utilities::arrayKeyExistsInsensitive(
                Resources::XTAG_STATUS,
                $geoReplication
            )) {
                $result->setStatus($geoReplication[Resources::XTAG_STATUS]);
            }

            if (Utilities::arrayKeyExistsInsensitive(
                Resources::XTAG_LAST_SYNC_TIME,
                $geoReplication
            )) {
                $lastSyncTime = $geoReplication[Resources::XTAG_LAST_SYNC_TIME];
                $result->setLastSyncTime(Utilities::convertToDateTime($lastSyncTime));
            }
        }

        return $result;
    }

    /**
     * Gets status of the result.
     *
     * @return string
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * Gets the last sync time.
     * @return \DateTime
     */
    public function getLastSyncTime()
    {
        return $this->lastSyncTime;
    }

    /**
     * Sets status of the result.
     *
     * @return void
     */
    protected function setStatus($status)
    {
        $this->status = $status;
    }

    /**
     * Sets the last sync time.
     *
     * @return void
     */
    protected function setLastSyncTime(\DateTime $lastSyncTime)
    {
        $this->lastSyncTime = $lastSyncTime;
    }
}


<?php

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

use MicrosoftAzure\Storage\Common\Middlewares\MiddlewareBase;
use MicrosoftAzure\Storage\Common\Internal\Authentication\IAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use Psr\Http\Message\RequestInterface;

/**
 * CommonRequestMiddleware is the middleware used to add the necessary headers
 * and to sign the request with provided authentication scheme. This middleware
 * is by default applied to each of the request.
 *
 * @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
 */
class CommonRequestMiddleware extends MiddlewareBase
{
    private $authenticationScheme;
    private $headers;
    private $msVersion;
    private $userAgent;

    /**
     * Creates CommonRequestMiddleware with the passed scheme and headers to
     * be added.
     *
     * @param IAuthScheme $authenticationScheme The authentication scheme.
     * @param string      $storageAPIVersion    Azure Storage Service API version,
     *                                          like '2016-05-31'.
     * @param string      $serviceSDKVersion    Like '1.0.1' or '1.2.0'.
     * @param array       $headers              The headers to be added.
     */
    public function __construct(
        IAuthScheme $authenticationScheme = null,
        $storageAPIVersion,
        $serviceSDKVersion,
        array $headers = array()
    ) {
        $this->authenticationScheme = $authenticationScheme;
        $this->msVersion            = $storageAPIVersion;
        $this->userAgent            = self::getUserAgent($serviceSDKVersion);
        $this->headers              = $headers;
    }

    /**
     * Add the provided headers, the date, then sign the request using the
     * authentication scheme, and return it.
     *
     * @param  RequestInterface $request un-signed request.
     *
     * @return RequestInterface
     */
    protected function onRequest(RequestInterface $request)
    {
        $result = $request;

        //Adding headers.
        foreach ($this->headers as $key => $value) {
            $headers = $result->getHeaders();
            if (!array_key_exists($key, $headers)) {
                $result = $result->withHeader($key, $value);
            }
        }

        //rewriting version and user-agent.
        $result = $result->withHeader(
            Resources::X_MS_VERSION,
            $this->msVersion
        );
        $result = $result->withHeader(
            Resources::USER_AGENT,
            $this->userAgent
        );

        //Adding date.
        $date = gmdate(Resources::AZURE_DATE_FORMAT, time());
        $result = $result->withHeader(Resources::DATE, $date);

        //Adding request-ID if not specified by the user.
        if (!$result->hasHeader(Resources::X_MS_REQUEST_ID)) {
            $result = $result->withHeader(Resources::X_MS_REQUEST_ID, \uniqid());
        }
        //Sign the request if authentication scheme is not null.
        $request = $this->authenticationScheme == null ?
            $request : $this->authenticationScheme->signRequest($result);
        return $request;
    }

    /**
     * Gets the user agent string used in request header.
     *
     * @param $serviceSDKVersion
     *
     * @return string
     */
    private static function getUserAgent($serviceSDKVersion)
    {
        // e.g. User-Agent: Azure-Storage/1.0.1-1.1.1 (PHP 5.5.32)/WINNT
        return 'Azure-Storage/' . $serviceSDKVersion . '-' .
            Resources::COMMON_SDK_VERSION .
            ' (PHP ' . PHP_VERSION . ')' . '/' . php_uname("s");
    }
}


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

/**
 * Base class for all REST services settings.
 *
 * Derived classes must implement the following members:
 * 1- $isInitialized: A static property that indicates whether the class's static
 *    members have been initialized.
 * 2- init(): A protected static method that initializes static members.
 * 3- $validSettingKeys: A static property that contains valid setting keys for this
 *    service.
 * 4- createFromConnectionString($connectionString): A public static function that
 *    takes a connection string and returns the created settings object.
 *
 * @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
 */
abstract class ServiceSettings
{
    /**
     * Throws an exception if the connection string format does not match any of the
     * available formats.
     *
     * @param string $connectionString The invalid formatted connection string.
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    protected static function noMatch($connectionString)
    {
        throw new \RuntimeException(
            sprintf(Resources::MISSING_CONNECTION_STRING_SETTINGS, $connectionString)
        );
    }

    /**
     * Parses the connection string and then validate that the parsed keys belong to
     * the $validSettingKeys
     *
     * @param string $connectionString The user provided connection string.
     *
     * @return array The tokenized connection string keys.
     *
     * @throws \RuntimeException
     */
    protected static function parseAndValidateKeys($connectionString)
    {
        // Initialize the static values if they are not initialized yet.
        if (!static::$isInitialized) {
            static::init();
            static::$isInitialized = true;
        }

        $tokenizedSettings = ConnectionStringParser::parseConnectionString(
            'connectionString',
            $connectionString
        );

        // Assure that all given keys are valid.
        foreach ($tokenizedSettings as $key => $value) {
            if (!Utilities::inArrayInsensitive($key, static::$validSettingKeys)) {
                throw new \RuntimeException(
                    sprintf(
                        Resources::INVALID_CONNECTION_STRING_SETTING_KEY,
                        $key,
                        implode("\n", static::$validSettingKeys)
                    )
                );
            }
        }

        return $tokenizedSettings;
    }

    /**
     * Creates an anonymous function that acts as predicate.
     *
     * @param array   $requirements The array of conditions to satisfy.
     * @param boolean $isRequired   Either these conditions are all required or all
     * optional.
     * @param boolean $atLeastOne   Indicates that at least one requirement must
     * succeed.
     *
     * @return callable
     */
    protected static function getValidator(
        array $requirements,
        $isRequired,
        $atLeastOne
    ) {
        // @codingStandardsIgnoreStart

        return function ($userSettings) use ($requirements, $isRequired, $atLeastOne) {
            $oneFound = false;
            $result   = array_change_key_case($userSettings);
            foreach ($requirements as $requirement) {
                $settingName = strtolower($requirement[Resources::SETTING_NAME]);

                // Check if the setting name exists in the provided user settings.
                if (array_key_exists($settingName, $result)) {
                    // Check if the provided user setting value is valid.
                    $validationFunc = $requirement[Resources::SETTING_CONSTRAINT];
                    $isValid        = $validationFunc($result[$settingName]);

                    if ($isValid) {
                        // Remove the setting as indicator for successful validation.
                        unset($result[$settingName]);
                        $oneFound = true;
                    }
                } else {
                    // If required then fail because the setting does not exist
                    if ($isRequired) {
                        return null;
                    }
                }
            }

            if ($atLeastOne) {
                // At least one requirement must succeed, otherwise fail.
                return $oneFound ? $result : null;
            } else {
                return $result;
            }
        };

        // @codingStandardsIgnoreEnd
    }

    /**
     * Creates at lease one succeed predicate for the provided list of requirements.
     *
     * @return callable
     */
    protected static function atLeastOne()
    {
        $allSettings = func_get_args();
        return self::getValidator($allSettings, false, true);
    }

    /**
     * Creates an optional predicate for the provided list of requirements.
     *
     * @return callable
     */
    protected static function optional()
    {
        $optionalSettings = func_get_args();
        return self::getValidator($optionalSettings, false, false);
    }

    /**
     * Creates an required predicate for the provided list of requirements.
     *
     * @return callable
     */
    protected static function allRequired()
    {
        $requiredSettings = func_get_args();
        return self::getValidator($requiredSettings, true, false);
    }

    /**
     * Creates a setting value condition using the passed predicate.
     *
     * @param string   $name      The setting key name.
     * @param callable $predicate The setting value predicate.
     *
     * @return array
     */
    protected static function settingWithFunc($name, $predicate)
    {
        $requirement                                = array();
        $requirement[Resources::SETTING_NAME]       = $name;
        $requirement[Resources::SETTING_CONSTRAINT] = $predicate;

        return $requirement;
    }

    /**
     * Creates a setting value condition that validates it is one of the
     * passed valid values.
     *
     * @param string $name The setting key name.
     *
     * @return array
     */
    protected static function setting($name)
    {
        $validValues = func_get_args();

        // Remove $name argument.
        unset($validValues[0]);

        $validValuesCount = func_num_args();

        $predicate = function ($settingValue) use ($validValuesCount, $validValues) {
            if (empty($validValues)) {
                // No restrictions, succeed,
                return true;
            }

            // Check to find if the $settingValue is valid or not. The index must
            // start from 1 as unset deletes the value but does not update the array
            // indecies.
            for ($index = 1; $index < $validValuesCount; $index++) {
                if ($settingValue == $validValues[$index]) {
                    // $settingValue is found in valid values set, succeed.
                    return true;
                }
            }

            throw new \RuntimeException(
                sprintf(
                    Resources::INVALID_CONFIG_VALUE,
                    $settingValue,
                    implode("\n", $validValues)
                )
            );

            // $settingValue is missing in valid values set, fail.
            return false;
        };

        return self::settingWithFunc($name, $predicate);
    }

    /**
     * Tests to see if a given list of settings matches a set of filters exactly.
     *
     * @param array $settings The settings to check.
     *
     * @return boolean If any filter returns null, false. If there are any settings
     * left over after all filters are processed, false. Otherwise true.
     */
    protected static function matchedSpecification(array $settings)
    {
        $constraints = func_get_args();

        // Remove first element which corresponds to $settings
        unset($constraints[0]);

        foreach ($constraints as $constraint) {
            $remainingSettings = $constraint($settings);

            if (is_null($remainingSettings)) {
                return false;
            } else {
                $settings = $remainingSettings;
            }
        }

        if (empty($settings)) {
            return true;
        }

        return false;
    }
}


<?php

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

namespace MicrosoftAzure\Storage\Common\Internal\Authentication;

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

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

    /**
     * Constructor.
     *
     * @param string $sasToken shared access signature token.
     *
     */
    public function __construct($sasToken)
    {
        // Remove '?' in front of the SAS token if existing
        $this->sasToken = str_replace('?', '', $sasToken, $i);

        if ($i > 1) {
            throw new \InvalidArgumentException(
                sprintf(
                    Resources::INVALID_SAS_TOKEN,
                    $sasToken
                )
            );
        }
    }

    /**
     * Adds authentication header to the request headers.
     *
     * @param  \GuzzleHttp\Psr7\Request $request HTTP request object.
     *
     * @abstract
     *
     * @return \GuzzleHttp\Psr7\Request
     */
    public function signRequest(Request $request)
    {
        // initial URI
        $uri = $request->getUri();

        // new query values from SAS token
        $queryValues = explode('&', $this->sasToken);

        // append SAS token query values to existing URI
        foreach ($queryValues as $queryField) {
            list($key, $value) = explode('=', $queryField);

            $uri = \GuzzleHttp\Psr7\Uri::withQueryValue($uri, $key, $value);
        }

        // replace URI
        return $request->withUri($uri, true);
    }
}


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

/**
 * Represents file properties
 *
 * @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 FileProperties
{
    private $lastModified;
    private $contentLength;
    private $contentType;
    private $etag;
    private $contentMD5;
    private $contentEncoding;
    private $contentLanguage;
    private $cacheControl;
    private $contentDisposition;
    private $contentRange;
    private $copyCompletionTime;
    private $copyStatusDescription;
    private $copyID;
    private $copyProgress;
    private $copySource;
    private $copyStatus;
    private $rangeContentMD5;

    /**
     * Creates FileProperties object from $parsed response in array
     * representation of http headers
     *
     * @param array $parsed parsed response in array format.
     *
     * @internal
     *
     * @return FileProperties
     */
    public static function createFromHttpHeaders(array $parsed)
    {
        $result = new FileProperties();
        $clean  = array_change_key_case($parsed);

        $lastModified = Utilities::tryGetValue($parsed, Resources::LAST_MODIFIED);

        $result->setLastModified(
            Utilities::rfc1123ToDateTime($lastModified)
        );

        $result->setContentLength(
            Utilities::tryGetValue($parsed, Resources::CONTENT_LENGTH)
        );

        $result->setContentType(
            Utilities::tryGetValue($parsed, Resources::CONTENT_TYPE)
        );

        $result->setETag(
            Utilities::tryGetValue($parsed, Resources::ETAG)
        );

        if (Utilities::tryGetValue($parsed, Resources::CONTENT_MD5) &&
            !Utilities::tryGetValue($parsed, Resources::CONTENT_RANGE)
        ) {
            $result->setContentMD5(
                Utilities::tryGetValue($parsed, Resources::CONTENT_MD5)
            );
        } else {
            $result->setContentMD5(
                Utilities::tryGetValue($parsed, Resources::FILE_CONTENT_MD5)
            );
            $result->setRangeContentMD5(
                Utilities::tryGetValue($parsed, Resources::CONTENT_MD5)
            );
        }

        $result->setContentEncoding(
            Utilities::tryGetValue($parsed, Resources::CONTENT_ENCODING)
        );

        $result->setContentLanguage(
            Utilities::tryGetValue($parsed, Resources::CONTENT_LANGUAGE)
        );

        $result->setCacheControl(
            Utilities::tryGetValue($parsed, Resources::CACHE_CONTROL)
        );

        $result->setContentDisposition(
            Utilities::tryGetValue($parsed, Resources::CONTENT_DISPOSITION)
        );

        $result->setContentRange(
            Utilities::tryGetValue($parsed, Resources::CONTENT_RANGE)
        );

        $result->setCopyCompletionTime(
            Utilities::tryGetValue($parsed, Resources::X_MS_COPY_COMPLETION_TIME)
        );

        $result->setCopyStatusDescription(
            Utilities::tryGetValue($parsed, Resources::X_MS_COPY_STATUS_DESCRIPTION)
        );

        $result->setCopyID(
            Utilities::tryGetValue($parsed, Resources::X_MS_COPY_ID)
        );

        $result->setCopyProgress(
            Utilities::tryGetValue($parsed, Resources::X_MS_COPY_PROGRESS)
        );

        $result->setCopySource(
            Utilities::tryGetValue($parsed, Resources::X_MS_COPY_SOURCE)
        );

        $result->setCopyStatus(
            Utilities::tryGetValue($parsed, Resources::X_MS_COPY_STATUS)
        );

        return $result;
    }

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

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

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

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

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

    /**
     * Sets file contentType.
     *
     * @param string $contentType value.
     *
     * @return void
     */
    public function setContentType($contentType)
    {
        $this->contentType = $contentType;
    }

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

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

    /**
     * Gets file contentLength.
     *
     * @return integer
     */
    public function getContentLength()
    {
        return $this->contentLength;
    }

    /**
     * Sets file contentLength.
     *
     * @param integer $contentLength value.
     *
     * @return void
     */
    public function setContentLength($contentLength)
    {
        Validate::isInteger($contentLength, 'contentLength');
        $this->contentLength = (int)$contentLength;
    }

    /**
     * Gets file contentEncoding.
     *
     * @return string
     */
    public function getContentEncoding()
    {
        return $this->contentEncoding;
    }
    /**
     * Sets file contentEncoding.
     *
     * @param string $contentEncoding value.
     *
     * @return void
     */
    public function setContentEncoding($contentEncoding)
    {
        $this->contentEncoding = $contentEncoding;
    }

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

    /**
     * Sets file contentLanguage.
     *
     * @param string $contentLanguage value.
     *
     * @return void
     */
    public function setContentLanguage($contentLanguage)
    {
        $this->contentLanguage = $contentLanguage;
    }

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

    /**
     * Sets file contentMD5.
     *
     * @param string $contentMD5 value.
     *
     * @return void
     */
    public function setContentMD5($contentMD5)
    {
        $this->contentMD5 = $contentMD5;
    }

    /**
     * Gets file range contentMD5.
     *
     * @return string
     */
    public function getRangeContentMD5()
    {
        return $this->rangeContentMD5;
    }

    /**
     * Sets file range contentMD5.
     *
     * @param string rangeContentMD5 value.
     *
     * @return void
     */
    public function setRangeContentMD5($rangeContentMD5)
    {
        $this->rangeContentMD5 = $rangeContentMD5;
    }

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

    /**
     * Sets file cacheControl.
     *
     * @param string $cacheControl value.
     *
     * @return void
     */
    public function setCacheControl($cacheControl)
    {
        $this->cacheControl = $cacheControl;
    }

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

    /**
     * Sets file contentDisposition.
     *
     * @param string $contentDisposition value.
     *
     * @return void
     */
    public function setContentDisposition($contentDisposition)
    {
        $this->contentDisposition = $contentDisposition;
    }

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

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

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

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

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

    /**
     * Sets file lease state.
     *
     * @param string $copyID value.
     *
     * @return void
     */
    protected function setCopyID($copyID)
    {
        $this->copyID = $copyID;
    }

    /**
     * Gets file lease duration.
     *
     * @return string
     */
    public function getCopyProgress()
    {
        return $this->copyProgress;
    }

    /**
     * Sets file copyStatusDescription.
     *
     * @param string $copyProgress value.
     *
     * @return void
     */
    protected function setCopyProgress($copyProgress)
    {
        $this->copyProgress = $copyProgress;
    }

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

    /**
     * Sets file copySource.
     *
     * @param int $copySource value.
     *
     * @return void
     */
    protected function setCopySource($copySource)
    {
        Validate::isInteger($copySource, 'copySource');
        $this->copySource = $copySource;
    }

    /**
     * Gets copy state of the file.
     *
     * @return CopyStatus
     */
    public function getCopyStatus()
    {
        return $this->copyStatus;
    }

    /**
     * Sets the copy state of the file.
     *
     * @param CopyStatus $copyStatus the copy state of the file.
     *
     * @return void
     */
    protected function setCopyStatus($copyStatus)
    {
        $this->copyStatus = $copyStatus;
    }
}


<?php

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

/**
 * Trait implementing logic for Table continuation tokens.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\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
 */
trait TableContinuationTokenTrait
{
    /** @var TableContinuationToken $continuationToken */
    private $continuationToken;

    /**
     * Setter for continuationToken
     *
     * @param TableContinuationToken $continuationToken the continuation token to be set.
     */
    public function setContinuationToken($continuationToken)
    {
        $this->continuationToken = $continuationToken;
    }

    /**
     * Getter for continuationToken
     *
     * @return TableContinuationToken
     */
    public function getContinuationToken()
    {
        return $this->continuationToken;
    }

    /**
     * Gets for location for previous request.
     *
     * @return string|null
     */
    public function getLocation()
    {
        if ($this->continuationToken == null) {
            return null;
        }
        return $this->continuationToken->getLocation();
    }

    public function getLocationMode()
    {
        if ($this->continuationToken == null) {
            return parent::getLocationMode();
        } elseif ($this->continuationToken->getLocation() == '') {
            return parent::getLocationMode();
        } else {
            return $this->getLocation();
        }
    }

    /**
     * Gets nextTableName
     *
     * @return string|null
     */
    public function getNextTableName()
    {
        if ($this->continuationToken == null) {
            return null;
        }
        return $this->continuationToken->getNextTableName();
    }

    /**
     * Gets entity next partition key.
     *
     * @return string|null
     */
    public function getNextPartitionKey()
    {
        if ($this->continuationToken == null) {
            return null;
        }
        return $this->continuationToken->getNextPartitionKey();
    }

    /**
     * Gets entity next row key.
     *
     * @return string|null
     */
    public function getNextRowKey()
    {
        if ($this->continuationToken == null) {
            return null;
        }
        return $this->continuationToken->getNextRowKey();
    }

    /**
     * Sets entity next row key.
     *
     * @param string $nextRowKey The entity next row key value.
     *
     * @return void
     */
    public function setNextRowKey($nextRowKey)
    {
        if ($this->continuationToken == null) {
            $this->setContinuationToken(new TableContinuationToken());
        }
        $this->continuationToken->setNextRowKey($nextRowKey);
    }

    /**
     * Sets entity next partition key.
     *
     * @param string $nextPartitionKey The entity next partition key value.
     *
     * @return void
     */
    public function setNextPartitionKey($nextPartitionKey)
    {
        if ($this->continuationToken == null) {
            $this->setContinuationToken(new TableContinuationToken());
        }
        $this->continuationToken->setNextPartitionKey($nextPartitionKey);
    }

    /**
     * Sets nextTableName
     *
     * @param string $nextTableName value
     *
     * @return void
     */
    public function setNextTableName($nextTableName)
    {
        if ($this->continuationToken == null) {
            $this->setContinuationToken(new TableContinuationToken());
        }
        $this->continuationToken->setNextTableName($nextTableName);
    }
}


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

/**
 * Basic Windows Azure EDM Types used for table entity properties.
 *
 * @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 EdmType
{
    // @codingStandardsIgnoreStart

    const DATETIME = 'Edm.DateTime';
    const BINARY   = 'Edm.Binary';
    const BOOLEAN  = 'Edm.Boolean';
    const DOUBLE   = 'Edm.Double';
    const GUID     = 'Edm.Guid';
    const INT32    = 'Edm.Int32';
    const INT64    = 'Edm.Int64';
    const STRING   = 'Edm.String';

    public static function propertyType($value)
    {
        if (is_int($value)) {
            if ($value <= Resources::INT32_MAX && $value >= Resources::INT32_MIN) {
                return EdmType::INT32;
            } else {
                return EdmType::INT64;
            }
        } elseif (Utilities::isDouble($value)) {
            return EdmType::DOUBLE;
        } elseif (is_bool($value)) {
            return EdmType::BOOLEAN;
        } elseif ($value instanceof \DateTime) {
            return EdmType::DATETIME;
        } else {
            return EdmType::STRING;
        }
    }

    public static function typeRequired($type)
    {
        switch ($type) {
            case EdmType::BINARY:
            case EdmType::INT64:
            case EdmType::DATETIME:
            case EdmType::GUID:
            case EdmType::DOUBLE:
            case EdmType::BOOLEAN:
                return true;

            default:
                return false;
        }
    }

    /**
     * Converts the type to string if it's empty and validates the type.
     *
     * @param string $type The Edm type
     *
     * @internal
     *
     * @return string
     */
    public static function processType($type)
    {
        $type = empty($type) ? self::STRING : $type;
        Validate::isTrue(self::isValid($type), Resources::INVALID_EDM_MSG);

        return $type;
    }

    /**
     * Validates that the value associated with the EDM type is valid.
     *
     * @param string $type       The EDM type.
     * @param mixed  $value      The EDM value.
     * @param string &$condition The error message.
     *
     * @internal
     *
     * @return boolean
     *
     * @throws \InvalidArgumentException
     */
    public static function validateEdmValue($type, $value, &$condition = null)
    {
        // Having null value means that the user wants to remove the property name
        // associated with this value. Leave the value as null so this hold.
        if (is_null($value)) {
            return true;
        } else {
            switch ($type) {
            case EdmType::GUID:
            case EdmType::BINARY:
            case EdmType::STRING:
            case EdmType::INT64:
            case null:
                // NULL also is treated as EdmType::STRING
                $condition = 'is_string';
                return is_string($value);

            case EdmType::DOUBLE:
                $condition = 'is_double or is_string';
                return is_double($value) || is_int($value) || is_string($value);

            case EdmType::INT32:
                $condition = 'is_int or is_string';
                return is_int($value) || is_string($value);

            case EdmType::DATETIME:
                $condition = 'instanceof \DateTime';
                return $value instanceof \DateTime;

            case EdmType::BOOLEAN:
                $condition = 'is_bool';
                return is_bool($value);

            default:
                throw new \InvalidArgumentException();
            }
        }
    }

    /**
     * Serializes EDM value into proper value for sending it to Windows Azure.
     *
     * @param string $type  The EDM type.
     * @param mixed  $value The EDM value.
     *
     * @internal
     *
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    public static function serializeValue($type, $value)
    {
        switch ($type) {
        case null:
            return $value;

        case EdmType::INT32:
            return intval($value);

        case EdmType::INT64:
        case EdmType::GUID:
        case EdmType::STRING:
            return strval($value);

        case EdmType::DOUBLE:
            return strval($value);

        case EdmType::BINARY:
            return base64_encode($value);

        case EdmType::DATETIME:
            return Utilities::convertToEdmDateTime($value);

        case EdmType::BOOLEAN:
            return (is_null($value) ? '' : ($value == true ? true : false));

        default:
            throw new \InvalidArgumentException();
        }
    }

    /**
     * Serializes EDM value into proper value to be used in query.
     *
     * @param string $type  The EDM type.
     * @param mixed  $value The EDM value.
     *
     * @internal
     *
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    public static function serializeQueryValue($type, $value)
    {
        switch ($type) {
        case EdmType::DATETIME:
            $edmDate = Utilities::convertToEdmDateTime($value);
            return 'datetime\'' . $edmDate . '\'';

        case EdmType::BINARY:
            return 'X\'' . implode('', unpack("H*", $value)) . '\'';

        case EdmType::BOOLEAN:
            return ($value ? 'true' : 'false');

        case EdmType::DOUBLE:
        case EdmType::INT32:
            return $value;

        case EdmType::INT64:
            return $value . 'L';

        case EdmType::GUID:
            return 'guid\'' . $value . '\'';

        case null:
        case EdmType::STRING:
            // NULL also is treated as EdmType::STRING
            return '\'' . str_replace('\'', '\'\'', $value) . '\'';

        default:
            throw new \InvalidArgumentException();
        }
    }

    /**
     * Converts the value into its proper type.
     *
     * @param string $type  The edm type.
     * @param string $value The edm value.
     *
     * @internal
     *
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    public static function unserializeQueryValue($type, $value)
    {
        // Having null value means that the user wants to remove the property name
        // associated with this value. Leave the value as null so this hold.
        if (is_null($value)) {
            return null;
        } else {
            switch ($type) {
            case self::GUID:
            case self::STRING:
            case self::INT64:
            case null:
                return strval($value);

            case self::BINARY:
                return base64_decode($value);

            case self::DATETIME:
                return Utilities::convertToDateTime($value);

            case self::BOOLEAN:
                return Utilities::toBoolean($value);

            case self::DOUBLE:
                return doubleval($value);

            case self::INT32:
                return intval($value);

            default:
                throw new \InvalidArgumentException();
            }
        }
    }

    /**
     * Check if the $type belongs to valid header types.
     *
     * @param string $type The type string to check.
     *
     * @internal
     *
     * @return boolean
     */
    public static function isValid($type)
    {
        switch ($type) {
        case $type == self::DATETIME:
        case $type == self::BINARY:
        case $type == self::BOOLEAN:
        case $type == self::DOUBLE:
        case $type == self::GUID:
        case $type == self::INT32:
        case $type == self::INT64:
        case $type == self::STRING:
        case $type == null:
            // NULL also is treated as EdmType::STRING
            return true;

        default:
            return false;

        }
    }

    // @codingStandardsIgnoreEnd
}


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

/**
 * Encapsulates service properties
 *
 * @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 ServiceProperties
{
    private $logging;
    private $hourMetrics;
    private $minuteMetrics;
    private $corses;
    private $defaultServiceVersion;

    private static $xmlRootName = 'StorageServiceProperties';

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

        if (array_key_exists(Resources::XTAG_DEFAULT_SERVICE_VERSION, $parsedResponse) &&
            $parsedResponse[Resources::XTAG_DEFAULT_SERVICE_VERSION] != null) {
            $result->setDefaultServiceVersion($parsedResponse[Resources::XTAG_DEFAULT_SERVICE_VERSION]);
        }

        if (array_key_exists(Resources::XTAG_LOGGING, $parsedResponse)) {
            $result->setLogging(Logging::create($parsedResponse[Resources::XTAG_LOGGING]));
        }
        $result->setHourMetrics(Metrics::create($parsedResponse[Resources::XTAG_HOUR_METRICS]));
        if (array_key_exists(Resources::XTAG_MINUTE_METRICS, $parsedResponse)) {
            $result->setMinuteMetrics(Metrics::create($parsedResponse[Resources::XTAG_MINUTE_METRICS]));
        }
        if (array_key_exists(Resources::XTAG_CORS, $parsedResponse) &&
            $parsedResponse[Resources::XTAG_CORS] != null) {
            //There could be multiple CORS rules, so need to extract them all.
            $corses = array();
            $corsArray =
                $parsedResponse[Resources::XTAG_CORS][Resources::XTAG_CORS_RULE];
            if (count(array_filter(array_keys($corsArray), 'is_string')) > 0) {
                //single cors rule
                $corses[] = CORS::create($corsArray);
            } else {
                //multiple cors rule
                foreach ($corsArray as $cors) {
                    $corses[] = CORS::create($cors);
                }
            }

            $result->setCorses($corses);
        } else {
            $result->setCorses(array());
        }

        return $result;
    }

    /**
     * Gets logging element.
     *
     * @return Logging
     */
    public function getLogging()
    {
        return $this->logging;
    }

    /**
     * Sets logging element.
     *
     * @param Logging $logging new element.
     *
     * @return void
     */
    public function setLogging(Logging $logging)
    {
        $this->logging = clone $logging;
    }

    /**
     * Gets hour metrics element.
     *
     * @return Metrics
     */
    public function getHourMetrics()
    {
        return $this->hourMetrics;
    }

    /**
     * Sets hour metrics element.
     *
     * @param Metrics $metrics new element.
     *
     * @return void
     */
    public function setHourMetrics(Metrics $hourMetrics)
    {
        $this->hourMetrics = clone $hourMetrics;
    }

    /**
     * Gets minute metrics element.
     *
     * @return Metrics
     */
    public function getMinuteMetrics()
    {
        return $this->minuteMetrics;
    }

    /**
     * Sets minute metrics element.
     *
     * @param Metrics $metrics new element.
     *
     * @return void
     */
    public function setMinuteMetrics(Metrics $minuteMetrics)
    {
        $this->minuteMetrics = clone $minuteMetrics;
    }

    /**
     * Gets corses element.
     *
     * @return CORS[]
     */
    public function getCorses()
    {
        return $this->corses;
    }

    /**
     * Sets corses element.
     *
     * @param CORS[] $corses new elements.
     *
     * @return void
     */
    public function setCorses(array $corses)
    {
        $this->corses = $corses;
    }

    /**
     * Gets the default service version.
     *
     * @return string
     */
    public function getDefaultServiceVersion()
    {
        return $this->defaultServiceVersion;
    }

    /**
     * Sets the default service version. This can obly be set for the blob service.
     *
     * @param string $defaultServiceVersion the default service version
     *
     * @return void
     */
    public function setDefaultServiceVersion($defaultServiceVersion)
    {
        $this->defaultServiceVersion = $defaultServiceVersion;
    }

    /**
     * Converts this object to array with XML tags
     *
     * @internal
     * @return array
     */
    public function toArray()
    {
        $result = array();

        if (!empty($this->getLogging())) {
            $result[Resources::XTAG_LOGGING] =
                    $this->getLogging()->toArray();
        }

        if (!empty($this->getHourMetrics())) {
            $result[Resources::XTAG_HOUR_METRICS] =
                    $this->getHourMetrics()->toArray();
        }

        if (!empty($this->getMinuteMetrics())) {
            $result[Resources::XTAG_MINUTE_METRICS] =
                    $this->getMinuteMetrics()->toArray();
        }

        $corsesArray = $this->getCorsesArray();
        if (!empty($corsesArray)) {
            $result[Resources::XTAG_CORS] =$corsesArray;
        }

        if ($this->defaultServiceVersion != null) {
            $result[Resources::XTAG_DEFAULT_SERVICE_VERSION] = $this->defaultServiceVersion;
        }

        return $result;
    }

    /**
     * Gets the array that contains all the CORSes.
     *
     * @return array
     */
    private function getCorsesArray()
    {
        $corsesArray = array();
        if (count($this->getCorses()) == 1) {
            $corsesArray = array(
                Resources::XTAG_CORS_RULE => $this->getCorses()[0]->toArray()
            );
        } elseif ($this->getCorses() != array()) {
            foreach ($this->getCorses() as $cors) {
                $corsesArray[] = [Resources::XTAG_CORS_RULE => $cors->toArray()];
            }
        }

        return $corsesArray;
    }

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


<?php

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

namespace MicrosoftAzure\Storage\Common\Internal;

/**
 * Holder for default connection string sources used in CloudConfigurationManager.
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ConnectionStringSource
{
    private static $_defaultSources;
    private static $_isInitialized;
    const ENVIRONMENT_SOURCE = 'environment_source';

    /**
     * Initializes the default sources.
     *
     * @return void
     */
    private static function _init()
    {
        if (!self::$_isInitialized) {
            self::$_defaultSources = array(
                self::ENVIRONMENT_SOURCE => array(__CLASS__, 'environmentSource')
            );
            self::$_isInitialized  = true;
        }
    }

    /**
     * Gets a connection string value from the system environment.
     *
     * @param string $key The connection string name.
     *
     * @return string
     */
    public static function environmentSource($key)
    {
        Validate::canCastAsString($key, 'key');

        return getenv($key);
    }

    /**
     * Gets list of default sources.
     *
     * @return array
     */
    public static function getDefaultSources()
    {
        self::_init();
        return self::$_defaultSources;
    }
}


<?php

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

namespace MicrosoftAzure\Storage\Table\Internal;

use MicrosoftAzure\Storage\Table\Internal\TableResources as Resources;
use MicrosoftAzure\Storage\Table\Models\EdmType;
use MicrosoftAzure\Storage\Table\Models\Entity;

/**
 * Serializes and unserializes results from table wrapper calls
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Table\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
 */
class JsonODataReaderWriter implements IODataReaderWriter
{
    /**
     * Constructs JSON representation for table entry.
     *
     * @param string $name The name of the table.
     *
     * @return string
     */
    public function getTable($name)
    {
        return json_encode(array(Resources::JSON_TABLE_NAME => $name));
    }

    /**
     * Parses one table entry.
     *
     * @param mixed $body The HTTP response body.
     *
     * @return string
     */
    public function parseTable($body)
    {
        $table = json_decode($body, true);
        return $table[Resources::JSON_TABLE_NAME];
    }

    /**
     * Constructs array of tables from HTTP response body.
     *
     * @param string $body The HTTP response body.
     *
     * @return array
     */
    public function parseTableEntries($body)
    {
        $tables     = array();
        $result     = json_decode($body, true);

        $rawEntries = $result[Resources::JSON_VALUE];

        foreach ($rawEntries as $entry) {
            $tables[] = $entry[Resources::JSON_TABLE_NAME];
        }

        return $tables;
    }

    /**
     * Constructs JSON representation for entity.
     *
     * @param Entity $entity The entity instance.
     *
     * @return string
     */
    public function getEntity(Entity $entity)
    {
        $entityProperties = $entity->getProperties();
        $properties       = array();

        foreach ($entityProperties as $name => $property) {
            $edmType    = $property->getEdmType();
            $edmValue   = $property->getValue();

            if (is_null($edmValue)) {
                // No @odata.type JSON property needed for null value
                $properties[$name] = null;
            } else {
                if (is_null($edmType)) {
                    $edmType = EdmType::propertyType($edmValue);
                }

                $value             = EdmType::serializeValue($edmType, $edmValue);
                $properties[$name] = $value;

                if (EdmType::typeRequired($edmType)) {
                    $properties[$name . Resources::JSON_ODATA_TYPE_SUFFIX] = $edmType;
                }
            }
        }

        return json_encode($properties);
    }

    /**
     * Constructs entity from HTTP response body.
     *
     * @param string $body The HTTP response body.
     *
     * @return Entity
     */
    public function parseEntity($body)
    {
        $rawEntity = json_decode($body, true);
        return $this->parseOneEntity($rawEntity);
    }

    /**
     * Constructs array of entities from HTTP response body.
     *
     * @param string $body The HTTP response body.
     *
     * @return array
     */
    public function parseEntities($body)
    {
        $rawEntities = json_decode($body, true);
        $entities   = array();

        foreach ($rawEntities[Resources::JSON_VALUE] as $rawEntity) {
            $entities[] = $this->parseOneEntity($rawEntity);
        }

        return $entities;
    }

    private function parseOneEntity($rawEntity)
    {
        $entity = new Entity();
        $timestamp;
        $etag;

        if (array_key_exists(Resources::JSON_TIMESTAMP, $rawEntity)) {
            $rawTimestamp   = $rawEntity[Resources::JSON_TIMESTAMP];
            $timestamp      = EdmType::unserializeQueryValue(EdmType::DATETIME, $rawTimestamp);

            $entity->addProperty(
                Resources::JSON_TIMESTAMP,
                EdmType::DATETIME,
                $timestamp
            );
        }

        // Make sure etag is set
        if (array_key_exists(Resources::JSON_ODATA_ETAG, $rawEntity)) {
            $etag = (string)$rawEntity[Resources::JSON_ODATA_ETAG];
        } else {
            $etag = null;
        }
        $entity->setETag($etag);

        foreach ($rawEntity as $key => $value) {
            if ($key === Resources::JSON_TIMESTAMP) {
                continue;
            }

            // Ignore keys end with Resources::JSON_ODATA_TYPE_SUFFIX
            if (strlen($key) > strlen(Resources::JSON_ODATA_TYPE_SUFFIX) &&
                strpos(
                    $key,
                    Resources::JSON_ODATA_TYPE_SUFFIX,
                    strlen($key) - strlen(Resources::JSON_ODATA_TYPE_SUFFIX)
                ) !== false) {
                continue;
            }

            if (strpos($key, "odata.") === 0) {
                continue;
            }

            $edmType;
            if (array_key_exists($key . Resources::JSON_ODATA_TYPE_SUFFIX, $rawEntity)) {
                $edmType = $rawEntity[$key . Resources::JSON_ODATA_TYPE_SUFFIX];
            } else {
                // Guess the property type
                $edmType = EdmType::propertyType($value);
            }
            //Store the raw value of the string representation.
            $rawValue = \is_string($value) ? $value : '';
            $value      = EdmType::unserializeQueryValue((string)$edmType, $value);
            $entity->addProperty(
                (string)$key,
                (string)$edmType,
                $value,
                $rawValue
            );
        }

        return $entity;
    }
}


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

/**
 * Batch parameter names.
 *
 * @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 BatchOperationParameterName
{
    const BP_TABLE         = 'table';
    const BP_ENTITY        = 'entity';
    const BP_PARTITION_KEY = 'PartitionKey';
    const BP_ROW_KEY       = 'RowKey';
    const BP_ETAG          = 'etag';

    /**
     * Validates if $paramName is already defined.
     *
     * @param string $paramName The batch operation parameter name.
     *
     * @internal
     *
     * @return boolean
     */
    public static function isValid($paramName)
    {
        switch ($paramName) {
            case self::BP_TABLE:
            case self::BP_ENTITY:
            case self::BP_PARTITION_KEY:
            case self::BP_ROW_KEY:
            case self::BP_ETAG:
                return true;
            default:
                return false;
        }
    }
}


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

/**
 * Holds access policy elements
 *
 * @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
 */
abstract class AccessPolicy
{
    private $start;
    private $expiry;
    private $permission;
    private $resourceType;

    /**
     * Get the valid permissions for the given resource.
     *
     * @return array
     */
    abstract protected static function getResourceValidPermissions();

    /**
     * Constructor
     *
     * @param string $resourceType the resource type of this access policy.
     */
    public function __construct($resourceType)
    {
        Validate::canCastAsString($resourceType, 'resourceType');
        Validate::isTrue(
            $resourceType == Resources::RESOURCE_TYPE_BLOB      ||
            $resourceType == Resources::RESOURCE_TYPE_CONTAINER ||
            $resourceType == Resources::RESOURCE_TYPE_QUEUE     ||
            $resourceType == Resources::RESOURCE_TYPE_TABLE     ||
            $resourceType == Resources::RESOURCE_TYPE_FILE      ||
            $resourceType == Resources::RESOURCE_TYPE_SHARE,
            Resources::ERROR_RESOURCE_TYPE_NOT_SUPPORTED
        );

        $this->resourceType = $resourceType;
    }

    /**
     * Gets start.
     *
     * @return \DateTime.
     */
    public function getStart()
    {
        return $this->start;
    }

    /**
     * Sets start.
     *
     * @param \DateTime $start value.
     *
     * @return void
     */
    public function setStart(\DateTime $start = null)
    {
        if ($start != null) {
            Validate::isDate($start);
        }
        $this->start = $start;
    }

    /**
     * Gets expiry.
     *
     * @return \DateTime.
     */
    public function getExpiry()
    {
        return $this->expiry;
    }

    /**
     * Sets expiry.
     *
     * @param \DateTime $expiry value.
     *
     * @return void
     */
    public function setExpiry($expiry)
    {
        Validate::isDate($expiry);
        $this->expiry = $expiry;
    }

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

    /**
     * Sets permission.
     *
     * @param string $permission value.
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPermission($permission)
    {
        $this->permission = $this->validatePermission($permission);
    }

    /**
     * Gets resource type.
     *
     * @return string.
     */
    public function getResourceType()
    {
        return $this->resourceType;
    }

    /**
     * Validate the permission against its corresponding allowed permissions
     *
     * @param  string $permission The permission to be validated.
     *
     * @throws \InvalidArgumentException
     *
     * @return string
     */
    private function validatePermission($permission)
    {
        $validPermissions = static::getResourceValidPermissions();
        $result = '';
        foreach ($validPermissions as $validPermission) {
            if (strpos($permission, $validPermission) !== false) {
                //append the valid permission to result.
                $result .= $validPermission;
                //remove all the character that represents the permission.
                $permission = str_replace(
                    $validPermission,
                    '',
                    $permission
                );
            }
        }
        //After filtering all the permissions, if there is still characters
        //left in the given permission, throw exception.
        Validate::isTrue(
            $permission == '',
            sprintf(
                Resources::INVALID_PERMISSION_PROVIDED,
                $this->getResourceType(),
                implode(', ', $validPermissions)
            )
        );

        return $result;
    }

    /**
     * Converts this current object to XML representation.
     *
     * @internal
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();

        if ($this->getStart() != null) {
            $array[Resources::XTAG_SIGNED_START] =
                Utilities::convertToEdmDateTime($this->getStart());
        }
        $array[Resources::XTAG_SIGNED_EXPIRY]     =
            Utilities::convertToEdmDateTime($this->getExpiry());
        $array[Resources::XTAG_SIGNED_PERMISSION] = $this->getPermission();

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

/**
 * Supported batch operations.
 *
 * @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 BatchOperationType
{
    const INSERT_ENTITY_OPERATION         = 'InsertEntityOperation';
    const UPDATE_ENTITY_OPERATION         = 'UpdateEntityOperation';
    const DELETE_ENTITY_OPERATION         = 'DeleteEntityOperation';
    const MERGE_ENTITY_OPERATION          = 'MergeEntityOperation';
    const INSERT_REPLACE_ENTITY_OPERATION = 'InsertOrReplaceEntityOperation';
    const INSERT_MERGE_ENTITY_OPERATION   = 'InsertOrMergeEntityOperation';

    /**
     * Validates if $type is already defined.
     *
     * @param string $type The operation type.
     *
     * @internal
     *
     * @return boolean
     */
    public static function isValid($type)
    {
        switch ($type) {
            case self::INSERT_ENTITY_OPERATION:
            case self::UPDATE_ENTITY_OPERATION:
            case self::DELETE_ENTITY_OPERATION:
            case self::MERGE_ENTITY_OPERATION:
            case self::INSERT_REPLACE_ENTITY_OPERATION:
            case self::INSERT_MERGE_ENTITY_OPERATION:
                return true;
            default:
                return false;
        }
    }
}