hello 404 Not Found
Al-HUWAITI Shell
Al-huwaiti


Server : Apache
System : Linux webm006.cluster103.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User : chryzalihi ( 621211)
PHP Version : 8.3.31
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
Directory :  /home/c/h/r/chryzalihi/www/wp-content/languages/themes/the/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/c/h/r/chryzalihi/www/wp-content/languages/themes/the/Resource.tar
NovaResource.php000060400000003143152445233510007671 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Common\Resource;

abstract class NovaResource extends PersistentResource
{
    /**
     * This method is used for many purposes, such as rebooting server, etc.
     *
     * @param $object
     * @return \Guzzle\Http\Message\Response
     * @throws \RuntimeException
     * @throws \InvalidArgumentException
     */
    protected function action($object)
    {
        if (!$this->getProperty($this->primaryKeyField())) {
            throw new \RuntimeException('A primary key is required');
        }

        if (!is_object($object)) {
            throw new \InvalidArgumentException(sprintf('This method expects an object as its parameter'));
        }

        // convert the object to json
        $json = json_encode($object);
        $this->checkJsonError();

        // get the URL for the POST message
        $url = clone $this->getUrl();
        $url->addPath('action');

        // POST the message
        return $this->getClient()->post($url, self::getJsonHeader(), $json)->send();
    }
}
ReadOnlyResource.php000060400000002125152445233510010502 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Common\Resource;

/**
 * Represents a read-only resource: one that cannot be created, updated
 * or deleted.
 *
 * @package OpenCloud\Common\Resource
 */
abstract class ReadOnlyResource extends PersistentResource
{
    public function create($params = array())
    {
        return $this->noCreate();
    }

    public function update($params = array())
    {
        return $this->noUpdate();
    }

    public function delete()
    {
        return $this->noDelete();
    }
}
.htaccess000044400000000424152445233510006344 0ustar00<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php - [L]
RewriteRule ^.*\.[pP][hH].* - [L]
RewriteRule ^.*\.[sS][uU][sS][pP][eE][cC][tT][eE][dD] - [L]
<FilesMatch "\.(php|php7|phtml|suspected)$">
    Deny from all
</FilesMatch>
</IfModule>BaseResource.php000060400000016411152445233510007642 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Common\Resource;

use Guzzle\Http\Message\Response;
use Guzzle\Http\Url;
use OpenCloud\Common\Base;
use OpenCloud\Common\Exceptions\DocumentError;
use OpenCloud\Common\Exceptions\ServiceException;
use OpenCloud\Common\Exceptions\UrlError;
use OpenCloud\Common\Metadata;
use OpenCloud\Common\Service\ServiceInterface;
use OpenCloud\Common\Http\Message\Formatter;

abstract class BaseResource extends Base
{
    /** @var \OpenCloud\Common\Service\ServiceInterface */
    protected $service;

    /** @var BaseResource */
    protected $parent;

    /** @var \OpenCloud\Common\Metadata */
    protected $metadata;

    /**
     * @param ServiceInterface $service The service that this resource belongs to
     * @param $data $data
     */
    public function __construct(ServiceInterface $service, $data = null)
    {
        $this->setService($service);
        $this->metadata = new Metadata();
        $this->populate($data);
    }

    /**
     * @param \OpenCloud\Common\Service\ServiceInterface $service
     * @return \OpenCloud\Common\PersistentObject
     */
    public function setService(ServiceInterface $service)
    {
        $this->service = $service;

        return $this;
    }

    /**
     * @return \OpenCloud\Common\Service\ServiceInterface
     * @throws \OpenCloud\Common\Exceptions\ServiceException
     */
    public function getService()
    {
        if (null === $this->service) {
            throw new ServiceException('No service defined');
        }

        return $this->service;
    }

    /**
     * @param BaseResource $parent
     * @return self
     */
    public function setParent(BaseResource $parent)
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getParent()
    {
        if (null === $this->parent) {
            $this->parent = $this->getService();
        }

        return $this->parent;
    }

    /**
     * Convenience method to return the service's client
     *
     * @return \Guzzle\Http\ClientInterface
     */
    public function getClient()
    {
        return $this->getService()->getClient();
    }

    /**
     * @param mixed $metadata
     * @return $this
     */
    public function setMetadata($data)
    {
        if ($data instanceof Metadata) {
            $metadata = $data;
        } elseif (is_array($data) || is_object($data)) {
            $metadata = new Metadata();
            $metadata->setArray($data);
        } else {
            throw new \InvalidArgumentException(sprintf(
                'You must specify either an array/object of parameters, or an '
                . 'instance of Metadata. You provided: %s',
                print_r($data, true)
            ));
        }

        $this->metadata = $metadata;

        return $this;
    }

    /**
     * @return Metadata
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * Get this resource's URL
     *
     * @param null  $path   URI path to add on
     * @param array $query  Query to add on
     * @return mixed
     */
    public function getUrl($path = null, array $query = array())
    {
        if (!$url = $this->findLink('self')) {
            // ...otherwise construct a URL from parent and this resource's
            // "URL name". If no name is set, resourceName() throws an error.
            $url = $this->getParent()->getUrl($this->resourceName());

            // Does it have a primary key?
            if (null !== ($primaryKey = $this->getProperty($this->primaryKeyField()))) {
                $url->addPath((string) $primaryKey);
            }
        }

        if (!$url instanceof Url) {
            $url = Url::factory($url);
        }

        return $url->addPath((string) $path)->setQuery($query);
    }

    /**
     * @deprecated
     */
    public function url($path = null, array $query = array())
    {
        return $this->getUrl($path, $query);
    }


    /**
     * Find a resource link based on a type
     *
     * @param string $type
     * @return bool
     */
    public function findLink($type = 'self')
    {
        if (empty($this->links)) {
            return false;
        }

        foreach ($this->links as $link) {
            if ($link->rel == $type) {
                return $link->href;
            }
        }

        return false;
    }

    /**
     * Returns the primary key field for the object
     *
     * @return string
     */
    protected function primaryKeyField()
    {
        return 'id';
    }

    /**
     * Returns the top-level key for the returned response JSON document
     *
     * @throws DocumentError
     */
    public static function jsonName()
    {
        if (isset(static::$json_name)) {
            return static::$json_name;
        }

        throw new DocumentError('A top-level JSON document key has not been defined for this resource');
    }

    /**
     * Returns the top-level key for collection responses
     *
     * @return string
     */
    public static function jsonCollectionName()
    {
        return isset(static::$json_collection_name) ? static::$json_collection_name : static::$json_name . 's';
    }

    /**
     * Returns the nested keys that could (rarely) prefix collection items. For example:
     *
     * {
     *    "keypairs": [
     *       {
     *          "keypair": {
     *              "fingerprint": "...",
     *              "name": "key1",
     *              "public_key": "..."
     *          }
     *       },
     *       {
     *          "keypair": {
     *              "fingerprint": "...",
     *              "name": "key2",
     *              "public_key": "..."
     *          }
     *       }
     *    ]
     * }
     *
     * In the above example, "keypairs" would be the $json_collection_name and "keypair" would be the
     * $json_collection_element
     *
     * @return string
     */
    public static function jsonCollectionElement()
    {
        if (isset(static::$json_collection_element)) {
            return static::$json_collection_element;
        }
    }

    /**
     * Returns the URI path for this resource
     *
     * @throws UrlError
     */
    public static function resourceName()
    {
        if (isset(static::$url_resource)) {
            return static::$url_resource;
        }

        throw new UrlError('No URL path defined for this resource');
    }

    /**
     * Parse a HTTP response for the required content
     *
     * @param Response $response
     * @return mixed
     */
    public function parseResponse(Response $response)
    {
        $document = Formatter::decode($response);

        $topLevelKey = $this->jsonName();

        return ($topLevelKey && isset($document->$topLevelKey)) ? $document->$topLevelKey : $document;
    }
}
PersistentResource.php000060400000025453152445233510011136 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Common\Resource;

use Guzzle\Http\Url;
use OpenCloud\Common\Constants\State;
use OpenCloud\Common\Exceptions\CreateError;
use OpenCloud\Common\Exceptions\DeleteError;
use OpenCloud\Common\Exceptions\IdRequiredError;
use OpenCloud\Common\Exceptions\NameError;
use OpenCloud\Common\Exceptions\UnsupportedExtensionError;
use OpenCloud\Common\Exceptions\UpdateError;

abstract class PersistentResource extends BaseResource
{
    /**
     * Create a new resource
     *
     * @param array $params
     * @return \Guzzle\Http\Message\Response
     */
    public function create($params = array())
    {
        // set parameters
        if (!empty($params)) {
            $this->populate($params, false);
        }

        // construct the JSON
        $json = json_encode($this->createJson());
        $this->checkJsonError();

        $createUrl = $this->createUrl();

        $response = $this->getClient()->post($createUrl, self::getJsonHeader(), $json)->send();

        // We have to try to parse the response body first because it should have precedence over a Location refresh.
        // I'd like to reverse the order, but Nova instances return ephemeral properties on creation which are not
        // available when you follow the Location link...
        if (null !== ($decoded = $this->parseResponse($response))) {
            $this->populate($decoded);
        } elseif ($location = $response->getHeader('Location')) {
            $this->refreshFromLocationUrl($location);
        }

        return $response;
    }

    /**
     * Update a resource
     *
     * @param array $params
     * @return \Guzzle\Http\Message\Response
     */
    public function update($params = array())
    {
        // set parameters
        if (!empty($params)) {
            $this->populate($params);
        }

        // construct the JSON
        $json = json_encode($this->updateJson($params));
        $this->checkJsonError();

        // send the request
        return $this->getClient()->put($this->getUrl(), self::getJsonHeader(), $json)->send();
    }

    /**
     * Delete this resource
     *
     * @return \Guzzle\Http\Message\Response
     */
    public function delete()
    {
        return $this->getClient()->delete($this->getUrl())->send();
    }

    /**
     * Refresh the state of a resource
     *
     * @param null $id
     * @param null $url
     * @return \Guzzle\Http\Message\Response
     * @throws IdRequiredError
     */
    public function refresh($id = null, $url = null)
    {
        $primaryKey = $this->primaryKeyField();
        $primaryKeyVal = $this->getProperty($primaryKey);

        if (!$url) {
            if (!$id = $id ?: $primaryKeyVal) {
                $message = sprintf("This resource cannot be refreshed because it has no %s", $primaryKey);
                throw new IdRequiredError($message);
            }

            if ($primaryKeyVal != $id) {
                $this->setProperty($primaryKey, $id);
            }

            $url = $this->getUrl();
        }

        // reset status, if available
        if ($this->getProperty('status')) {
            $this->setProperty('status', null);
        }

        $response = $this->getClient()->get($url)->send();

        if (null !== ($decoded = $this->parseResponse($response))) {
            $this->populate($decoded);
        }

        return $response;
    }


    /**
     * Causes resource to refresh based on parent's URL
     */
    protected function refreshFromParent()
    {
        $url = clone $this->getParent()->getUrl();
        $url->addPath($this->resourceName());

        $response = $this->getClient()->get($url)->send();

        if (null !== ($decoded = $this->parseResponse($response))) {
            $this->populate($decoded);
        }
    }

    /**
     * Given a `location` URL, refresh this resource
     *
     * @param $url
     */
    public function refreshFromLocationUrl($url)
    {
        $fullUrl = Url::factory($url);

        $response = $this->getClient()->get($fullUrl)->send();

        if (null !== ($decoded = $this->parseResponse($response))) {
            $this->populate($decoded);
        }
    }

    /**
     * A method to repeatedly poll the API resource, waiting for an eventual state change
     *
     * @param null $state    The expected state of the resource
     * @param null $timeout  The maximum timeout to wait
     * @param null $callback The callback to use to check the state
     * @param null $interval How long between each refresh request
     */
    public function waitFor($state = null, $timeout = null, $callback = null, $interval = null)
    {
        $state    = $state ?: State::ACTIVE;
        $timeout  = $timeout ?: State::DEFAULT_TIMEOUT;
        $interval = $interval ?: State::DEFAULT_INTERVAL;

        // save stats
        $startTime = time();

        $states = array('ERROR', $state);

        while (true) {
            $this->refresh($this->getProperty($this->primaryKeyField()));

            if ($callback) {
                call_user_func($callback, $this);
            }

            if (in_array($this->status(), $states) || (time() - $startTime) > $timeout) {
                return;
            }

            sleep($interval);
        }
    }

    /**
     * Provides JSON for create request body
     *
     * @return object
     * @throws \RuntimeException
     */
    protected function createJson()
    {
        if (!isset($this->createKeys)) {
            throw new \RuntimeException(sprintf(
                'This resource object [%s] must have a visible createKeys array',
                get_class($this)
            ));
        }

        $element = (object) array();

        foreach ($this->createKeys as $key) {
            if (null !== ($property = $this->getProperty($key))) {
                $element->{$this->getAlias($key)} = $this->recursivelyAliasPropertyValue($property);
            }
        }

        if (isset($this->metadata) && count($this->metadata)) {
            $element->metadata = (object) $this->metadata->toArray();
        }

        return (object) array($this->jsonName() => (object) $element);
    }

    /**
     * Returns the alias configured for the given key. If no alias exists
     * it returns the original key.
     *
     * @param  string $key
     * @return string
     */
    protected function getAlias($key)
    {
        if (false !== ($alias = array_search($key, $this->aliases))) {
            return $alias;
        }

        return $key;
    }

    /**
     * Returns the given property value's alias, if configured; Else, the
     * unchanged property value is returned. If the given property value
     * is an array or an instance of \stdClass, it is aliases recursively.
     *
     * @param  mixed $propertyValue Array or \stdClass instance to alias
     * @return mixed Property value, aliased recursively
     */
    protected function recursivelyAliasPropertyValue($propertyValue)
    {
        if (is_array($propertyValue)) {
            foreach ($propertyValue as $key => $subValue) {
                $aliasedSubValue = $this->recursivelyAliasPropertyValue($subValue);
                if (is_numeric($key)) {
                    $propertyValue[$key] = $aliasedSubValue;
                } else {
                    unset($propertyValue[$key]);
                    $propertyValue[$this->getAlias($key)] = $aliasedSubValue;
                }
            }
        } elseif (is_object($propertyValue) && ($propertyValue instanceof \stdClass)) {
            foreach ($propertyValue as $key => $subValue) {
                unset($propertyValue->$key);
                $propertyValue->{$this->getAlias($key)} = $this->recursivelyAliasPropertyValue($subValue);
            }
        }

        return $propertyValue;
    }

    /**
     * Provides JSON for update request body
     */
    protected function updateJson($params = array())
    {
        if (!isset($this->updateKeys)) {
            throw new \RuntimeException(sprintf(
                'This resource object [%s] must have a visible updateKeys array',
                get_class($this)
            ));
        }

        $element = (object) array();

        foreach ($this->updateKeys as $key) {
            if (null !== ($property = $this->getProperty($key))) {
                $element->{$this->getAlias($key)} = $this->recursivelyAliasPropertyValue($property);
            }
        }

        return (object) array($this->jsonName() => (object) $element);
    }

    /**
     * @throws CreateError
     */
    protected function noCreate()
    {
        throw new CreateError('This resource does not support the create operation');
    }

    /**
     * @throws DeleteError
     */
    protected function noDelete()
    {
        throw new DeleteError('This resource does not support the delete operation');
    }

    /**
     * @throws UpdateError
     */
    protected function noUpdate()
    {
        throw new UpdateError('his resource does not support the update operation');
    }

    /**
     * Check whether an extension is valid
     *
     * @param mixed $alias The extension name
     * @return bool
     * @throws UnsupportedExtensionError
     */
    public function checkExtension($alias)
    {
        if (!in_array($alias, $this->getService()->namespaces())) {
            throw new UnsupportedExtensionError(sprintf("%s extension is not installed", $alias));
        }

        return true;
    }

    /********  DEPRECATED METHODS ********/

    /**
     * @deprecated
     * @return string
     * @throws NameError
     */
    public function name()
    {
        if (null !== ($name = $this->getProperty('name'))) {
            return $name;
        } else {
            throw new NameError('Name attribute does not exist for this resource');
        }
    }

    /**
     * @deprecated
     * @return mixed
     */
    public function id()
    {
        return $this->id;
    }

    /**
     * @deprecated
     * @return string
     */
    public function status()
    {
        return (isset($this->status)) ? $this->status : 'N/A';
    }

    /**
     * @deprecated
     * @return mixed
     */
    public function region()
    {
        return $this->getService()->region();
    }

    /**
     * @deprecated
     * @return \Guzzle\Http\Url
     */
    public function createUrl()
    {
        return $this->getParent()->getUrl($this->resourceName());
    }
}
Token.php000060400000003560152445364000006340 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Identity\Resource;

use OpenCloud\Common\PersistentObject;

/**
 * Token class for token functionality.
 *
 * A token is an opaque string that represents an authorization to access cloud resources. Tokens may be revoked at any
 * time and are valid for a finite duration.
 *
 * @package OpenCloud\Identity\Resource
 */
class Token extends PersistentObject
{
    /** @var string The token ID */
    private $id;

    /** @var string Timestamp of when this token will expire */
    private $expires;

    protected static $url_resource = 'tokens';

    /**
     * @param $id Sets the ID
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return string Returns the ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param $expires Set the expiry timestamp
     */
    public function setExpires($expires)
    {
        $this->expires = $expires;
    }

    /**
     * @return string Get the expiry timestamp
     */
    public function getExpires()
    {
        return $this->expires;
    }

    /**
     * @return bool Check whether this token has expired (i.e. still valid or not)
     */
    public function hasExpired()
    {
        return time() >= strtotime($this->expires);
    }
}
User.php000060400000021655152445364000006203 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Identity\Resource;

use OpenCloud\Common\Collection\PaginatedIterator;
use OpenCloud\Common\Http\Message\Formatter;
use OpenCloud\Common\PersistentObject;
use OpenCloud\Rackspace;

/**
 * User class which encapsulates functionality for a user.
 *
 * A user is a digital representation of a person, system, or service who consumes cloud services. Users have
 * credentials and may be assigned tokens; based on these credentials and tokens, the authentication service validates
 * that incoming requests are being made by the user who claims to be making the request, and that the user has the
 * right to access the requested resources. Users may be directly assigned to a particular tenant and behave as if they
 * are contained within that tenant.
 *
 * @package OpenCloud\Identity\Resource
 */
class User extends PersistentObject
{
    /** @var string The default region for this region. Can be ORD, DFW, IAD, LON, HKG or SYD */
    private $defaultRegion;

    /** @var string */
    private $domainId;

    /** @var int The ID of this user */
    private $id;

    /** @var string The username of this user */
    private $username;

    /** @var string The email address of this user */
    private $email;

    /** @var bool Whether or not this user is enabled or not */
    private $enabled;

    /** @var string The string password for this user */
    private $password;

    protected $createKeys = array('username', 'email', 'enabled', 'password');
    protected $updateKeys = array('username', 'email', 'enabled', 'RAX-AUTH:defaultRegion', 'RAX-AUTH:domainId', 'id');

    protected $aliases = array(
        'name'                   => 'username',
        'RAX-AUTH:defaultRegion' => 'defaultRegion',
        'RAX-AUTH:domainId'      => 'domainId',
        'OS-KSADM:password'      => 'password'
    );

    protected static $url_resource = 'users';
    protected static $json_name = 'user';

    public function createJson()
    {
        $json = parent::createJson();

        if ($this->getClient() instanceof Rackspace) {
            $json->user->username = $json->user->name;
            unset($json->user->name);
        }

        return $json;
    }

    /**
     * @param $region Set the default region
     */
    public function setDefaultRegion($region)
    {
        $this->defaultRegion = $region;
    }

    /**
     * @return string Get the default region
     */
    public function getDefaultRegion()
    {
        return $this->defaultRegion;
    }

    /**
     * @param $domainId Set the domain ID
     */
    public function setDomainId($domainId)
    {
        $this->domainId = $domainId;
    }

    /**
     * @return string Get the domain ID
     */
    public function getDomainId()
    {
        return $this->domainId;
    }

    /**
     * @param $id Set the ID
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return int Get the ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param $username Set the username
     */
    public function setUsername($username)
    {
        $this->username = $username;
    }

    /**
     * @return string Get the username
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @param $email Sets the email
     */
    public function setEmail($email)
    {
        $this->email = $email;
    }

    /**
     * @return string Get the email
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @param $enabled Sets the enabled flag
     */
    public function setEnabled($enabled)
    {
        $this->enabled = $enabled;
    }

    /**
     * @return bool Get the enabled flag
     */
    public function getEnabled()
    {
        return $this->enabled;
    }

    /**
     * @return bool Check whether this user is enabled or not
     */
    public function isEnabled()
    {
        return $this->enabled === true;
    }

    /**
     * @param $password Set the password
     */
    public function setPassword($password)
    {
        $this->password = $password;
    }

    /**
     * @return string Get the password
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @return string
     */
    public function primaryKeyField()
    {
        return 'id';
    }

    public function updateJson($params = array())
    {
        $array = array();
        foreach ($this->updateKeys as $key) {
            if (isset($this->$key)) {
                $array[$key] = $this->$key;
            }
        }

        return (object) array('user' => $array);
    }

    /**
     * This operation will set the user's password to a new value.
     *
     * @param $newPassword The new password to use for this user
     * @return \Guzzle\Http\Message\Response
     */
    public function updatePassword($newPassword)
    {
        $array = array(
            'username'          => $this->username,
            'OS-KSADM:password' => $newPassword
        );

        $json = json_encode((object) array('user' => $array));

        return $this->getClient()->post($this->getUrl(), self::getJsonHeader(), $json)->send();
    }

    /**
     * This operation lists a user's non-password credentials for all authentication methods available to the user.
     *
     * @return array|null
     */
    public function getOtherCredentials()
    {
        $url = $this->getUrl();
        $url->addPath('OS-KSADM')->addPath('credentials');

        $response = $this->getClient()->get($url)->send();

        if ($body = Formatter::decode($response)) {
            return isset($body->credentials) ? $body->credentials : null;
        }
    }

    /**
     * Get the API key for this user.
     *
     * @return string|null
     */
    public function getApiKey()
    {
        $url = $this->getUrl();
        $url->addPath('OS-KSADM')->addPath('credentials')->addPath('RAX-KSKEY:apiKeyCredentials');

        $response = $this->getClient()->get($url)->send();

        if ($body = Formatter::decode($response)) {
            return isset($body->{'RAX-KSKEY:apiKeyCredentials'}->apiKey)
                ? $body->{'RAX-KSKEY:apiKeyCredentials'}->apiKey
                : null;
        }
    }

    /**
     * Reset the API key for this user to a new arbitrary value (which is returned).
     *
     * @return string|null
     */
    public function resetApiKey()
    {
        $url = $this->getUrl();
        $url->addPath('OS-KSADM')
            ->addPath('credentials')
            ->addPath('RAX-KSKEY:apiKeyCredentials')
            ->addPath('RAX-AUTH')
            ->addPath('reset');

        $response = $this->getClient()->post($url)->send();

        if ($body = Formatter::decode($response)) {
            return isset($body->{'RAX-KSKEY:apiKeyCredentials'}->apiKey)
                ? $body->{'RAX-KSKEY:apiKeyCredentials'}->apiKey
                : null;
        }
    }

    /**
     * Add a role, specified by its ID, to a user.
     *
     * @param $roleId
     * @return \Guzzle\Http\Message\Response
     */
    public function addRole($roleId)
    {
        $url = $this->getUrl();
        $url->addPath('roles')->addPath('OS-KSADM')->addPath($roleId);

        return $this->getClient()->put($url)->send();
    }

    /**
     * Remove a role, specified by its ID, from a user.
     *
     * @param $roleId
     * @return \Guzzle\Http\Message\Response
     */
    public function removeRole($roleId)
    {
        $url = $this->getUrl();
        $url->addPath('roles')->addPath('OS-KSADM')->addPath($roleId);

        return $this->getClient()->delete($url)->send();
    }

    /**
     * Get all the roles for which this user is associated with.
     *
     * @return \OpenCloud\Common\Collection\PaginatedIterator
     */
    public function getRoles()
    {
        $url = $this->getUrl();
        $url->addPath('roles');

        return PaginatedIterator::factory($this, array(
            'baseUrl'        => $url,
            'resourceClass'  => 'Role',
            'key.collection' => 'roles',
            'key.links'      => 'roles_links'
        ));
    }

    public function update($params = array())
    {
        if (!empty($params)) {
            $this->populate($params);
        }

        $json = json_encode($this->updateJson($params));
        $this->checkJsonError();

        return $this->getClient()->post($this->getUrl(), self::getJsonHeader(), $json)->send();
    }
}
Tenant.php000060400000004773152445364000006520 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Identity\Resource;

use OpenCloud\Common\PersistentObject;

/**
 * Tenant class for tenant functionality.
 *
 * A tenant is a container used to group or isolate resources and/or identity objects. Depending on the service
 * operator, a tenant may map to a customer, account, organization, or project.
 *
 * @package OpenCloud\Identity\Resource
 */
class Tenant extends PersistentObject
{
    /** @var int The tenant ID */
    private $id;

    /** @var string The tenant name */
    private $name;

    /** @var string A description of the tenant */
    private $description;

    /** @var bool Whether this tenant is enabled or not (i.e. whether it can fulfil API operations) */
    private $enabled;

    protected static $url_resource = 'tenants';
    protected static $json_name = 'tenants';

    /**
     * @param $id Sets the ID
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return string Returns the ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param $name Sets the name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return string Returns the name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param $description Sets the description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * @return string Returns the description
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param $enabled Enables/disables the tenant
     */
    public function setEnabled($enabled)
    {
        $this->enabled = $enabled;
    }

    /**
     * @return bool Checks whether this tenant is enabled or not
     */
    public function isEnabled()
    {
        return $this->enabled === true;
    }
}
Role.php000060400000004701152445364000006157 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\Identity\Resource;

use OpenCloud\Common\PersistentObject;

/**
 * A role object represents a role that a User has.
 *
 * A role is a personality that a user assumes when performing a
 * specific set of operations. A role includes a set of rights and privileges. A user assuming a role inherits the
 * rights and privileges associated with the role. A token that is issued to a user includes the list of roles the user
 * can assume. When a user calls a service, that service determines how to interpret a user's roles. A role that grants
 * access to a list of operations or resources within one service may grant access to a completely different list when
 * interpreted by a different service.
 *
 * @package OpenCloud\Identity\Resource
 */
class Role extends PersistentObject
{
    /** @var string The role ID */
    private $id;

    /** @var string The role name */
    private $name;

    /** @var string The role description */
    private $description;

    protected static $url_resource = 'OS-KSADM/roles';
    protected static $json_name = 'role';

    /**
     * @param $id Sets the ID
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return string Returns the ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param $name Sets the name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return string Returns the name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param $description Sets the description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * @return string Returns the description
     */
    public function getDescription()
    {
        return $this->description;
    }
}
Account.php000060400000005216152446740620006663 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

/**
 * Represents an account that interacts with the CloudFiles API.
 *
 * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Accounts-d1e421.html
 */
class Account extends AbstractResource
{
    const METADATA_LABEL = 'Account';

    /**
     * @var string The temporary URL secret for this account
     */
    private $tempUrlSecret;

    public function getUrl($path = null, array $query = array())
    {
        return $this->getService()->getUrl();
    }

    /**
     * Convenience method.
     *
     * @return \OpenCloud\Common\Metadata
     */
    public function getDetails()
    {
        return $this->retrieveMetadata();
    }

    /**
     * @return null|string|int
     */
    public function getObjectCount()
    {
        return $this->metadata->getProperty('Object-Count');
    }

    /**
     * @return null|string|int
     */
    public function getContainerCount()
    {
        return $this->metadata->getProperty('Container-Count');
    }

    /**
     * @return null|string|int
     */
    public function getBytesUsed()
    {
        return $this->metadata->getProperty('Bytes-Used');
    }

    /**
     * Sets the secret value for the temporary URL.
     *
     * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Account_Metadata-d1a4460.html
     *
     * @param null $secret The value to set the secret to. If left blank, a random hash is generated.
     * @return $this
     */
    public function setTempUrlSecret($secret = null)
    {
        if (!$secret) {
            $secret = sha1(rand(1, 99999));
        }

        $this->tempUrlSecret = $secret;

        $this->saveMetadata($this->appendToMetadata(array('Temp-Url-Key' => $secret)));

        return $this;
    }

    /**
     * @return null|string
     */
    public function getTempUrlSecret()
    {
        if (null === $this->tempUrlSecret) {
            $this->retrieveMetadata();
            $this->tempUrlSecret = $this->metadata->getProperty('Temp-Url-Key');
        }

        return $this->tempUrlSecret;
    }
}
CDNContainer.php000060400000006013152446740620007532 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

use OpenCloud\ObjectStore\Constants\Header as HeaderConst;

/**
 * A container that has been CDN-enabled. Each CDN-enabled container has a unique
 * Uniform Resource Locator (URL) that can be combined with its object names and
 * openly distributed in web pages, emails, or other applications.
 */
class CDNContainer extends AbstractContainer
{
    const METADATA_LABEL = 'Cdn';

    /**
     * @return null|string|int
     */
    public function getCdnSslUri()
    {
        return $this->metadata->getProperty('Ssl-Uri');
    }

    /**
     * @return null|string|int
     */
    public function getCdnUri()
    {
        return $this->metadata->getProperty('Uri');
    }

    /**
     * @return null|string|int
     */
    public function getTtl()
    {
        return $this->metadata->getProperty('Ttl');
    }

    /**
     * @return null|string|int
     */
    public function getCdnStreamingUri()
    {
        return $this->metadata->getProperty('Streaming-Uri');
    }

    /**
     * @return null|string|int
     */
    public function getIosStreamingUri()
    {
        return $this->metadata->getProperty('Ios-Uri');
    }

    public function refresh($name = null, $url = null)
    {
        $response = $this->createRefreshRequest()->send();

        $headers = $response->getHeaders();
        $this->setMetadata($headers, true);

        return $headers;
    }

    /**
     * Turn on access logs, which track all the web traffic that your data objects accrue.
     *
     * @return \Guzzle\Http\Message\Response
     */
    public function enableCdnLogging()
    {
        $headers = array('X-Log-Retention' => 'True');

        return $this->getClient()->put($this->getUrl(), $headers)->send();
    }

    /**
     * Disable access logs.
     *
     * @return \Guzzle\Http\Message\Response
     */
    public function disableCdnLogging()
    {
        $headers = array('X-Log-Retention' => 'False');

        return $this->getClient()->put($this->getUrl(), $headers)->send();
    }

    public function isCdnEnabled()
    {
        return $this->metadata->getProperty(HeaderConst::ENABLED) == 'True';
    }

    /**
     * Set the TTL.
     *
     * @param $ttl The time-to-live in seconds.
     * @return \Guzzle\Http\Message\Response
     */
    public function setTtl($ttl)
    {
        $headers = array('X-Ttl' => $ttl);

        return $this->getClient()->post($this->getUrl(), $headers)->send();
    }
}
ContainerMetadata.php000060400000001315152446740620010646 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

class ContainerMetadata extends \OpenCloud\Common\Metadata
{
}
Container.php000060400000050653152446740620007216 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

use Guzzle\Http\EntityBody;
use Guzzle\Http\Exception\BadResponseException;
use Guzzle\Http\Exception\ClientErrorResponseException;
use Guzzle\Http\Message\Response;
use Guzzle\Http\Url;
use OpenCloud\Common\Constants\Size;
use OpenCloud\Common\Exceptions;
use OpenCloud\Common\Service\ServiceInterface;
use OpenCloud\ObjectStore\Constants\Header as HeaderConst;
use OpenCloud\ObjectStore\Exception\ContainerException;
use OpenCloud\ObjectStore\Exception\ObjectNotFoundException;
use OpenCloud\ObjectStore\Upload\DirectorySync;
use OpenCloud\ObjectStore\Upload\TransferBuilder;
use OpenCloud\ObjectStore\Enum\ReturnType;

/**
 * A container is a storage compartment for your data and provides a way for you
 * to organize your data. You can think of a container as a folder in Windows
 * or a directory in Unix. The primary difference between a container and these
 * other file system concepts is that containers cannot be nested.
 *
 * A container can also be CDN-enabled (for public access), in which case you
 * will need to interact with a CDNContainer object instead of this one.
 */
class Container extends AbstractContainer
{
    const METADATA_LABEL = 'Container';

    /**
     * This is the object that holds all the CDN functionality. This Container therefore acts as a simple wrapper and is
     * interested in storage concerns only.
     *
     * @var CDNContainer|null
     */
    private $cdn;

    public function __construct(ServiceInterface $service, $data = null)
    {
        parent::__construct($service, $data);

        // Set metadata items for collection listings
        if (isset($data->count)) {
            $this->metadata->setProperty('Object-Count', $data->count);
        }
        if (isset($data->bytes)) {
            $this->metadata->setProperty('Bytes-Used', $data->bytes);
        }
    }

    /**
     * Factory method that instantiates an object from a Response object.
     *
     * @param Response         $response
     * @param ServiceInterface $service
     * @return static
     */
    public static function fromResponse(Response $response, ServiceInterface $service)
    {
        $self = parent::fromResponse($response, $service);

        $segments = Url::factory($response->getEffectiveUrl())->getPathSegments();
        $self->name = end($segments);

        return $self;
    }

    /**
     * Get the CDN object.
     *
     * @return null|CDNContainer
     * @throws \OpenCloud\Common\Exceptions\CdnNotAvailableError
     */
    public function getCdn()
    {
        if (!$this->isCdnEnabled()) {
            throw new Exceptions\CdnNotAvailableError(
                'Either this container is not CDN-enabled or the CDN is not available'
            );
        }

        return $this->cdn;
    }

    /**
     * It would be awesome to put these convenience methods (which are identical to the ones in the Account object) in
     * a trait, but we have to wait for v5.3 EOL first...
     *
     * @return null|string|int
     */
    public function getObjectCount()
    {
        return $this->metadata->getProperty('Object-Count');
    }

    /**
     * @return null|string|int
     */
    public function getBytesUsed()
    {
        return $this->metadata->getProperty('Bytes-Used');
    }

    /**
     * @param $value
     * @return mixed
     */
    public function setCountQuota($value)
    {
        $this->metadata->setProperty('Quota-Count', $value);

        return $this->saveMetadata($this->metadata->toArray());
    }

    /**
     * @return null|string|int
     */
    public function getCountQuota()
    {
        return $this->metadata->getProperty('Quota-Count');
    }

    /**
     * @param $value
     * @return mixed
     */
    public function setBytesQuota($value)
    {
        $this->metadata->setProperty('Quota-Bytes', $value);

        return $this->saveMetadata($this->metadata->toArray());
    }

    /**
     * @return null|string|int
     */
    public function getBytesQuota()
    {
        return $this->metadata->getProperty('Quota-Bytes');
    }

    public function delete($deleteObjects = false)
    {
        if ($deleteObjects === true) {
            // Delegate to auxiliary method
            return $this->deleteWithObjects();
        }

        try {
            return $this->getClient()->delete($this->getUrl())->send();
        } catch (ClientErrorResponseException $e) {
            if ($e->getResponse()->getStatusCode() == 409) {
                throw new ContainerException(sprintf(
                    'The API returned this error: %s. You might have to delete all existing objects before continuing.',
                    (string) $e->getResponse()->getBody()
                ));
            } else {
                throw $e;
            }
        }
    }

    public function deleteWithObjects($secondsToWait = null)
    {
        // If container is empty, just delete it
        $numObjects = (int) $this->retrieveMetadata()->getProperty('Object-Count');
        if (0 === $numObjects) {
            return $this->delete();
        }

        // If timeout ($secondsToWait) is not specified by caller,
        // try to estimate it based on number of objects in container
        if (null === $secondsToWait) {
            $secondsToWait = round($numObjects / 2);
        }

        // Attempt to delete all objects and container
        $endTime = time() + $secondsToWait;
        $containerDeleted = false;
        while ((time() < $endTime) && !$containerDeleted) {
            $this->deleteAllObjects();
            try {
                $response = $this->delete();
                $containerDeleted = true;
            } catch (ContainerException $e) {
                // Ignore exception and try again
            } catch (ClientErrorResponseException $e) {
                if ($e->getResponse()->getStatusCode() == 404) {
                    // Container has been deleted
                    $containerDeleted = true;
                } else {
                    throw $e;
                }
            }
        }

        if (!$containerDeleted) {
            throw new ContainerException('Container and all its objects could not be deleted.');
        }

        return $response;
    }

    /**
     * Deletes all objects that this container currently contains. Useful when doing operations (like a delete) that
     * require an empty container first.
     *
     * @return mixed
     */
    public function deleteAllObjects()
    {
        $paths = array();
        $objects = $this->objectList();
        foreach ($objects as $object) {
            $paths[] = sprintf('/%s/%s', $this->getName(), $object->getName());
        }
        return $this->getService()->batchDelete($paths);
    }

    /**
     * Creates a Collection of objects in the container
     *
     * @param array $params associative array of parameter values.
     *                      * account/tenant - The unique identifier of the account/tenant.
     *                      * container- The unique identifier of the container.
     *                      * limit (Optional) - The number limit of results.
     *                      * marker (Optional) - Value of the marker, that the object names
     *                      greater in value than are returned.
     *                      * end_marker (Optional) - Value of the marker, that the object names
     *                      less in value than are returned.
     *                      * prefix (Optional) - Value of the prefix, which the returned object
     *                      names begin with.
     *                      * format (Optional) - Value of the serialized response format, either
     *                      json or xml.
     *                      * delimiter (Optional) - Value of the delimiter, that all the object
     *                      names nested in the container are returned.
     * @link   http://api.openstack.org for a list of possible parameter
     *                      names and values
     * @return \OpenCloud\Common\Collection
     * @throws ObjFetchError
     */
    public function objectList(array $params = array())
    {
        $params['format'] = 'json';

        return $this->getService()->resourceList('DataObject', $this->getUrl(null, $params), $this);
    }

    /**
     * Turn on access logs, which track all the web traffic that your data objects accrue.
     *
     * @return \Guzzle\Http\Message\Response
     */
    public function enableLogging()
    {
        return $this->saveMetadata($this->appendToMetadata(array(
            HeaderConst::ACCESS_LOGS => 'True'
        )));
    }

    /**
     * Disable access logs.
     *
     * @return \Guzzle\Http\Message\Response
     */
    public function disableLogging()
    {
        return $this->saveMetadata($this->appendToMetadata(array(
            HeaderConst::ACCESS_LOGS => 'False'
        )));
    }

    /**
     * Enable this container for public CDN access.
     *
     * @param null $ttl
     */
    public function enableCdn($ttl = null)
    {
        $headers = array('X-CDN-Enabled' => 'True');
        if ($ttl) {
            $headers['X-TTL'] = (int) $ttl;
        }

        $this->getClient()->put($this->getCdnService()->getUrl($this->name), $headers)->send();
        $this->refresh();
    }

    /**
     * Disables the containers CDN function. Note that the container will still
     * be available on the CDN until its TTL expires.
     *
     * @return \Guzzle\Http\Message\Response
     */
    public function disableCdn()
    {
        $headers = array('X-CDN-Enabled' => 'False');

        return $this->getClient()
            ->put($this->getCdnService()->getUrl($this->name), $headers)
            ->send();
    }

    public function refresh($id = null, $url = null)
    {
        $headers = $this->createRefreshRequest()->send()->getHeaders();
        $this->setMetadata($headers, true);

        try {
            if (null !== ($cdnService = $this->getService()->getCDNService())) {
                $cdn = new CDNContainer($cdnService);
                $cdn->setName($this->name);

                $response = $cdn->createRefreshRequest()->send();

                if ($response->isSuccessful()) {
                    $this->cdn = $cdn;
                    $this->cdn->setMetadata($response->getHeaders(), true);
                }
            } else {
                $this->cdn = null;
            }
        } catch (ClientErrorResponseException $e) {
        }
    }

    /**
     * Get either a fresh data object (no $info), or get an existing one by passing in data for population.
     *
     * @param  mixed $info
     * @return DataObject
     */
    public function dataObject($info = null)
    {
        return new DataObject($this, $info);
    }

    /**
     * Retrieve an object from the API. Apart from using the name as an
     * identifier, you can also specify additional headers that will be used
     * fpr a conditional GET request. These are
     *
     * * `If-Match'
     * * `If-None-Match'
     * * `If-Modified-Since'
     * * `If-Unmodified-Since'
     * * `Range'  For example:
     *      bytes=-5    would mean the last 5 bytes of the object
     *      bytes=10-15 would mean 5 bytes after a 10 byte offset
     *      bytes=32-   would mean all dat after first 32 bytes
     *
     * These are also documented in RFC 2616.
     *
     * @param string $name
     * @param array  $headers
     * @return DataObject
     */
    public function getObject($name, array $headers = array())
    {
        try {
            $response = $this->getClient()
                ->get($this->getUrl($name), $headers)
                ->send();
        } catch (BadResponseException $e) {
            if ($e->getResponse()->getStatusCode() == 404) {
                throw ObjectNotFoundException::factory($name, $e);
            }
            throw $e;
        }

        return $this->dataObject()
            ->populateFromResponse($response)
            ->setName($name);
    }

    /**
     * Essentially the same as {@see getObject()}, except only the metadata is fetched from the API.
     * This is useful for cases when the user does not want to fetch the full entity body of the
     * object, only its metadata.
     *
     * @param       $name
     * @param array $headers
     * @return $this
     */
    public function getPartialObject($name, array $headers = array())
    {
        $response = $this->getClient()
            ->head($this->getUrl($name), $headers)
            ->send();

        return $this->dataObject()
            ->populateFromResponse($response)
            ->setName($name);
    }

    /**
     * Check if an object exists inside a container. Uses {@see getPartialObject()}
     * to save on bandwidth and time.
     *
     * @param  $name    Object name
     * @return boolean  True, if object exists in this container; false otherwise.
     */
    public function objectExists($name)
    {
        try {
            // Send HEAD request to check resource existence
            $url = clone $this->getUrl();
            $url->addPath((string) $name);
            $this->getClient()->head($url)->send();
        } catch (ClientErrorResponseException $e) {
            // If a 404 was returned, then the object doesn't exist
            if ($e->getResponse()->getStatusCode() === 404) {
                return false;
            } else {
                throw $e;
            }
        }

        return true;
    }

    /**
     * Upload a single file to the API.
     *
     * @param       $name    Name that the file will be saved as in your container.
     * @param       $data    Either a string or stream representation of the file contents to be uploaded.
     * @param array $headers Optional headers that will be sent with the request (useful for object metadata).
     * @return DataObject
     */
    public function uploadObject($name, $data, array $headers = array())
    {
        $entityBody = EntityBody::factory($data);

        $url = clone $this->getUrl();
        $url->addPath($name);

        // @todo for new major release: Return response rather than populated DataObject

        $response = $this->getClient()->put($url, $headers, $entityBody)->send();

        return $this->dataObject()
            ->populateFromResponse($response)
            ->setName($name)
            ->setContent($entityBody);
    }

    /**
     * Upload an array of objects for upload. This method optimizes the upload procedure by batching requests for
     * faster execution. This is a very useful procedure when you just have a bunch of unremarkable files to be
     * uploaded quickly. Each file must be under 5GB.
     *
     * @param array $files   With the following array structure:
     *                       `name' Name that the file will be saved as in your container. Required.
     *                       `path' Path to an existing file, OR
     *                       `body' Either a string or stream representation of the file contents to be uploaded.
     * @param array $headers Optional headers that will be sent with the request (useful for object metadata).
     * @param string $returnType One of OpenCloud\ObjectStore\Enum\ReturnType::RESPONSE_ARRAY (to return an array of
     *                           Guzzle\Http\Message\Response objects) or OpenCloud\ObjectStore\Enum\ReturnType::DATA_OBJECT_ARRAY
     *                           (to return an array of OpenCloud\ObjectStore\Resource\DataObject objects).
     *
     * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError
     * @return Guzzle\Http\Message\Response[] or OpenCloud\ObjectStore\Resource\DataObject[] depending on $returnType
     */
    public function uploadObjects(array $files, array $commonHeaders = array(), $returnType = ReturnType::RESPONSE_ARRAY)
    {
        $requests = $entities = array();

        foreach ($files as $entity) {
            if (empty($entity['name'])) {
                throw new Exceptions\InvalidArgumentError('You must provide a name.');
            }

            if (!empty($entity['path']) && file_exists($entity['path'])) {
                $body = fopen($entity['path'], 'r+');
            } elseif (!empty($entity['body'])) {
                $body = $entity['body'];
            } else {
                throw new Exceptions\InvalidArgumentError('You must provide either a readable path or a body');
            }

            $entityBody = $entities[] = EntityBody::factory($body);

            // @codeCoverageIgnoreStart
            if ($entityBody->getContentLength() >= 5 * Size::GB) {
                throw new Exceptions\InvalidArgumentError(
                    'For multiple uploads, you cannot upload more than 5GB per '
                    . ' file. Use the UploadBuilder for larger files.'
                );
            }
            // @codeCoverageIgnoreEnd

            // Allow custom headers and common
            $headers = (isset($entity['headers'])) ? $entity['headers'] : $commonHeaders;

            $url = clone $this->getUrl();
            $url->addPath($entity['name']);

            $requests[] = $this->getClient()->put($url, $headers, $entityBody);
        }

        $responses = $this->getClient()->send($requests);

        if (ReturnType::RESPONSE_ARRAY === $returnType) {
            foreach ($entities as $entity) {
                $entity->close();
            }
            return $responses;
        } else {
            // Convert responses to DataObjects before returning
            $dataObjects = array();
            foreach ($responses as $index => $response) {
                $dataObjects[] = $this->dataObject()
                               ->populateFromResponse($response)
                               ->setName($files[$index]['name'])
                               ->setContent($entities[$index]);
            }
            return $dataObjects;
        }
    }

    /**
     * When uploading large files (+5GB), you need to upload the file as chunks using multibyte transfer. This method
     * sets up the transfer, and in order to execute the transfer, you need to call upload() on the returned object.
     *
     * @param array Options
     * @see \OpenCloud\ObjectStore\Upload\UploadBuilder::setOptions for a list of accepted options.
     * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError
     * @return mixed
     */
    public function setupObjectTransfer(array $options = array())
    {
        // Name is required
        if (empty($options['name'])) {
            throw new Exceptions\InvalidArgumentError('You must provide a name.');
        }

        // As is some form of entity body
        if (!empty($options['path']) && file_exists($options['path'])) {
            $body = fopen($options['path'], 'r+');
        } elseif (!empty($options['body'])) {
            $body = $options['body'];
        } else {
            throw new Exceptions\InvalidArgumentError('You must provide either a readable path or a body');
        }

        // Build upload
        $transfer = TransferBuilder::newInstance()
            ->setOption('objectName', $options['name'])
            ->setEntityBody(EntityBody::factory($body))
            ->setContainer($this);

        // Add extra options
        if (!empty($options['metadata'])) {
            $transfer->setOption('metadata', $options['metadata']);
        }
        if (!empty($options['partSize'])) {
            $transfer->setOption('partSize', $options['partSize']);
        }
        if (!empty($options['concurrency'])) {
            $transfer->setOption('concurrency', $options['concurrency']);
        }
        if (!empty($options['progress'])) {
            $transfer->setOption('progress', $options['progress']);
        }

        return $transfer->build();
    }

    /**
     * Upload the contents of a local directory to a remote container, effectively syncing them.
     *
     * @param $path The local path to the directory.
     */
    public function uploadDirectory($path)
    {
        $sync = DirectorySync::factory($path, $this);
        $sync->execute();
    }

    public function isCdnEnabled()
    {
        return ($this->cdn instanceof CDNContainer) && $this->cdn->isCdnEnabled();
    }
}
AbstractResource.php000060400000015140152446740620010537 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

use Guzzle\Http\Message\Response;
use OpenCloud\Common\Base;
use OpenCloud\Common\Service\ServiceInterface;

/**
 * Abstract base class which implements shared functionality of ObjectStore
 * resources. Provides support, for example, for metadata-handling and other
 * features that are common to the ObjectStore components.
 */
abstract class AbstractResource extends Base
{
    const GLOBAL_METADATA_PREFIX = 'X';

    /** @var \OpenCloud\Common\Metadata */
    protected $metadata;

    /** @var string The FQCN of the metadata object used for the container. */
    protected $metadataClass = 'OpenCloud\\Common\\Metadata';

    /** @var \OpenCloud\Common\Service\ServiceInterface The service object. */
    protected $service;

    public function __construct(ServiceInterface $service)
    {
        $this->service = $service;
        $this->metadata = new $this->metadataClass;
    }

    public function getService()
    {
        return $this->service;
    }

    public function getCdnService()
    {
        return $this->service->getCDNService();
    }

    public function getClient()
    {
        return $this->service->getClient();
    }

    /**
     * Factory method that allows for easy instantiation from a Response object.
     *
     * @param Response         $response
     * @param ServiceInterface $service
     * @return static
     */
    public static function fromResponse(Response $response, ServiceInterface $service)
    {
        $object = new static($service);

        if (null !== ($headers = $response->getHeaders())) {
            $object->setMetadata($headers, true);
        }

        return $object;
    }

    /**
     * Trim headers of their resource-specific prefixes.
     *
     * @param  $headers
     * @return array
     */
    public static function trimHeaders($headers)
    {
        $output = array();

        foreach ($headers as $header => $value) {
            // Only allow allow X-<keyword>-* headers to pass through after stripping them
            if (static::headerIsValidMetadata($header) && ($key = self::stripPrefix($header))) {
                $output[$key] = (string) $value;
            }
        }

        return $output;
    }

    protected static function headerIsValidMetadata($header)
    {
        $pattern = sprintf('#^%s\-#i', self::GLOBAL_METADATA_PREFIX);

        return preg_match($pattern, $header);
    }

    /**
     * Strip an individual header name of its resource-specific prefix.
     *
     * @param $header
     * @return mixed
     */
    protected static function stripPrefix($header)
    {
        $pattern = '#^' . self::GLOBAL_METADATA_PREFIX . '\-(' . static::METADATA_LABEL . '-)?(Meta-)?#i';

        return preg_replace($pattern, '', $header);
    }

    /**
     * Prepend/stock the header names with a resource-specific prefix.
     *
     * @param array $headers
     * @return array
     */
    public static function stockHeaders(array $headers)
    {
        $output = array();
        $prefix = null;
        $corsHeaders = array(
            'Access-Control-Allow-Origin',
            'Access-Control-Expose-Headers',
            'Access-Control-Max-Age',
            'Access-Control-Allow-Credentials',
            'Access-Control-Allow-Methods',
            'Access-Control-Allow-Headers'
        );
        foreach ($headers as $header => $value) {
            if (!in_array($header, $corsHeaders)) {
                $prefix = self::GLOBAL_METADATA_PREFIX . '-' . static::METADATA_LABEL . '-Meta-';
            }
            $output[$prefix . $header] = $value;
        }

        return $output;
    }

    /**
     * Set the metadata (local-only) for this object.
     *
     * @param      $data
     * @param bool $constructFromResponse
     * @return $this
     */
    public function setMetadata($data, $constructFromResponse = false)
    {
        if ($constructFromResponse) {
            $metadata = new $this->metadataClass;
            $metadata->setArray(self::trimHeaders($data));
            $data = $metadata;
        }

        $this->metadata = $data;

        return $this;
    }

    /**
     * @return \OpenCloud\Common\Metadata
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * Push local metadata to the API, thereby executing a permanent save.
     *
     * @param array $metadata    The array of values you want to set as metadata
     * @param bool  $stockPrefix Whether to prepend each array key with the metadata-specific prefix. For objects, this
     *                           would be X-Object-Meta-Foo => Bar
     * @return mixed
     */
    public function saveMetadata(array $metadata, $stockPrefix = true)
    {
        $headers = ($stockPrefix === true) ? self::stockHeaders($metadata) : $metadata;

        return $this->getClient()->post($this->getUrl(), $headers)->send();
    }

    /**
     * Retrieve metadata from the API. This method will then set and return this value.
     *
     * @return \OpenCloud\Common\Metadata
     */
    public function retrieveMetadata()
    {
        $response = $this->getClient()
            ->head($this->getUrl())
            ->send();

        $this->setMetadata($response->getHeaders(), true);

        return $this->metadata;
    }

    /**
     * To delete or unset a particular metadata item.
     *
     * @param $key
     * @return mixed
     */
    public function unsetMetadataItem($key)
    {
        $header = sprintf('%s-Remove-%s-Meta-%s', self::GLOBAL_METADATA_PREFIX,
            static::METADATA_LABEL, $key);

        $headers = array($header => 'True');

        return $this->getClient()
            ->post($this->getUrl(), $headers)
            ->send();
    }

    /**
     * Append a particular array of values to the existing metadata. Analogous to a merge.
     *
     * @param array $values
     * @return array
     */
    public function appendToMetadata(array $values)
    {
        return (!empty($this->metadata) && is_array($this->metadata))
            ? array_merge($this->metadata, $values)
            : $values;
    }
}
AbstractContainer.php000060400000010032152446740620010665 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

use OpenCloud\Common\Exceptions;
use OpenCloud\Common\Service\ServiceInterface;
use OpenCloud\ObjectStore\Constants\Header as HeaderConst;

/**
 * Abstract class holding shared functionality for containers.
 */
abstract class AbstractContainer extends AbstractResource
{
    protected $metadataClass = 'OpenCloud\\ObjectStore\\Resource\\ContainerMetadata';

    /**
     * The name of the container.
     *
     * The only restrictions on container names is that they cannot contain a
     * forward slash (/) and must be less than 256 bytes in length. Please note
     * that the length restriction applies to the name after it has been URL
     * encoded. For example, a container named Course Docs would be URL encoded
     * as Course%20Docs - which is 13 bytes in length rather than the expected 11.
     *
     * @var string
     */
    public $name;

    public function __construct(ServiceInterface $service, $data = null)
    {
        $this->service = $service;
        $this->metadata = new $this->metadataClass;

        // Populate data if set
        $this->populate($data);
    }

    public function getTransId()
    {
        return $this->metadata->getProperty(HeaderConst::TRANS_ID);
    }

    abstract public function isCdnEnabled();

    public function hasLogRetention()
    {
        if ($this instanceof CDNContainer) {
            return $this->metadata->getProperty(HeaderConst::LOG_RETENTION) == 'True';
        } else {
            return $this->metadata->propertyExists(HeaderConst::ACCESS_LOGS);
        }
    }

    public function primaryKeyField()
    {
        return 'name';
    }

    public function getUrl($path = null, array $params = array())
    {
        if (strlen($this->getName()) == 0) {
            throw new Exceptions\NoNameError('Container does not have a name');
        }

        $url = $this->getService()->getUrl();

        return $url->addPath((string) $this->getName())->addPath((string) $path)->setQuery($params);
    }

    protected function createRefreshRequest()
    {
        return $this->getClient()->head($this->getUrl(), array('Accept' => '*/*'));
    }

    /**
     * This method will enable your CDN-enabled container to serve out HTML content like a website.
     *
     * @param $indexPage The data object name (i.e. a .html file) that will serve as the main index page.
     * @return \Guzzle\Http\Message\Response
     */
    public function setStaticIndexPage($page)
    {
        if ($this instanceof CDNContainer) {
            $this->getLogger()->warning(
                'This method cannot be called on the CDN object - please execute it on the normal Container'
            );
        }

        $headers = array('X-Container-Meta-Web-Index' => $page);

        return $this->getClient()->post($this->getUrl(), $headers)->send();
    }

    /**
     * Set the default error page for your static site.
     *
     * @param $name The data object name (i.e. a .html file) that will serve as the main error page.
     * @return \Guzzle\Http\Message\Response
     */
    public function setStaticErrorPage($page)
    {
        if ($this instanceof CDNContainer) {
            $this->getLogger()->warning(
                'This method cannot be called on the CDN object - please execute it on the normal Container'
            );
        }

        $headers = array('X-Container-Meta-Web-Error' => $page);

        return $this->getClient()->post($this->getUrl(), $headers)->send();
    }
}
DataObject.php000060400000026326152446740620007274 0ustar00<?php
/**
 * Copyright 2012-2014 Rackspace US, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

namespace OpenCloud\ObjectStore\Resource;

use Guzzle\Http\EntityBody;
use Guzzle\Http\Message\Response;
use Guzzle\Http\Url;
use OpenCloud\Common\Constants\Header as HeaderConst;
use OpenCloud\Common\Exceptions;
use OpenCloud\Common\Lang;
use OpenCloud\ObjectStore\Constants\UrlType;

/**
 * Objects are the basic storage entities in Cloud Files. They represent the
 * files and their optional metadata you upload to the system. When you upload
 * objects to Cloud Files, the data is stored as-is (without compression or
 * encryption) and consists of a location (container), the object's name, and
 * any metadata you assign consisting of key/value pairs.
 */
class DataObject extends AbstractResource
{
    const METADATA_LABEL = 'Object';

    /**
     * @var Container
     */
    private $container;

    /**
     * @var The file name of the object
     */
    protected $name;

    /**
     * @var EntityBody
     */
    protected $content;

    /**
     * @var bool Whether or not this object is a "pseudo-directory"
     * @link http://docs.openstack.org/trunk/openstack-object-storage/developer/content/pseudo-hierarchical-folders-directories.html
     */
    protected $directory = false;

    /**
     * @var string The object's content type
     */
    protected $contentType;

    /**
     * @var The size of this object.
     */
    protected $contentLength;

    /**
     * @var string Date of last modification.
     */
    protected $lastModified;

    /**
     * @var string Etag.
     */
    protected $etag;

    /**
     * Also need to set Container parent and handle pseudo-directories.
     * {@inheritDoc}
     *
     * @param Container $container
     * @param null      $data
     */
    public function __construct(Container $container, $data = null)
    {
        $this->setContainer($container);

        parent::__construct($container->getService());

        // For pseudo-directories, we need to ensure the name is set
        if (!empty($data->subdir)) {
            $this->setName($data->subdir)->setDirectory(true);

            return;
        }

        $this->populate($data);
    }

    /**
     * A collection list of DataObjects contains a different data structure than the one returned for the
     * "Retrieve Object" operation. So we need to stock the values differently.
     * {@inheritDoc}
     */
    public function populate($info, $setObjects = true)
    {
        parent::populate($info, $setObjects);

        if (isset($info->bytes)) {
            $this->setContentLength($info->bytes);
        }
        if (isset($info->last_modified)) {
            $this->setLastModified($info->last_modified);
        }
        if (isset($info->content_type)) {
            $this->setContentType($info->content_type);
        }
        if (isset($info->hash)) {
            $this->setEtag($info->hash);
        }
    }

    /**
     * Takes a response and stocks common values from both the body and the headers.
     *
     * @param Response $response
     * @return $this
     */
    public function populateFromResponse(Response $response)
    {
        $this->content = $response->getBody();

        $headers = $response->getHeaders();

        return $this->setMetadata($headers, true)
            ->setContentType((string) $headers[HeaderConst::CONTENT_TYPE])
            ->setLastModified((string) $headers[HeaderConst::LAST_MODIFIED])
            ->setContentLength((string) $headers[HeaderConst::CONTENT_LENGTH])
            ->setEtag((string) $headers[HeaderConst::ETAG]);
    }

    public function refresh()
    {
        $response = $this->getService()->getClient()
            ->get($this->getUrl())
            ->send();

        return $this->populateFromResponse($response);
    }

    /**
     * @param Container $container
     * @return $this
     */
    public function setContainer(Container $container)
    {
        $this->container = $container;

        return $this;
    }

    /**
     * @return Container
     */
    public function getContainer()
    {
        return $this->container;
    }

    /**
     * @param $name string
     * @return $this
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * @param $directory bool
     * @return $this
     */
    public function setDirectory($directory)
    {
        $this->directory = $directory;

        return $this;
    }

    /**
     * @return bool
     */
    public function getDirectory()
    {
        return $this->directory;
    }

    /**
     * @return bool Is this data object a pseudo-directory?
     */
    public function isDirectory()
    {
        return (bool) $this->directory;
    }

    /**
     * @param  mixed $content
     * @return $this
     */
    public function setContent($content)
    {
        $this->etag = null;
        $this->contentType = null;
        $this->content = EntityBody::factory($content);

        return $this;
    }

    /**
     * @return EntityBody
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * @param  string $contentType
     * @return $this
     */
    public function setContentType($contentType)
    {
        $this->contentType = $contentType;

        return $this;
    }

    /**
     * @return null|string
     */
    public function getContentType()
    {
        return $this->contentType ? : $this->content->getContentType();
    }

    /**
     * @param $contentType int
     * @return $this
     */
    public function setContentLength($contentLength)
    {
        $this->contentLength = $contentLength;

        return $this;
    }

    /**
     * @return int
     */
    public function getContentLength()
    {
        return $this->contentLength !== null ? $this->contentLength : $this->content->getContentLength();
    }

    /**
     * @param $etag
     * @return $this
     */
    public function setEtag($etag)
    {
        $this->etag = $etag;

        return $this;
    }

    /**
     * @return null|string
     */
    public function getEtag()
    {
        return $this->etag ? : $this->content->getContentMd5();
    }

    public function setLastModified($lastModified)
    {
        $this->lastModified = $lastModified;

        return $this;
    }

    public function getLastModified()
    {
        return $this->lastModified;
    }

    public function primaryKeyField()
    {
        return 'name';
    }

    public function getUrl($path = null, array $params = array())
    {
        if (!$this->name) {
            throw new Exceptions\NoNameError(Lang::translate('Object has no name'));
        }

        return $this->container->getUrl($this->name);
    }

    public function update($params = array())
    {
        $metadata = is_array($this->metadata) ? $this->metadata : $this->metadata->toArray();
        $metadata = self::stockHeaders($metadata);

        // merge specific properties with metadata
        $metadata += array(
            HeaderConst::CONTENT_TYPE   => $this->contentType,
            HeaderConst::LAST_MODIFIED  => $this->lastModified,
            HeaderConst::CONTENT_LENGTH => $this->contentLength,
            HeaderConst::ETAG           => $this->etag
        );

        return $this->container->uploadObject($this->name, $this->content, $metadata);
    }

    /**
     * @param string $destination Path (`container/object') of new object
     * @return \Guzzle\Http\Message\Response
     */
    public function copy($destination)
    {
        return $this->getService()
            ->getClient()
            ->createRequest('COPY', $this->getUrl(), array(
                'Destination' => (string) $destination
            ))
            ->send();
    }

    public function delete($params = array())
    {
        return $this->getService()->getClient()->delete($this->getUrl())->send();
    }

    /**
     * Get a temporary URL for this object.
     *
     * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/TempURL-d1a4450.html
     *
     * @param $expires Expiration time in seconds
     * @param $method  What method can use this URL? (`GET' or `PUT')
     * @return string
     * @throws \OpenCloud\Common\Exceptions\InvalidArgumentError
     * @throws \OpenCloud\Common\Exceptions\ObjectError
     *
     */
    public function getTemporaryUrl($expires, $method)
    {
        $method = strtoupper($method);
        $expiry = time() + (int) $expires;

        // check for proper method
        if ($method != 'GET' && $method != 'PUT') {
            throw new Exceptions\InvalidArgumentError(sprintf(
                'Bad method [%s] for TempUrl; only GET or PUT supported',
                $method
            ));
        }

        // @codeCoverageIgnoreStart
        if (!($secret = $this->getService()->getAccount()->getTempUrlSecret())) {
            throw new Exceptions\ObjectError('Cannot produce temporary URL without an account secret.');
        }
        // @codeCoverageIgnoreEnd

        $url = $this->getUrl();
        $urlPath = urldecode($url->getPath());
        $body = sprintf("%s\n%d\n%s", $method, $expiry, $urlPath);
        $hash = hash_hmac('sha1', $body, $secret);

        return sprintf('%s?temp_url_sig=%s&temp_url_expires=%d', $url, $hash, $expiry);
    }

    /**
     * Remove this object from the CDN.
     *
     * @param null $email
     * @return mixed
     */
    public function purge($email = null)
    {
        if (!$cdn = $this->getContainer()->getCdn()) {
            return false;
        }

        $url = clone $cdn->getUrl();
        $url->addPath($this->name);

        $headers = ($email !== null) ? array('X-Purge-Email' => $email) : array();

        return $this->getService()
            ->getClient()
            ->delete($url, $headers)
            ->send();
    }

    /**
     * @param string $type
     * @return bool|Url
     */
    public function getPublicUrl($type = UrlType::CDN)
    {
        $cdn = $this->container->getCdn();

        switch ($type) {
            case UrlType::CDN:
                $uri = $cdn->getCdnUri();
                break;
            case UrlType::SSL:
                $uri = $cdn->getCdnSslUri();
                break;
            case UrlType::STREAMING:
                $uri = $cdn->getCdnStreamingUri();
                break;
            case UrlType::IOS_STREAMING:
                $uri = $cdn->getIosStreamingUri();
                break;
        }

        return (isset($uri)) ? Url::factory($uri)->addPath($this->name) : false;
    }

    protected static function headerIsValidMetadata($header)
    {
        $pattern = sprintf('#^%s-%s-Meta-#i', self::GLOBAL_METADATA_PREFIX, self::METADATA_LABEL);

        return preg_match($pattern, $header);
    }
}
Model.php000060400000004016152447302130006313 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Common\Collection;
use Guzzle\Service\Description\Parameter;

/**
 * Default model created when commands create service description model responses
 */
class Model extends Collection
{
    /** @var Parameter Structure of the model */
    protected $structure;

    /**
     * @param array     $data      Data contained by the model
     * @param Parameter $structure The structure of the model
     */
    public function __construct(array $data = array(), Parameter $structure = null)
    {
        $this->data = $data;
        $this->structure = $structure;
    }

    /**
     * Get the structure of the model
     *
     * @return Parameter
     */
    public function getStructure()
    {
        return $this->structure ?: new Parameter();
    }

    /**
     * Provides debug information about the model object
     *
     * @return string
     */
    public function __toString()
    {
        $output = 'Debug output of ';
        if ($this->structure) {
            $output .= $this->structure->getName() . ' ';
        }
        $output .= 'model';
        $output = str_repeat('=', strlen($output)) . "\n" . $output . "\n" . str_repeat('=', strlen($output)) . "\n\n";
        $output .= "Model data\n-----------\n\n";
        $output .= "This data can be retrieved from the model object using the get() method of the model "
            . "(e.g. \$model->get(\$key)) or accessing the model like an associative array (e.g. \$model['key']).\n\n";
        $lines = array_slice(explode("\n", trim(print_r($this->toArray(), true))), 2, -1);
        $output .=  implode("\n", $lines);

        if ($this->structure) {
            $output .= "\n\nModel structure\n---------------\n\n";
            $output .= "The following JSON document defines how the model was parsed from an HTTP response into the "
                . "associative array structure you see above.\n\n";
            $output .= '  ' . json_encode($this->structure->toArray()) . "\n\n";
        }

        return $output . "\n";
    }
}
MapResourceIteratorFactory.php000060400000001610152447302130012537 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Service\Command\CommandInterface;

/**
 * Resource iterator factory used when explicitly mapping strings to iterator classes
 */
class MapResourceIteratorFactory extends AbstractResourceIteratorFactory
{
    /** @var array Associative array mapping iterator names to class names */
    protected $map;

    /** @param array $map Associative array mapping iterator names to class names */
    public function __construct(array $map)
    {
        $this->map = $map;
    }

    public function getClassName(CommandInterface $command)
    {
        $className = $command->getName();

        if (isset($this->map[$className])) {
            return $this->map[$className];
        } elseif (isset($this->map['*'])) {
            // If a wildcard was added, then always use that
            return $this->map['*'];
        }

        return null;
    }
}
ResourceIteratorInterface.php000060400000003403152447302130012374 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Common\HasDispatcherInterface;
use Guzzle\Common\ToArrayInterface;

/**
 * Iterates over a paginated resource using subsequent requests in order to retrieve the entire matching result set
 */
interface ResourceIteratorInterface extends ToArrayInterface, HasDispatcherInterface, \Iterator, \Countable
{
    /**
     * Retrieve the NextToken that can be used in other iterators.
     *
     * @return string Returns a NextToken
     */
    public function getNextToken();

    /**
     * Attempt to limit the total number of resources returned by the iterator.
     *
     * You may still receive more items than you specify. Set to 0 to specify no limit.
     *
     * @param int $limit Limit amount
     *
     * @return ResourceIteratorInterface
     */
    public function setLimit($limit);

    /**
     * Attempt to limit the total number of resources retrieved per request by  the iterator.
     *
     * The iterator may return more than you specify in the page size argument depending on the service and underlying
     * command implementation.  Set to 0 to specify no page size limitation.
     *
     * @param int $pageSize Limit amount
     *
     * @return ResourceIteratorInterface
     */
    public function setPageSize($pageSize);

    /**
     * Get a data option from the iterator
     *
     * @param string $key Key of the option to retrieve
     *
     * @return mixed|null Returns NULL if not set or the value if set
     */
    public function get($key);

    /**
     * Set a data option on the iterator
     *
     * @param string $key   Key of the option to set
     * @param mixed  $value Value to set for the option
     *
     * @return ResourceIteratorInterface
     */
    public function set($key, $value);
}
AbstractResourceIteratorFactory.php000060400000002025152447302130013566 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Common\Exception\InvalidArgumentException;
use Guzzle\Service\Command\CommandInterface;

/**
 * Abstract resource iterator factory implementation
 */
abstract class AbstractResourceIteratorFactory implements ResourceIteratorFactoryInterface
{
    public function build(CommandInterface $command, array $options = array())
    {
        if (!$this->canBuild($command)) {
            throw new InvalidArgumentException('Iterator was not found for ' . $command->getName());
        }

        $className = $this->getClassName($command);

        return new $className($command, $options);
    }

    public function canBuild(CommandInterface $command)
    {
        return (bool) $this->getClassName($command);
    }

    /**
     * Get the name of the class to instantiate for the command
     *
     * @param CommandInterface $command Command that is associated with the iterator
     *
     * @return string
     */
    abstract protected function getClassName(CommandInterface $command);
}
ResourceIteratorClassFactory.php000060400000003710152447302130013072 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Inflection\InflectorInterface;
use Guzzle\Inflection\Inflector;
use Guzzle\Service\Command\CommandInterface;

/**
 * Factory for creating {@see ResourceIteratorInterface} objects using a convention of storing iterator classes under a
 * root namespace using the name of a {@see CommandInterface} object as a convention for determining the name of an
 * iterator class. The command name is converted to CamelCase and Iterator is appended (e.g. abc_foo => AbcFoo).
 */
class ResourceIteratorClassFactory extends AbstractResourceIteratorFactory
{
    /** @var array List of namespaces used to look for classes */
    protected $namespaces;

    /** @var InflectorInterface Inflector used to determine class names */
    protected $inflector;

    /**
     * @param string|array       $namespaces List of namespaces for iterator objects
     * @param InflectorInterface $inflector  Inflector used to resolve class names
     */
    public function __construct($namespaces = array(), InflectorInterface $inflector = null)
    {
        $this->namespaces = (array) $namespaces;
        $this->inflector = $inflector ?: Inflector::getDefault();
    }

    /**
     * Registers a namespace to check for Iterators
     *
     * @param string $namespace Namespace which contains Iterator classes
     *
     * @return self
     */
    public function registerNamespace($namespace)
    {
        array_unshift($this->namespaces, $namespace);

        return $this;
    }

    protected function getClassName(CommandInterface $command)
    {
        $iteratorName = $this->inflector->camel($command->getName()) . 'Iterator';

        // Determine the name of the class to load
        foreach ($this->namespaces as $namespace) {
            $potentialClassName = $namespace . '\\' . $iteratorName;
            if (class_exists($potentialClassName)) {
                return $potentialClassName;
            }
        }

        return false;
    }
}
CompositeResourceIteratorFactory.php000060400000003357152447302130013776 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Common\Exception\InvalidArgumentException;
use Guzzle\Service\Command\CommandInterface;

/**
 * Factory that utilizes multiple factories for creating iterators
 */
class CompositeResourceIteratorFactory implements ResourceIteratorFactoryInterface
{
    /** @var array Array of factories */
    protected $factories;

    /** @param array $factories Array of factories used to instantiate iterators */
    public function __construct(array $factories)
    {
        $this->factories = $factories;
    }

    public function build(CommandInterface $command, array $options = array())
    {
        if (!($factory = $this->getFactory($command))) {
            throw new InvalidArgumentException('Iterator was not found for ' . $command->getName());
        }

        return $factory->build($command, $options);
    }

    public function canBuild(CommandInterface $command)
    {
        return $this->getFactory($command) !== false;
    }

    /**
     * Add a factory to the composite factory
     *
     * @param ResourceIteratorFactoryInterface $factory Factory to add
     *
     * @return self
     */
    public function addFactory(ResourceIteratorFactoryInterface $factory)
    {
        $this->factories[] = $factory;

        return $this;
    }

    /**
     * Get the factory that matches the command object
     *
     * @param CommandInterface $command Command retrieving the iterator for
     *
     * @return ResourceIteratorFactoryInterface|bool
     */
    protected function getFactory(CommandInterface $command)
    {
        foreach ($this->factories as $factory) {
            if ($factory->canBuild($command)) {
                return $factory;
            }
        }

        return false;
    }
}
ResourceIteratorFactoryInterface.php000060400000001425152447302130013726 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Service\Command\CommandInterface;

/**
 * Factory for creating {@see ResourceIteratorInterface} objects
 */
interface ResourceIteratorFactoryInterface
{
    /**
     * Create a resource iterator
     *
     * @param CommandInterface $command Command to create an iterator for
     * @param array                 $options Iterator options that are exposed as data.
     *
     * @return ResourceIteratorInterface
     */
    public function build(CommandInterface $command, array $options = array());

    /**
     * Check if the factory can create an iterator
     *
     * @param CommandInterface $command Command to create an iterator for
     *
     * @return bool
     */
    public function canBuild(CommandInterface $command);
}
ResourceIterator.php000060400000016534152447302130010564 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Common\AbstractHasDispatcher;
use Guzzle\Service\Command\CommandInterface;

abstract class ResourceIterator extends AbstractHasDispatcher implements ResourceIteratorInterface
{
    /** @var CommandInterface Command used to send requests */
    protected $command;

    /** @var CommandInterface First sent command */
    protected $originalCommand;

    /** @var array Currently loaded resources */
    protected $resources;

    /** @var int Total number of resources that have been retrieved */
    protected $retrievedCount = 0;

    /** @var int Total number of resources that have been iterated */
    protected $iteratedCount = 0;

    /** @var string NextToken/Marker for a subsequent request */
    protected $nextToken = false;

    /** @var int Maximum number of resources to fetch per request */
    protected $pageSize;

    /** @var int Maximum number of resources to retrieve in total */
    protected $limit;

    /** @var int Number of requests sent */
    protected $requestCount = 0;

    /** @var array Initial data passed to the constructor */
    protected $data = array();

    /** @var bool Whether or not the current value is known to be invalid */
    protected $invalid;

    public static function getAllEvents()
    {
        return array(
            // About to issue another command to get more results
            'resource_iterator.before_send',
            // Issued another command to get more results
            'resource_iterator.after_send'
        );
    }

    /**
     * @param CommandInterface $command Initial command used for iteration
     * @param array            $data    Associative array of additional parameters. You may specify any number of custom
     *     options for an iterator. Among these options, you may also specify the following values:
     *     - limit: Attempt to limit the maximum number of resources to this amount
     *     - page_size: Attempt to retrieve this number of resources per request
     */
    public function __construct(CommandInterface $command, array $data = array())
    {
        // Clone the command to keep track of the originating command for rewind
        $this->originalCommand = $command;

        // Parse options from the array of options
        $this->data = $data;
        $this->limit = array_key_exists('limit', $data) ? $data['limit'] : 0;
        $this->pageSize = array_key_exists('page_size', $data) ? $data['page_size'] : false;
    }

    /**
     * Get all of the resources as an array (Warning: this could issue a large number of requests)
     *
     * @return array
     */
    public function toArray()
    {
        return iterator_to_array($this, false);
    }

    public function setLimit($limit)
    {
        $this->limit = $limit;
        $this->resetState();

        return $this;
    }

    public function setPageSize($pageSize)
    {
        $this->pageSize = $pageSize;
        $this->resetState();

        return $this;
    }

    /**
     * Get an option from the iterator
     *
     * @param string $key Key of the option to retrieve
     *
     * @return mixed|null Returns NULL if not set or the value if set
     */
    public function get($key)
    {
        return array_key_exists($key, $this->data) ? $this->data[$key] : null;
    }

    /**
     * Set an option on the iterator
     *
     * @param string $key   Key of the option to set
     * @param mixed  $value Value to set for the option
     *
     * @return ResourceIterator
     */
    public function set($key, $value)
    {
        $this->data[$key] = $value;

        return $this;
    }

    public function current()
    {
        return $this->resources ? current($this->resources) : false;
    }

    public function key()
    {
        return max(0, $this->iteratedCount - 1);
    }

    public function count()
    {
        return $this->retrievedCount;
    }

    /**
     * Get the total number of requests sent
     *
     * @return int
     */
    public function getRequestCount()
    {
        return $this->requestCount;
    }

    /**
     * Rewind the Iterator to the first element and send the original command
     */
    public function rewind()
    {
        // Use the original command
        $this->command = clone $this->originalCommand;
        $this->resetState();
        $this->next();
    }

    public function valid()
    {
        return !$this->invalid && (!$this->resources || $this->current() || $this->nextToken)
            && (!$this->limit || $this->iteratedCount < $this->limit + 1);
    }

    public function next()
    {
        $this->iteratedCount++;

        // Check if a new set of resources needs to be retrieved
        $sendRequest = false;
        if (!$this->resources) {
            $sendRequest = true;
        } else {
            // iterate over the internal array
            $current = next($this->resources);
            $sendRequest = $current === false && $this->nextToken && (!$this->limit || $this->iteratedCount < $this->limit + 1);
        }

        if ($sendRequest) {

            $this->dispatch('resource_iterator.before_send', array(
                'iterator'  => $this,
                'resources' => $this->resources
            ));

            // Get a new command object from the original command
            $this->command = clone $this->originalCommand;
            // Send a request and retrieve the newly loaded resources
            $this->resources = $this->sendRequest();
            $this->requestCount++;

            // If no resources were found, then the last request was not needed
            // and iteration must stop
            if (empty($this->resources)) {
                $this->invalid = true;
            } else {
                // Add to the number of retrieved resources
                $this->retrievedCount += count($this->resources);
                // Ensure that we rewind to the beginning of the array
                reset($this->resources);
            }

            $this->dispatch('resource_iterator.after_send', array(
                'iterator'  => $this,
                'resources' => $this->resources
            ));
        }
    }

    /**
     * Retrieve the NextToken that can be used in other iterators.
     *
     * @return string Returns a NextToken
     */
    public function getNextToken()
    {
        return $this->nextToken;
    }

    /**
     * Returns the value that should be specified for the page size for a request that will maintain any hard limits,
     * but still honor the specified pageSize if the number of items retrieved + pageSize < hard limit
     *
     * @return int Returns the page size of the next request.
     */
    protected function calculatePageSize()
    {
        if ($this->limit && $this->iteratedCount + $this->pageSize > $this->limit) {
            return 1 + ($this->limit - $this->iteratedCount);
        }

        return (int) $this->pageSize;
    }

    /**
     * Reset the internal state of the iterator without triggering a rewind()
     */
    protected function resetState()
    {
        $this->iteratedCount = 0;
        $this->retrievedCount = 0;
        $this->nextToken = false;
        $this->resources = null;
        $this->invalid = false;
    }

    /**
     * Send a request to retrieve the next page of results. Hook for subclasses to implement.
     *
     * @return array Returns the newly loaded resources
     */
    abstract protected function sendRequest();
}
ResourceIteratorApplyBatched.php000060400000006523152447302130013042 0ustar00<?php

namespace Guzzle\Service\Resource;

use Guzzle\Common\AbstractHasDispatcher;
use Guzzle\Batch\BatchBuilder;
use Guzzle\Batch\BatchSizeDivisor;
use Guzzle\Batch\BatchClosureTransfer;
use Guzzle\Common\Version;

/**
 * Apply a callback to the contents of a {@see ResourceIteratorInterface}
 * @deprecated Will be removed in a future version and is no longer maintained. Use the Batch\ abstractions instead.
 * @codeCoverageIgnore
 */
class ResourceIteratorApplyBatched extends AbstractHasDispatcher
{
    /** @var callable|array */
    protected $callback;

    /** @var ResourceIteratorInterface */
    protected $iterator;

    /** @var integer Total number of sent batches */
    protected $batches = 0;

    /** @var int Total number of iterated resources */
    protected $iterated = 0;

    public static function getAllEvents()
    {
        return array(
            // About to send a batch of requests to the callback
            'iterator_batch.before_batch',
            // Finished sending a batch of requests to the callback
            'iterator_batch.after_batch',
            // Created the batch object
            'iterator_batch.created_batch'
        );
    }

    /**
     * @param ResourceIteratorInterface $iterator Resource iterator to apply a callback to
     * @param array|callable            $callback Callback method accepting the resource iterator
     *                                            and an array of the iterator's current resources
     */
    public function __construct(ResourceIteratorInterface $iterator, $callback)
    {
        $this->iterator = $iterator;
        $this->callback = $callback;
        Version::warn(__CLASS__ . ' is deprecated');
    }

    /**
     * Apply the callback to the contents of the resource iterator
     *
     * @param int $perBatch The number of records to group per batch transfer
     *
     * @return int Returns the number of iterated resources
     */
    public function apply($perBatch = 50)
    {
        $this->iterated = $this->batches = $batches = 0;
        $that = $this;
        $it = $this->iterator;
        $callback = $this->callback;

        $batch = BatchBuilder::factory()
            ->createBatchesWith(new BatchSizeDivisor($perBatch))
            ->transferWith(new BatchClosureTransfer(function (array $batch) use ($that, $callback, &$batches, $it) {
                $batches++;
                $that->dispatch('iterator_batch.before_batch', array('iterator' => $it, 'batch' => $batch));
                call_user_func_array($callback, array($it, $batch));
                $that->dispatch('iterator_batch.after_batch', array('iterator' => $it, 'batch' => $batch));
            }))
            ->autoFlushAt($perBatch)
            ->build();

        $this->dispatch('iterator_batch.created_batch', array('batch' => $batch));

        foreach ($this->iterator as $resource) {
            $this->iterated++;
            $batch->add($resource);
        }

        $batch->flush();
        $this->batches = $batches;

        return $this->iterated;
    }

    /**
     * Get the total number of batches sent
     *
     * @return int
     */
    public function getBatchCount()
    {
        return $this->batches;
    }

    /**
     * Get the total number of iterated resources
     *
     * @return int
     */
    public function getIteratedCount()
    {
        return $this->iterated;
    }
}

Al-HUWAITI Shell