Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore')
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/AbstractService.php57
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/CDNService.php62
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/AbstractStorageObject.php170
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/CDNContainer.php298
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/Container.php401
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/DataObject.php941
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Service.php115
7 files changed, 2044 insertions, 0 deletions
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/AbstractService.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/AbstractService.php
new file mode 100644
index 00000000000..4a2298d60ed
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/AbstractService.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore;
+
+use OpenCloud\Common\Service as CommonService;
+
+define('SWIFT_MAX_OBJECT_SIZE', 5 * 1024 * 1024 * 1024 + 1);
+
+/**
+ * An abstract base class for common code shared between ObjectStore\Service
+ * (container) and ObjectStore\CDNService (CDN containers).
+ *
+ * @todo Maybe we use Traits instead of this small abstract class?
+ */
+abstract class AbstractService extends CommonService
+{
+
+ const MAX_CONTAINER_NAME_LEN = 256;
+ const MAX_OBJECT_NAME_LEN = 1024;
+ const MAX_OBJECT_SIZE = SWIFT_MAX_OBJECT_SIZE;
+
+ /**
+ * Creates a Container resource object.
+ *
+ * @param mixed $cdata The name of the container or an object from which to set values
+ * @return OpenCloud\ObjectStore\Resource\Container
+ */
+ public function container($cdata = null)
+ {
+ return new Resource\Container($this, $cdata);
+ }
+
+ /**
+ * Returns a Collection of Container objects.
+ *
+ * @param array $filter An array to filter the results
+ * @return OpenCloud\Common\Collection
+ */
+ public function containerList(array $filter = array())
+ {
+ $filter['format'] = 'json';
+
+ return $this->collection(
+ 'OpenCloud\ObjectStore\Resource\Container', $this->url(null, $filter)
+ );
+ }
+
+}
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/CDNService.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/CDNService.php
new file mode 100644
index 00000000000..132d5f47ad6
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/CDNService.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore;
+
+use OpenCloud\OpenStack;
+use OpenCloud\Common\Exceptions;
+
+/**
+ * This is the CDN version of the ObjectStore service.
+ */
+class CDNService extends AbstractService
+{
+
+ /**
+ * Creates a new CDNService object.
+ *
+ * This is a simple wrapper function around the parent Service construct,
+ * but supplies defaults for the service type.
+ *
+ * @param OpenCloud\OpenStack $connection The connection object
+ * @param string $serviceName The name of the service
+ * @param string $serviceRegion The service's region
+ * @param string $urlType The type of URL (normally 'publicURL')
+ */
+ public function __construct(
+ OpenStack $connection,
+ $serviceName = RAXSDK_OBJSTORE_NAME,
+ $serviceRegion = RAXSDK_OBJSTORE_REGION,
+ $urltype = RAXSDK_URL_PUBLIC
+ ) {
+ $this->getLogger()->info('Initializing CDN Service...');
+
+ parent::__construct(
+ $connection,
+ 'rax:object-cdn',
+ $serviceName,
+ $serviceRegion,
+ $urltype
+ );
+ }
+
+ /**
+ * Helps catch errors if someone calls the method on the
+ * wrong object
+ */
+ public function CDN()
+ {
+ throw new Exceptions\CdnError(
+ 'Invalid method call; no CDN() on the CDN object'
+ );
+ }
+
+}
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/AbstractStorageObject.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/AbstractStorageObject.php
new file mode 100644
index 00000000000..c6799b22b7e
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/AbstractStorageObject.php
@@ -0,0 +1,170 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore\Resource;
+
+use OpenCloud\Common\Base;
+use OpenCloud\Common\Metadata;
+use OpenCloud\Common\Exceptions\NameError;
+use OpenCloud\Common\Exceptions\MetadataPrefixError;
+use OpenCloud\Common\Request\Response\Http;
+
+/**
+ * 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 AbstractStorageObject extends Base
+{
+
+ const ACCOUNT_META_PREFIX = 'X-Account-';
+ const CONTAINER_META_PREFIX = 'X-Container-Meta-';
+ const OBJECT_META_PREFIX = 'X-Object-Meta-';
+ const CDNCONTAINER_META_PREFIX = 'X-Cdn-';
+
+ /**
+ * Metadata belonging to a resource.
+ *
+ * @var OpenCloud\Common\Metadata
+ */
+ public $metadata;
+
+ /**
+ * Initializes the metadata component
+ */
+ public function __construct()
+ {
+ $this->metadata = new Metadata;
+ }
+
+ /**
+ * Given an Http response object, converts the appropriate headers
+ * to metadata
+ *
+ * @param OpenCloud\Common\Request\Response\Http
+ * @return void
+ */
+ public function getMetadata(Http $response)
+ {
+ $this->metadata = new Metadata;
+ $this->metadata->setArray($response->headers(), $this->prefix());
+ }
+
+ /**
+ * If object has metadata, return an associative array of headers.
+ *
+ * For example, if a DataObject has a metadata item named 'FOO',
+ * then this would return array('X-Object-Meta-FOO'=>$value);
+ *
+ * @return array
+ */
+ public function metadataHeaders()
+ {
+ $headers = array();
+
+ // only build if we have metadata
+ if (is_object($this->metadata)) {
+ foreach ($this->metadata as $key => $value) {
+ $headers[$this->prefix() . $key] = $value;
+ }
+ }
+
+ return $headers;
+ }
+
+ /**
+ * Returns the displayable name of the object
+ *
+ * Can be overridden by child objects; *must* be overridden by child
+ * objects if the object does not have a `name` attribute defined.
+ *
+ * @api
+ * @throws NameError if attribute 'name' is not defined
+ */
+ public function name()
+ {
+ if (property_exists($this, 'name')) {
+ return $this->name;
+ } else {
+ throw new NameError(sprintf(
+ 'Name attribute does not exist for [%s]',
+ get_class($this)
+ ));
+ }
+ }
+
+ /**
+ * Override parent method.
+ *
+ * @return null
+ */
+ public static function jsonName()
+ {
+ return null;
+ }
+
+ /**
+ * Override parent method.
+ *
+ * @return null
+ */
+ public static function jsonCollectionName()
+ {
+ return null;
+ }
+
+ /**
+ * Override parent method.
+ *
+ * @return null
+ */
+ public static function jsonCollectionElement()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the proper prefix for the specified type of object
+ *
+ * @param string $type The type of object; derived from `get_class()` if not
+ * specified.
+ * @codeCoverageIgnore
+ */
+ private function prefix($type = null)
+ {
+ if ($type === null) {
+ $parts = preg_split('/\\\/', get_class($this));
+ $type = $parts[count($parts)-1];
+ }
+
+ switch($type) {
+ case 'Account':
+ $prefix = self::ACCOUNT_META_PREFIX;
+ break;
+ case 'CDNContainer':
+ $prefix = self::CDNCONTAINER_META_PREFIX;
+ break;
+ case 'Container':
+ $prefix = self::CONTAINER_META_PREFIX;
+ break;
+ case 'DataObject':
+ $prefix = self::OBJECT_META_PREFIX;
+ break;
+ default:
+ throw new MetadataPrefixError(sprintf(
+ 'Unrecognized metadata type [%s]',
+ $type
+ ));
+ }
+
+ return $prefix;
+ }
+}
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/CDNContainer.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/CDNContainer.php
new file mode 100644
index 00000000000..9b6367c87e0
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/CDNContainer.php
@@ -0,0 +1,298 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore\Resource;
+
+use OpenCloud\Common\Service as AbstractService;
+use OpenCloud\Common\Lang;
+use OpenCloud\Common\Exceptions;
+use OpenCloud\ObjectStore\AbstractService as AbstractObjectService;
+
+/**
+ * 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 AbstractStorageObject
+{
+ /**
+ * 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;
+
+ /**
+ * Count of how many objects exist in the container.
+ *
+ * @var int
+ */
+ public $count = 0;
+
+ /**
+ * The total bytes used in the container.
+ *
+ * @var int
+ */
+ public $bytes = 0;
+
+ /**
+ * The service object.
+ *
+ * @var AbstractService
+ */
+ private $service;
+
+ /**
+ * URL of the container.
+ *
+ * @var string
+ */
+ private $containerUrl;
+
+ /**
+ * Creates the container object
+ *
+ * Creates a new container object or, if the $cdata object is a string,
+ * retrieves the named container from the object store. If $cdata is an
+ * array or an object, then its values are used to set this object.
+ *
+ * @param OpenCloud\ObjectStore $service - the ObjectStore service
+ * @param mixed $cdata - if supplied, the name of the object
+ */
+ public function __construct(AbstractService $service, $cdata = null)
+ {
+ $this->getLogger()->info('Initializing CDN Container Service...');
+
+ parent::__construct();
+
+ $this->service = $service;
+
+ // Populate data if set
+ $this->populate($cdata);
+ }
+
+ /**
+ * Allow other objects to know what the primary key is.
+ *
+ * @return string
+ */
+ public function primaryKeyField()
+ {
+ return 'name';
+ }
+
+ /**
+ * Returns the Service associated with the Container
+ */
+ public function getService()
+ {
+ return $this->service;
+ }
+
+ /**
+ * Returns the URL of the container
+ *
+ * @return string
+ * @param string $subresource not used; required for compatibility
+ * @throws NoNameError
+ */
+ public function url($subresource = '')
+ {
+ if (strlen($this->name) == 0) {
+ throw new Exceptions\NoNameError(
+ Lang::translate('Container does not have an identifier')
+ );
+ }
+
+ return Lang::noslash($this->getService()->url(rawurlencode($this->name)));
+ }
+
+ /**
+ * Creates a new container with the specified attributes
+ *
+ * @param array $params array of parameters
+ * @return boolean TRUE on success; FALSE on failure
+ * @throws ContainerCreateError
+ */
+ public function create($params = array())
+ {
+ // Populate object and check container name
+ $this->populate($params);
+ $this->isValidName($this->name);
+
+ // Dispatch
+ $this->containerUrl = $this->url();
+ $response = $this->getService()->request($this->url(), 'PUT', $this->metadataHeaders());
+
+ // Check return code
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 202) {
+ throw new Exceptions\ContainerCreateError(sprintf(
+ Lang::translate('Problem creating container [%s] status [%d] response [%s]'),
+ $this->url(),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return true;
+ }
+
+ /**
+ * Updates the metadata for a container
+ *
+ * @return boolean TRUE on success; FALSE on failure
+ * @throws ContainerCreateError
+ */
+ public function update()
+ {
+ $response = $this->getService()->request($this->url(), 'POST', $this->metadataHeaders());
+
+ // check return code
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 204) {
+ throw new Exceptions\ContainerCreateError(sprintf(
+ Lang::translate('Problem updating container [%s] status [%d] response [%s]'),
+ $this->Url(),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return true;
+ }
+
+ /**
+ * Deletes the specified container
+ *
+ * @return boolean TRUE on success; FALSE on failure
+ * @throws ContainerDeleteError
+ */
+ public function delete()
+ {
+ $response = $this->getService()->request($this->url(), 'DELETE');
+
+ // validate the response code
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() == 404) {
+ throw new Exceptions\ContainerNotFoundError(sprintf(
+ Lang::translate('Container [%s] not found'),
+ $this->name
+ ));
+ }
+
+ if ($response->httpStatus() == 409) {
+ throw new Exceptions\ContainerNotEmptyError(sprintf(
+ Lang::translate('Container [%s] must be empty before deleting'),
+ $this->name
+ ));
+ }
+
+ if ($response->httpStatus() >= 300) {
+ throw new Exceptions\ContainerDeleteError(sprintf(
+ Lang::translate('Problem deleting container [%s] status [%d] response [%s]'),
+ $this->url(),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ return false;
+ }
+ // @codeCoverageIgnoreEnd
+
+ return true;
+ }
+
+ /**
+ * Loads the object from the service
+ *
+ * @return void
+ */
+ public function refresh($name = null, $url = null)
+ {
+ $response = $this->getService()->request(
+ $this->url($name), 'HEAD', array('Accept' => '*/*')
+ );
+
+ // validate the response code
+ // @codeCoverageIgnoreStart
+ if ($response->HttpStatus() == 404) {
+ throw new Exceptions\ContainerNotFoundError(sprintf(
+ 'Container [%s] (%s) not found',
+ $this->name,
+ $this->url()
+ ));
+ }
+
+ if ($response->HttpStatus() >= 300) {
+ throw new Exceptions\HttpError(sprintf(
+ 'Error retrieving Container, status [%d] response [%s]',
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+
+ // check for headers (not metadata)
+ foreach($response->headers() as $header => $value) {
+ switch($header) {
+ case 'X-Container-Object-Count':
+ $this->count = $value;
+ break;
+ case 'X-Container-Bytes-Used':
+ $this->bytes = $value;
+ break;
+ }
+ }
+ // @codeCoverageIgnoreEnd
+
+ // parse the returned object
+ $this->getMetadata($response);
+ }
+
+ /**
+ * Validates that the container name is acceptable
+ *
+ * @param string $name the container name to validate
+ * @return boolean TRUE if ok; throws an exception if not
+ * @throws ContainerNameError
+ */
+ public function isValidName($name)
+ {
+ if (strlen($name) == 0) {
+ throw new Exceptions\ContainerNameError(
+ 'Container name cannot be blank'
+ );
+ }
+
+ if (strpos($name, '/') !== false) {
+ throw new Exceptions\ContainerNameError(
+ 'Container name cannot contain "/"'
+ );
+ }
+
+ if (strlen($name) > AbstractObjectService::MAX_CONTAINER_NAME_LEN) {
+ throw new Exceptions\ContainerNameError(
+ 'Container name is too long'
+ );
+ }
+
+ return true;
+ }
+
+}
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/Container.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/Container.php
new file mode 100644
index 00000000000..3a56ebd9fca
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/Container.php
@@ -0,0 +1,401 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore\Resource;
+
+use OpenCloud\Common\Exceptions;
+use OpenCloud\Common\Lang;
+
+/**
+ * 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 CDNContainer
+{
+
+ /**
+ * CDN container (if set).
+ *
+ * @var CDNContainer|null
+ */
+ private $cdn;
+
+ /**
+ * Sets the CDN container.
+ *
+ * @param OpenCloud\ObjectStore\Resource\CDNContainer $cdn
+ */
+ public function setCDN(CDNContainer $cdn)
+ {
+ $this->cdn = $cdn;
+ }
+
+ /**
+ * Returns the CDN container.
+ *
+ * @returns CDNContainer
+ */
+ public function getCDN()
+ {
+ if (!$this->cdn) {
+ throw new Exceptions\CdnNotAvailableError(
+ Lang::translate('CDN-enabled container is not available')
+ );
+ }
+
+ return $this->cdn;
+ }
+
+ /**
+ * Backwards compatability.
+ */
+ public function CDN()
+ {
+ return $this->getCDN();
+ }
+
+ /**
+ * Makes the container public via the CDN
+ *
+ * @api
+ * @param integer $TTL the Time-To-Live for the CDN container; if NULL,
+ * then the cloud's default value will be used for caching.
+ * @throws CDNNotAvailableError if CDN services are not available
+ * @return CDNContainer
+ */
+ public function enableCDN($ttl = null)
+ {
+ $url = $this->getService()->CDN()->url() . '/' . rawurlencode($this->name);
+
+ $headers = $this->metadataHeaders();
+
+ if ($ttl) {
+
+ // Make sure we're dealing with a real figure
+ if (!is_integer($ttl)) {
+ throw new Exceptions\CdnTtlError(sprintf(
+ Lang::translate('TTL value [%s] must be an integer'),
+ $ttl
+ ));
+ }
+
+ $headers['X-TTL'] = $ttl;
+ }
+
+ $headers['X-Log-Retention'] = 'True';
+ $headers['X-CDN-Enabled'] = 'True';
+
+ // PUT to the CDN container
+ $response = $this->getService()->request($url, 'PUT', $headers);
+
+ // check the response status
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 202) {
+ throw new Exceptions\CdnHttpError(sprintf(
+ Lang::translate('HTTP error publishing to CDN, status [%d] response [%s]'),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ // refresh the data
+ $this->refresh();
+
+ // return the CDN container object
+ $cdn = new CDNContainer($this->getService()->getCDNService(), $this->name);
+ $this->setCDN($cdn);
+
+ return $cdn;
+ }
+
+ /**
+ * Backwards compatability.
+ */
+ public function publishToCDN($ttl = null)
+ {
+ return $this->enableCDN($ttl);
+ }
+
+ /**
+ * Disables the containers CDN function.
+ *
+ * Note that the container will still be available on the CDN until
+ * its TTL expires.
+ *
+ * @api
+ * @return void
+ */
+ public function disableCDN()
+ {
+ // Set necessary headers
+ $headers['X-Log-Retention'] = 'False';
+ $headers['X-CDN-Enabled'] = 'False';
+
+ // PUT it to the CDN service
+ $response = $this->getService()->request($this->CDNURL(), 'PUT', $headers);
+
+ // check the response status
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() != 201) {
+ throw new Exceptions\CdnHttpError(sprintf(
+ Lang::translate('HTTP error disabling CDN, status [%d] response [%s]'),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return true;
+ }
+
+ /**
+ * Creates a static website from the container
+ *
+ * @api
+ * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_Static_Website-dle4000.html
+ * @param string $index the index page (starting page) of the website
+ * @return \OpenCloud\HttpResponse
+ */
+ public function createStaticSite($indexHtml)
+ {
+ $headers = array('X-Container-Meta-Web-Index' => $indexHtml);
+ $response = $this->getService()->request($this->url(), 'POST', $headers);
+
+ // check return code
+ // @codeCoverageIgnoreStart
+ if ($response->HttpStatus() > 204) {
+ throw new Exceptions\ContainerError(sprintf(
+ Lang::translate('Error creating static website for [%s], status [%d] response [%s]'),
+ $this->name,
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $response;
+ }
+
+ /**
+ * Sets the error page(s) for the static website
+ *
+ * @api
+ * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Error_Pages_for_Static_Website-dle4005.html
+ * @param string $name the name of the error page
+ * @return \OpenCloud\HttpResponse
+ */
+ public function staticSiteErrorPage($name)
+ {
+ $headers = array('X-Container-Meta-Web-Error' => $name);
+ $response = $this->getService()->request($this->url(), 'POST', $headers);
+
+ // check return code
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 204) {
+ throw new Exceptions\ContainerError(sprintf(
+ Lang::translate('Error creating static site error page for [%s], status [%d] response [%s]'),
+ $this->name,
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+
+ return $response;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Returns the CDN URL of the container (if enabled)
+ *
+ * The CDNURL() is used to manage the container. Note that it is different
+ * from the PublicURL() of the container, which is the publicly-accessible
+ * URL on the network.
+ *
+ * @api
+ * @return string
+ */
+ public function CDNURL()
+ {
+ return $this->getCDN()->url();
+ }
+
+ /**
+ * Returns the Public URL of the container (on the CDN network)
+ *
+ */
+ public function publicURL()
+ {
+ return $this->CDNURI();
+ }
+
+ /**
+ * Returns the CDN info about the container
+ *
+ * @api
+ * @return stdClass
+ */
+ public function CDNinfo($property = null)
+ {
+ // Not quite sure why this is here...
+ // @codeCoverageIgnoreStart
+ if ($this->getService() instanceof CDNService) {
+ return $this->metadata;
+ }
+ // @codeCoverageIgnoreEnd
+
+ // return NULL if the CDN container is not enabled
+ if (!isset($this->getCDN()->metadata->Enabled)
+ || $this->getCDN()->metadata->Enabled == 'False'
+ ) {
+ return null;
+ }
+
+ // check to see if it's set
+ if (isset($this->getCDN()->metadata->$property)) {
+ return trim($this->getCDN()->metadata->$property);
+ } elseif ($property !== null) {
+ return null;
+ }
+
+ // otherwise, return the whole metadata object
+ return $this->getCDN()->metadata;
+ }
+
+ /**
+ * Returns the CDN container URI prefix
+ *
+ * @api
+ * @return string
+ */
+ public function CDNURI()
+ {
+ return $this->CDNinfo('Uri');
+ }
+
+ /**
+ * Returns the SSL URI for the container
+ *
+ * @api
+ * @return string
+ */
+ public function SSLURI()
+ {
+ return $this->CDNinfo('Ssl-Uri');
+ }
+
+ /**
+ * Returns the streaming URI for the container
+ *
+ * @api
+ * @return string
+ */
+ public function streamingURI()
+ {
+ return $this->CDNinfo('Streaming-Uri');
+ }
+
+ /**
+ * Returns the IOS streaming URI for the container
+ *
+ * @api
+ * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/iOS-Streaming-d1f3725.html
+ * @return string
+ */
+ public function iosStreamingURI()
+ {
+ return $this->CDNinfo('Ios-Uri');
+ }
+
+ /**
+ * 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\Collection
+ * @throws ObjFetchError
+ */
+ public function objectList($params = array())
+ {
+ // construct a query string out of the parameters
+ $params['format'] = 'json';
+
+ $queryString = $this->makeQueryString($params);
+
+ // append the query string to the URL
+ $url = $this->url();
+ if (strlen($queryString) > 0) {
+ $url .= '?' . $queryString;
+ }
+
+ return $this->getService()->collection(
+ 'OpenCloud\ObjectStore\Resource\DataObject', $url, $this
+ );
+ }
+
+ /**
+ * Returns a new DataObject associated with this container
+ *
+ * @param string $name if supplied, the name of the object to return
+ * @return DataObject
+ */
+ public function dataObject($name = null)
+ {
+ return new DataObject($this, $name);
+ }
+
+ /**
+ * Refreshes, then associates the CDN container
+ */
+ public function refresh($id = null, $url = null)
+ {
+ parent::refresh($id, $url);
+
+ // @codeCoverageIgnoreStart
+ if ($this->getService() instanceof CDNService) {
+ return;
+ }
+
+
+ if (null !== ($cdn = $this->getService()->CDN())) {
+ try {
+ $this->cdn = new CDNContainer(
+ $cdn,
+ $this->name
+ );
+ } catch (Exceptions\ContainerNotFoundError $e) {
+ $this->cdn = new CDNContainer($cdn);
+ $this->cdn->name = $this->name;
+ }
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+}
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/DataObject.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/DataObject.php
new file mode 100644
index 00000000000..443df1f651f
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Resource/DataObject.php
@@ -0,0 +1,941 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore\Resource;
+
+use finfo as FileInfo;
+use OpenCloud\Common\Lang;
+use OpenCloud\Common\Exceptions;
+use OpenCloud\ObjectStore\AbstractService;
+use OpenCloud\Common\Request\Response\Http;
+
+/**
+ * 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 AbstractStorageObject
+{
+ /**
+ * Object name. The only restriction on object names is that they must be
+ * less than 1024 bytes in length after URL encoding.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * Hash value of the object.
+ *
+ * @var string
+ */
+ public $hash;
+
+ /**
+ * Size of object in bytes.
+ *
+ * @var string
+ */
+ public $bytes;
+
+ /**
+ * Date of last modification.
+ *
+ * @var string
+ */
+ public $last_modified;
+
+ /**
+ * Object's content type.
+ *
+ * @var string
+ */
+ public $content_type;
+
+ /**
+ * Object's content length.
+ *
+ * @var string
+ */
+ public $content_length;
+
+ /**
+ * Other headers set for this object (e.g. Access-Control-Allow-Origin)
+ *
+ * @var array
+ */
+ public $extra_headers = array();
+
+ /**
+ * Whether or not to calculate and send an ETag on create.
+ *
+ * @var bool
+ */
+ public $send_etag = true;
+
+ /**
+ * The data contained by the object.
+ *
+ * @var string
+ */
+ private $data;
+
+ /**
+ * The ETag value.
+ *
+ * @var string
+ */
+ private $etag;
+
+ /**
+ * The parent container of this object.
+ *
+ * @var CDNContainer
+ */
+ private $container;
+
+ /**
+ * Is this data object a pseudo directory?
+ *
+ * @var bool
+ */
+ private $directory = false;
+
+ /**
+ * Used to translate header values (returned by requests) into properties.
+ *
+ * @var array
+ */
+ private $headerTranslate = array(
+ 'Etag' => 'hash',
+ 'ETag' => 'hash',
+ 'Last-Modified' => 'last_modified',
+ 'Content-Length' => array('bytes', 'content_length'),
+ );
+
+ /**
+ * These properties can be freely set by the user for CRUD operations.
+ *
+ * @var array
+ */
+ private $allowedProperties = array(
+ 'name',
+ 'content_type',
+ 'extra_headers',
+ 'send_etag'
+ );
+
+ /**
+ * Option for clearing the status cache when objects are uploaded to API.
+ * By default, it is set to FALSE for performance; but if you have files
+ * that are rapidly and very often updated, you might want to clear the status
+ * cache so PHP reads the files directly, instead of relying on the cache.
+ *
+ * @link http://php.net/manual/en/function.clearstatcache.php
+ * @var bool
+ */
+ public $clearStatusCache = false;
+
+ /**
+ * A DataObject is related to a container and has a name
+ *
+ * If `$name` is specified, then it attempts to retrieve the object from the
+ * object store.
+ *
+ * @param Container $container the container holding this object
+ * @param mixed $cdata if an object or array, it is treated as values
+ * with which to populate the object. If it is a string, it is
+ * treated as a name and the object's info is retrieved from
+ * the service.
+ * @return void
+ */
+ public function __construct($container, $cdata = null)
+ {
+ parent::__construct();
+
+ $this->container = $container;
+
+ // For pseudo-directories, we need to ensure the name is set
+ if (!empty($cdata->subdir)) {
+ $this->name = $cdata->subdir;
+ $this->directory = true;
+ } else {
+ $this->populate($cdata);
+ }
+ }
+
+ /**
+ * Is this data object a pseudo-directory?
+ *
+ * @return bool
+ */
+ public function isDirectory()
+ {
+ return $this->directory;
+ }
+
+ /**
+ * Allow other objects to know what the primary key is.
+ *
+ * @return string
+ */
+ public function primaryKeyField()
+ {
+ return 'name';
+ }
+
+ /**
+ * Is this a real file?
+ *
+ * @param string $filename
+ * @return bool
+ */
+ private function isRealFile($filename)
+ {
+ return $filename != '/dev/null' && $filename != 'NUL';
+ }
+
+ /**
+ * Set this file's content type.
+ *
+ * @param string $contentType
+ */
+ public function setContentType($contentType)
+ {
+ $this->content_type = $contentType;
+ }
+
+ /**
+ * Return the content type.
+ *
+ * @return string
+ */
+ public function getContentType()
+ {
+ return $this->content_type;
+ }
+
+ /**
+ * Returns the URL of the data object
+ *
+ * If the object is new and doesn't have a name, then an exception is
+ * thrown.
+ *
+ * @param string $subresource Not used
+ * @return string
+ * @throws NoNameError
+ */
+ public function url($subresource = '')
+ {
+ if (!$this->name) {
+ throw new Exceptions\NoNameError(Lang::translate('Object has no name'));
+ }
+
+ return Lang::noslash(
+ $this->container->url()) . '/' . str_replace('%2F', '/', rawurlencode($this->name)
+ );
+ }
+
+ /**
+ * Creates (or updates; both the same) an instance of the object
+ *
+ * @api
+ * @param array $params an optional associative array that can contain the
+ * 'name' and 'content_type' of the object
+ * @param string $filename if provided, then the object is loaded from the
+ * specified file
+ * @return boolean
+ * @throws CreateUpdateError
+ */
+ public function create($params = array(), $filename = null, $extractArchive = null)
+ {
+ // Set and validate params
+ $this->setParams($params);
+
+ // assume no file upload
+ $fp = false;
+
+ // if the filename is provided, process it
+ if ($filename) {
+
+ if (!$fp = @fopen($filename, 'r')) {
+ throw new Exceptions\IOError(sprintf(
+ Lang::translate('Could not open file [%s] for reading'),
+ $filename
+ ));
+ }
+
+ // @todo Maybe, for performance, we could set the "clear status cache"
+ // feature to false by default - but allow users to set to true if required
+ clearstatcache($this->clearStatusCache === true, $filename);
+
+ // Cast filesize as a floating point
+ $filesize = (float) filesize($filename);
+
+ // Check it's below a reasonable size, and set
+ // @codeCoverageIgnoreStart
+ if ($filesize > AbstractService::MAX_OBJECT_SIZE) {
+ throw new Exceptions\ObjectError("File size exceeds maximum object size.");
+ }
+ // @codeCoverageIgnoreEnd
+ $this->content_length = $filesize;
+
+ // Guess the content type if necessary
+ if (!$this->getContentType() && $this->isRealFile($filename)) {
+ $this->setContentType($this->inferContentType($filename));
+ }
+
+ // Send ETag checksum if necessary
+ if ($this->send_etag) {
+ $this->etag = md5_file($filename);
+ }
+
+ // Announce to the world
+ $this->getLogger()->info('Uploading {size} bytes from {name}', array(
+ 'size' => $filesize,
+ 'name' => $filename
+ ));
+
+ } else {
+ // compute the length
+ $this->content_length = strlen($this->data);
+
+ if ($this->send_etag) {
+ $this->etag = md5($this->data);
+ }
+ }
+
+ // Only allow supported archive types
+ // http://docs.rackspace.com/files/api/v1/cf-devguide/content/Extract_Archive-d1e2338.html
+ $extractArchiveUrlArg = '';
+
+ if ($extractArchive) {
+ if ($extractArchive !== "tar.gz" && $extractArchive !== "tar.bz2") {
+ throw new Exceptions\ObjectError(
+ "Extract Archive only supports tar.gz and tar.bz2"
+ );
+ } else {
+ $extractArchiveUrlArg = "?extract-archive=" . $extractArchive;
+ $this->etag = null;
+ $this->setContentType('');
+ }
+ }
+
+ // Set headers
+ $headers = $this->metadataHeaders();
+
+ if (!empty($this->etag)) {
+ $headers['ETag'] = $this->etag;
+ }
+
+ // Content-Type is no longer required; if not specified, it will
+ // attempt to guess based on the file extension.
+ if (!$this->getContentType()) {
+ $headers['Content-Type'] = $this->getContentType();
+ }
+
+ $headers['Content-Length'] = $this->content_length;
+
+ // Merge in extra headers
+ if (!empty($this->extra_headers)) {
+ $headers = $this->extra_headers + $headers;
+ }
+
+ // perform the request
+ $response = $this->getService()->request(
+ $this->url() . $extractArchiveUrlArg,
+ 'PUT',
+ $headers,
+ $fp ? $fp : $this->data
+ );
+
+ // check the status
+ // @codeCoverageIgnoreStart
+ if (($status = $response->httpStatus()) >= 300) {
+ throw new Exceptions\CreateUpdateError(sprintf(
+ Lang::translate('Problem saving/updating object [%s] HTTP status [%s] response [%s]'),
+ $this->url() . $extractArchiveUrlArg,
+ $status,
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ // set values from response
+ $this->saveResponseHeaders($response);
+
+ // close the file handle
+ if ($fp) {
+ fclose($fp);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Update() is provided as an alias for the Create() method
+ *
+ * Since update and create both use a PUT request, the different functions
+ * may allow the developer to distinguish between the semantics in his or
+ * her application.
+ *
+ * @api
+ * @param array $params an optional associative array that can contain the
+ * 'name' and 'type' of the object
+ * @param string $filename if provided, the object is loaded from the file
+ * @return boolean
+ */
+ public function update($params = array(), $filename = '')
+ {
+ return $this->create($params, $filename);
+ }
+
+ /**
+ * UpdateMetadata() - updates headers
+ *
+ * Updates metadata headers
+ *
+ * @api
+ * @param array $params an optional associative array that can contain the
+ * 'name' and 'type' of the object
+ * @return boolean
+ */
+ public function updateMetadata($params = array())
+ {
+ $this->setParams($params);
+
+ // set the headers
+ $headers = $this->metadataHeaders();
+ $headers['Content-Type'] = $this->getContentType();
+
+ $response = $this->getService()->request(
+ $this->url(),
+ 'POST',
+ $headers
+ );
+
+ // check the status
+ // @codeCoverageIgnoreStart
+ if (($stat = $response->httpStatus()) >= 204) {
+ throw new Exceptions\UpdateError(sprintf(
+ Lang::translate('Problem updating object [%s] HTTP status [%s] response [%s]'),
+ $this->url(),
+ $stat,
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $response;
+ }
+
+ /**
+ * Deletes an object from the Object Store
+ *
+ * Note that we can delete without retrieving by specifying the name in the
+ * parameter array.
+ *
+ * @api
+ * @param array $params an array of parameters
+ * @return HttpResponse if successful; FALSE if not
+ * @throws DeleteError
+ */
+ public function delete($params = array())
+ {
+ $this->setParams($params);
+
+ $response = $this->getService()->request($this->url(), 'DELETE');
+
+ // check the status
+ // @codeCoverageIgnoreStart
+ if (($stat = $response->httpStatus()) >= 300) {
+ throw new Exceptions\DeleteError(sprintf(
+ Lang::translate('Problem deleting object [%s] HTTP status [%s] response [%s]'),
+ $this->url(),
+ $stat,
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $response;
+ }
+
+ /**
+ * Copies the object to another container/object
+ *
+ * Note that this function, because it operates within the Object Store
+ * itself, is much faster than downloading the object and re-uploading it
+ * to a new object.
+ *
+ * @param DataObject $target the target of the COPY command
+ */
+ public function copy(DataObject $target)
+ {
+ $uri = sprintf('/%s/%s', $target->container()->name(), $target->name());
+
+ $this->getLogger()->info('Copying object to [{uri}]', array('uri' => $uri));
+
+ $response = $this->getService()->request(
+ $this->url(),
+ 'COPY',
+ array('Destination' => $uri)
+ );
+
+ // check response code
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 202) {
+ throw new Exceptions\ObjectCopyError(sprintf(
+ Lang::translate('Error copying object [%s], status [%d] response [%s]'),
+ $this->url(),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $response;
+ }
+
+ /**
+ * Returns the container of the object
+ *
+ * @return Container
+ */
+ public function container()
+ {
+ return $this->container;
+ }
+
+ /**
+ * returns the TEMP_URL for the object
+ *
+ * Some notes:
+ * * The `$secret` value is arbitrary; it must match the value set for
+ * the `X-Account-Meta-Temp-URL-Key` on the account level. This can be
+ * set by calling `$service->SetTempUrlSecret($secret)`.
+ * * The `$expires` value is the number of seconds you want the temporary
+ * URL to be valid for. For example, use `60` to make it valid for a
+ * minute
+ * * The `$method` must be either GET or PUT. No other methods are
+ * supported.
+ *
+ * @param string $secret the shared secret
+ * @param integer $expires the expiration time (in seconds)
+ * @param string $method either GET or PUT
+ * @return string the temporary URL
+ */
+ public function tempUrl($secret, $expires, $method)
+ {
+ $method = strtoupper($method);
+ $expiry_time = time() + $expires;
+
+ // check for proper method
+ if ($method != 'GET' && $method != 'PUT') {
+ throw new Exceptions\TempUrlMethodError(sprintf(
+ Lang::translate(
+ 'Bad method [%s] for TempUrl; only GET or PUT supported'),
+ $method
+ ));
+ }
+
+ // construct the URL
+ $url = $this->url();
+ $path = urldecode(parse_url($url, PHP_URL_PATH));
+
+ $hmac_body = "$method\n$expiry_time\n$path";
+ $hash = hash_hmac('sha1', $hmac_body, $secret);
+
+ $this->getLogger()->info('URL [{url}]; SIG [{sig}]; HASH [{hash}]', array(
+ 'url' => $url,
+ 'sig' => $hmac_body,
+ 'hash' => $hash
+ ));
+
+ $temp_url = sprintf('%s?temp_url_sig=%s&temp_url_expires=%d', $url, $hash, $expiry_time);
+
+ // debug that stuff
+ $this->getLogger()->info('TempUrl generated [{url}]', array(
+ 'url' => $temp_url
+ ));
+
+ return $temp_url;
+ }
+
+ /**
+ * Sets object data from string
+ *
+ * This is a convenience function to permit the use of other technologies
+ * for setting an object's content.
+ *
+ * @param string $data
+ * @return void
+ */
+ public function setData($data)
+ {
+ $this->data = (string) $data;
+ }
+
+ /**
+ * Return object's data as a string
+ *
+ * @return string the entire object
+ */
+ public function saveToString()
+ {
+ return $this->getService()->request($this->url())->httpBody();
+ }
+
+ /**
+ * Saves the object's data to local filename
+ *
+ * Given a local filename, the Object's data will be written to the newly
+ * created file.
+ *
+ * Example:
+ * <code>
+ * # ... authentication/connection/container code excluded
+ * # ... see previous examples
+ *
+ * # Whoops! I deleted my local README, let me download/save it
+ * #
+ * $my_docs = $conn->get_container("documents");
+ * $doc = $my_docs->get_object("README");
+ *
+ * $doc->SaveToFilename("/home/ej/cloudfiles/readme.restored");
+ * </code>
+ *
+ * @param string $filename name of local file to write data to
+ * @return boolean <kbd>TRUE</kbd> if successful
+ * @throws IOException error opening file
+ * @throws InvalidResponseException unexpected response
+ */
+ public function saveToFilename($filename)
+ {
+ if (!$fp = @fopen($filename, "wb")) {
+ throw new Exceptions\IOError(sprintf(
+ Lang::translate('Could not open file [%s] for writing'),
+ $filename
+ ));
+ }
+
+ $result = $this->getService()->request($this->url(), 'GET', array(), $fp);
+
+ fclose($fp);
+
+ return $result;
+ }
+
+ /**
+ * Saves the object's to a stream filename
+ *
+ * Given a local filename, the Object's data will be written to the stream
+ *
+ * Example:
+ * <code>
+ * # ... authentication/connection/container code excluded
+ * # ... see previous examples
+ *
+ * # If I want to write the README to a temporary memory string I
+ * # do :
+ * #
+ * $my_docs = $conn->get_container("documents");
+ * $doc = $my_docs->DataObject(array("name"=>"README"));
+ *
+ * $fp = fopen('php://temp', 'r+');
+ * $doc->SaveToStream($fp);
+ * fclose($fp);
+ * </code>
+ *
+ * @param string $filename name of local file to write data to
+ * @return boolean <kbd>TRUE</kbd> if successful
+ * @throws IOException error opening file
+ * @throws InvalidResponseException unexpected response
+ */
+ public function saveToStream($resource)
+ {
+ if (!is_resource($resource)) {
+ throw new Exceptions\ObjectError(
+ Lang::translate("Resource argument not a valid PHP resource."
+ ));
+ }
+
+ return $this->getService()->request($this->url(), 'GET', array(), $resource);
+ }
+
+
+ /**
+ * Returns the object's MD5 checksum
+ *
+ * Accessor method for reading Object's private ETag attribute.
+ *
+ * @api
+ * @return string MD5 checksum hexidecimal string
+ */
+ public function getETag()
+ {
+ return $this->etag;
+ }
+
+ /**
+ * Purges the object from the CDN
+ *
+ * Note that the object will still be served up to the time of its
+ * TTL value.
+ *
+ * @api
+ * @param string $email An email address that will be notified when
+ * the object is purged.
+ * @return void
+ * @throws CdnError if the container is not CDN-enabled
+ * @throws CdnHttpError if there is an HTTP error in the transaction
+ */
+ public function purgeCDN($email)
+ {
+ // @codeCoverageIgnoreStart
+ if (!$cdn = $this->Container()->CDNURL()) {
+ throw new Exceptions\CdnError(Lang::translate('Container is not CDN-enabled'));
+ }
+ // @codeCoverageIgnoreEnd
+
+ $url = $cdn . '/' . $this->name;
+ $headers['X-Purge-Email'] = $email;
+ $response = $this->getService()->request($url, 'DELETE', $headers);
+
+ // check the status
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 204) {
+ throw new Exceptions\CdnHttpError(sprintf(
+ Lang::translate('Error purging object, status [%d] response [%s]'),
+ $response->httpStatus(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return true;
+ }
+
+ /**
+ * Returns the CDN URL (for managing the object)
+ *
+ * Note that the DataObject::PublicURL() method is used to return the
+ * publicly-available URL of the object, while the CDNURL() is used
+ * to manage the object.
+ *
+ * @return string
+ */
+ public function CDNURL()
+ {
+ return $this->container()->CDNURL() . '/' . $this->name;
+ }
+
+ /**
+ * Returns the object's Public CDN URL, if available
+ *
+ * @api
+ * @param string $type can be 'streaming', 'ssl', 'ios-streaming',
+ * or anything else for the
+ * default URL. For example, `$object->PublicURL('ios-streaming')`
+ * @return string
+ */
+ public function publicURL($type = null)
+ {
+ if (!$prefix = $this->container()->CDNURI()) {
+ return null;
+ }
+
+ switch(strtoupper($type)) {
+ case 'SSL':
+ $url = $this->container()->SSLURI().'/'.$this->name;
+ break;
+ case 'STREAMING':
+ $url = $this->container()->streamingURI().'/'.$this->name;
+ break;
+ case 'IOS':
+ case 'IOS-STREAMING':
+ $url = $this->container()->iosStreamingURI().'/'.$this->name;
+ break;
+ default:
+ $url = $prefix.'/'.$this->name;
+ break;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Sets parameters from an array and validates them.
+ *
+ * @param array $params Associative array of parameters
+ * @return void
+ */
+ private function setParams(array $params = array())
+ {
+ // Inspect the user's array for any unapproved keys, and unset if necessary
+ foreach (array_diff(array_keys($params), $this->allowedProperties) as $key) {
+ $this->getLogger()->warning('You cannot use the {keyName} key when creating an object', array(
+ 'keyName' => $key
+ ));
+ unset($params[$key]);
+ }
+
+ $this->populate($params);
+ }
+
+ /**
+ * Retrieves a single object, parses headers
+ *
+ * @return void
+ * @throws NoNameError, ObjFetchError
+ */
+ private function fetch()
+ {
+ if (!$this->name) {
+ throw new Exceptions\NoNameError(Lang::translate('Cannot retrieve an unnamed object'));
+ }
+
+ $response = $this->getService()->request($this->url(), 'HEAD', array('Accept' => '*/*'));
+
+ // check for errors
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() >= 300) {
+ throw new Exceptions\ObjFetchError(sprintf(
+ Lang::translate('Problem retrieving object [%s]'),
+ $this->url()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ // set headers as metadata?
+ $this->saveResponseHeaders($response);
+
+ // parse the metadata
+ $this->getMetadata($response);
+ }
+
+ /**
+ * Extracts the headers from the response, and saves them as object
+ * attributes. Additional name conversions are done where necessary.
+ *
+ * @param Http $response
+ */
+ private function saveResponseHeaders(Http $response, $fillExtraIfNotFound = true)
+ {
+ foreach ($response->headers() as $header => $value) {
+ if (isset($this->headerTranslate[$header])) {
+ // This header needs to be translated
+ $property = $this->headerTranslate[$header];
+ // Are there multiple properties that need to be set?
+ if (is_array($property)) {
+ foreach ($property as $subProperty) {
+ $this->$subProperty = $value;
+ }
+ } else {
+ $this->$property = $value;
+ }
+ } elseif ($fillExtraIfNotFound === true) {
+ // Otherwise, stock extra headers
+ $this->extra_headers[$header] = $value;
+ }
+ }
+ }
+
+ /**
+ * Compatability.
+ */
+ public function refresh()
+ {
+ return $this->fetch();
+ }
+
+ /**
+ * Returns the service associated with this object
+ *
+ * It's actually the object's container's service, so this method will
+ * simplify things a bit.
+ */
+ private function getService()
+ {
+ return $this->container->getService();
+ }
+
+ /**
+ * Performs an internal check to get the proper MIME type for an object
+ *
+ * This function would go over the available PHP methods to get
+ * the MIME type.
+ *
+ * By default it will try to use the PHP fileinfo library which is
+ * available from PHP 5.3 or as an PECL extension
+ * (http://pecl.php.net/package/Fileinfo).
+ *
+ * It will get the magic file by default from the system wide file
+ * which is usually available in /usr/share/magic on Unix or try
+ * to use the file specified in the source directory of the API
+ * (share directory).
+ *
+ * if fileinfo is not available it will try to use the internal
+ * mime_content_type function.
+ *
+ * @param string $handle name of file or buffer to guess the type from
+ * @return boolean <kbd>TRUE</kbd> if successful
+ * @throws BadContentTypeException
+ * @codeCoverageIgnore
+ */
+ private function inferContentType($handle)
+ {
+ if ($contentType = $this->getContentType()) {
+ return $contentType;
+ }
+
+ $contentType = false;
+
+ $filePath = (is_string($handle)) ? $handle : (string) $handle;
+
+ if (function_exists("finfo_open")) {
+
+ $magicPath = dirname(__FILE__) . "/share/magic";
+ $finfo = new FileInfo(FILEINFO_MIME, file_exists($magicPath) ? $magicPath : null);
+
+ if ($finfo) {
+
+ $contentType = is_file($filePath)
+ ? $finfo->file($handle)
+ : $finfo->buffer($handle);
+
+ /**
+ * PHP 5.3 fileinfo display extra information like charset so we
+ * remove everything after the ; since we are not into that stuff
+ */
+ if (null !== ($extraInfo = strpos($contentType, "; "))) {
+ $contentType = substr($contentType, 0, $extraInfo);
+ }
+ }
+
+ //unset($finfo);
+ }
+
+ if (!$contentType) {
+ // Try different native function instead
+ if (is_file((string) $handle) && function_exists("mime_content_type")) {
+ $contentType = mime_content_type($handle);
+ } else {
+ $this->getLogger()->error('Content-Type cannot be found');
+ }
+ }
+
+ return $contentType;
+ }
+
+}
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Service.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Service.php
new file mode 100644
index 00000000000..571b33378ac
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/ObjectStore/Service.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * PHP OpenCloud library.
+ *
+ * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
+ * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
+ * @version 1.6.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+
+namespace OpenCloud\ObjectStore;
+
+use OpenCloud\OpenStack;
+use OpenCloud\Common\Exceptions;
+use OpenCloud\Common\Lang;
+
+/**
+ * The ObjectStore (Cloud Files) service.
+ */
+class Service extends AbstractService
+{
+
+ /**
+ * This holds the associated CDN service (for Rackspace public cloud)
+ * or is NULL otherwise. The existence of an object here is
+ * indicative that the CDN service is available.
+ */
+ private $cdn;
+
+ /**
+ * Creates a new ObjectStore service object.
+ *
+ * @param OpenCloud\OpenStack $connection The connection object
+ * @param string $serviceName The name of the service
+ * @param string $serviceRegion The service's region
+ * @param string $urlType The type of URL (normally 'publicURL')
+ */
+ public function __construct(
+ OpenStack $connection,
+ $serviceName = RAXSDK_OBJSTORE_NAME,
+ $serviceRegion = RAXSDK_OBJSTORE_REGION,
+ $urltype = RAXSDK_OBJSTORE_URLTYPE
+ ) {
+ $this->getLogger()->info('Initializing Container Service...');
+
+ parent::__construct(
+ $connection,
+ 'object-store',
+ $serviceName,
+ $serviceRegion,
+ $urltype
+ );
+
+ // establish the CDN container, if available
+ try {
+ $this->cdn = new CDNService(
+ $connection,
+ $serviceName . 'CDN',
+ $serviceRegion,
+ $urltype
+ );
+ } catch (Exceptions\EndpointError $e) {
+ // If we have an endpoint error, then the CDN functionality is not
+ // available. In this case, we silently ignore it.
+ }
+ }
+
+ /**
+ * Sets the shared secret value for the TEMP_URL
+ *
+ * @param string $secret the shared secret
+ * @return HttpResponse
+ */
+ public function setTempUrlSecret($secret)
+ {
+ $response = $this->request(
+ $this->url(),
+ 'POST',
+ array('X-Account-Meta-Temp-Url-Key' => $secret)
+ );
+
+ // @codeCoverageIgnoreStart
+ if ($response->httpStatus() > 204) {
+ throw new Exceptions\HttpError(sprintf(
+ Lang::translate('Error in request, status [%d] for URL [%s] [%s]'),
+ $response->httpStatus(),
+ $this->url(),
+ $response->httpBody()
+ ));
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $response;
+ }
+
+ /**
+ * Get the CDN service.
+ *
+ * @return null|CDNService
+ */
+ public function getCDNService()
+ {
+ return $this->cdn;
+ }
+
+ /**
+ * Backwards compability.
+ */
+ public function CDN()
+ {
+ return $this->getCDNService();
+ }
+
+}