29 use \HPCloud\Bootstrap;
30 use \HPCloud\Storage\ObjectStorage;
379 $this->dirListing = array();
416 if (empty(
$url[
'host'])) {
417 trigger_error(
'Container name is required.' , E_USER_WARNING);
425 if (empty(
$url[
'path'])) {
426 $this->dirPrefix =
'';
429 $this->dirPrefix =
$url[
'path'];
435 $this->dirListing =
$container->objectsWithPrefix($this->dirPrefix, $sep);
438 trigger_error(
'Directory could not be opened: ' . $e->getMessage(), E_USER_WARNING);
472 if (count($this->dirListing) <= $this->dirIndex) {
476 $curr = $this->dirListing[$this->dirIndex];
480 $fullpath = $curr->path();
483 $fullpath = $curr->name();
486 if (!empty($this->dirPrefix)) {
487 $len = strlen($this->dirPrefix);
488 $fullpath = substr($fullpath, $len);
570 public function rename($path_from, $path_to) {
575 if ($src[
'scheme'] != $dest[
'scheme']) {
576 trigger_error(
"I'm too stupid to copy across protocols.", E_USER_WARNING);
579 if ( empty($src[
'host']) || empty($src[
'path'])
580 || empty($dest[
'host']) || empty($dest[
'path'])) {
581 trigger_error(
'Container and path are required for both source and destination URLs.', E_USER_WARNING);
586 $container = $this->store->container($src[
'host']);
596 trigger_error(
'Rename was not completed: ' . $e->getMessage(), E_USER_WARNING);
619 return $this->objStream;
649 trigger_error(
'Error while closing: ' . $e->getMessage(), E_USER_NOTICE);
655 fclose($this->objStream);
673 return feof($this->objStream);
689 syslog(LOG_WARNING, $e);
690 trigger_error(
'Error while flushing: ' . $e->getMessage(), E_USER_NOTICE);
702 $contentType = $this->
cxt(
'content_type');
703 if (!empty($contentType)) {
704 $this->obj->setContentType($contentType);
708 if ($this->isNeverDirty) {
713 if ($this->isDirty) {
714 $position = ftell($this->objStream);
716 rewind($this->objStream);
717 $this->
container->save($this->obj, $this->objStream);
719 fseek($this->objStream, SEEK_SET, $position);
722 $this->isDirty = FALSE;
782 public function stream_open($path, $mode, $options, &$opened_path) {
788 if (STREAM_REPORT_ERRORS & $options) {
789 $this->triggerErrors = TRUE;
800 if (empty(
$url[
'host'])) {
802 trigger_error(
'No container name was supplied in ' . $path, E_USER_WARNING);
808 if (empty(
$url[
'path'])) {
810 trigger_error(
'No object name was supplied in ' . $path, E_USER_WARNING);
818 if (isset(
$url[
'scheme'])) {
819 $this->schemeName ==
$url[
'scheme'];
826 $containerName =
$url[
'host'];
829 $objectName =
$url[
'path'];
838 trigger_error(
'Failed to init object storage: ' . $e->getMessage(), E_USER_WARNING);
847 $cdnUrl = $this->store->cdnUrl($containerName, FALSE);
848 $cdnSslUrl = $this->store->cdnUrl($containerName, TRUE);
849 if (!empty($cdnUrl) && !$this->isWriting && !$this->isAppending) {
850 $requireSSL = (boolean) $this->
cxt(
'cdn_require_ssl', TRUE);
852 $newUrl = $this->store->url() .
'/' . $containerName;
853 $token = $this->store->token();
854 $this->
container = new \HPCloud\Storage\ObjectStorage\Container($containerName, $newUrl,
$token);
855 $this->
container->useCDN($cdnUrl, $cdnSslUrl);
856 $this->obj = $this->
container->object($objectName, $requireSSL);
857 $this->objStream = $this->obj->stream();
871 $this->
container = $this->store->container($containerName);
873 catch (\HPCloud\
Transport\FileNotFoundException $e) {
874 trigger_error(
'Container not found.', E_USER_WARNING);
883 $this->obj = $this->
container->object($objectName);
884 $stream = $this->obj->stream();
885 $streamMeta = stream_get_meta_data($stream);
888 if ($this->noOverwrite) {
890 trigger_error(
'File exists and cannot be overwritten.', E_USER_WARNING);
898 if ($this->isWriting && ($streamMeta[
'mode'] ==
'r' || !$this->isReading)) {
899 $newMode = $this->isReading ?
'rb+' :
'wb';
900 $tmpStream = fopen(
'php://temp', $newMode);
901 stream_copy_to_stream($stream, $tmpStream);
904 if (!$this->isAppending) {
908 $this->objStream = $tmpStream;
911 $this->objStream = $this->obj->stream();
915 if ($this->isAppending) {
916 fseek($this->objStream, -1, SEEK_END);
922 catch (\HPCloud\
Transport\FileNotFoundException $nf) {
925 if ($this->createIfNotFound) {
926 $this->obj =
new Object($objectName);
927 $this->objStream = fopen(
'php://temp',
'rb+');
928 $this->isDirty = TRUE;
932 trigger_error($nf->getMessage(), E_USER_WARNING);
941 trigger_error(
'Failed to fetch object: ' . $e->getMessage(), E_USER_WARNING);
981 return fread($this->objStream, $count);
996 $ret = fseek($this->objStream, $offset, $whence);
1016 case STREAM_OPTION_BLOCKING:
1017 return stream_set_blocking($this->objStream, $arg1);
1018 case STREAM_OPTION_READ_TIMEOUT:
1021 return stream_set_timeout($this->objStream, $arg1, $arg2);
1022 case STREAM_OPTION_WRITE_BUFFER:
1023 return stream_set_write_buffer($this->objStream, $arg2);
1047 $stat = fstat($this->objStream);
1051 $contentLength = $stat[
'size'];
1066 return ftell($this->objStream);
1083 $this->isDirty = TRUE;
1084 return fwrite($this->objStream, $data);
1113 if (empty(
$url[
'host'])) {
1114 trigger_error(
'Container name is required.', E_USER_WARNING);
1121 if (empty(
$url[
'path'])) {
1122 trigger_error(
'Path is required.', E_USER_WARNING);
1130 $token = $this->store->token();
1131 $endpoint_url = $this->store->url() .
'/' . rawurlencode(
$name);
1136 trigger_error(
'Error during unlink: ' . $e->getMessage(), E_USER_WARNING);
1148 if (empty(
$url[
'host']) || empty(
$url[
'path'])) {
1149 if ($flags & STREAM_URL_STAT_QUIET) {
1150 trigger_error(
'Container name (host) and path are required.', E_USER_WARNING);
1163 $token = $this->store->token();
1164 $endpoint_url = $this->store->url() .
'/' . rawurlencode(
$name);
1176 if ($flags & STREAM_URL_STAT_QUIET) {
1235 return $this->store->token();
1248 return self::$serviceCatalogCache[$this->
token()];
1282 $mode =
$container->acl()->isPublic() ? 33277 : 33272;
1286 if (function_exists(
'posix_geteuid')) {
1287 $uid = posix_geteuid();
1288 $gid = posix_getegid();
1296 $modTime =
$object->lastModified();
1310 'atime' => $modTime,
1311 'mtime' => $modTime,
1312 'ctime' => $modTime,
1317 $final = array_values($values) + $values;
1339 $mode = strtolower($mode);
1345 $this->isBinary = strpos($mode,
'b') !== FALSE;
1346 $this->isText = strpos($mode,
't') !== FALSE;
1349 $mode = preg_replace(
'/[bt]?/',
'', $mode);
1353 $this->isWriting = TRUE;
1355 $this->isReading = TRUE;
1356 $this->createIfNotFound = FALSE;
1361 $this->isReading = TRUE;
1363 $this->isTruncating = TRUE;
1364 $this->isWriting = TRUE;
1369 $this->isReading = TRUE;
1371 $this->isAppending = TRUE;
1372 $this->isWriting = TRUE;
1377 $this->isReading = TRUE;
1379 $this->isWriting = TRUE;
1380 $this->noOverwrite = TRUE;
1384 $this->isReading = TRUE;
1386 $this->isWriting = TRUE;
1394 $this->isReading = TRUE;
1395 $this->isWriting = TRUE;
1396 $this->isNeverDirty = TRUE;
1402 $this->isReading = TRUE;
1403 $this->isWriting = TRUE;
1429 if (is_resource($this->context) && empty($this->contextArray)) {
1430 $cxt = stream_context_get_options($this->context);
1433 if (!empty(
$cxt[$this->schemeName])) {
1434 $this->contextArray =
$cxt[$this->schemeName];
1437 elseif (!empty(
$cxt[self::DEFAULT_SCHEME])) {
1438 $this->contextArray =
$cxt[self::DEFAULT_SCHEME];
1443 if (isset($this->contextArray[
$name])) {
1444 return $this->contextArray[
$name];
1449 $val = \HPCloud\Bootstrap::config($name, NULL);
1473 $res = parse_url(
$url);
1478 foreach ($res as
$key => $val) {
1479 if (
$key ==
'host') {
1480 $res[
$key] = urldecode($val);
1482 elseif (
$key ==
'path') {
1483 if (strpos($val,
'/') === 0) {
1484 $val = substr($val, 1);
1486 $res[
$key] = urldecode($val);
1525 $key = $this->
cxt(
'key', $this->
cxt(
'secret'));
1528 $tenantName = $this->
cxt(
'tenantname');
1529 $authUrl = $this->
cxt(
'endpoint');
1532 $serviceCatalog = NULL;
1534 if (!empty(
$token) && isset(self::$serviceCatalogCache[
$token])) {
1535 $serviceCatalog = self::$serviceCatalogCache[
$token];
1540 if (!empty($token) && !empty(
$endpoint)) {
1541 $this->store = new \HPCloud\Storage\ObjectStorage($token,
$endpoint);
1544 elseif ($this->
cxt(
'use_swift_auth', FALSE)) {
1546 if (empty($authUrl) || empty(
$account) || empty(
$key)) {
1547 throw new \HPCloud\Exception(
'account, endpoint, key are required stream parameters.');
1553 elseif (empty(
$tenantId) && empty($tenantName)) {
1554 throw new \HPCloud\Exception(
'Either Tenant ID (tenantid) or Tenant Name (tenantname) is required.');
1556 elseif (empty($authUrl)) {
1557 throw new \HPCloud\Exception(
'An Identity Service Endpoint (endpoint) is required.');
1564 $token = $ident->token();
1565 $serviceCatalog = $ident->serviceCatalog();
1566 self::$serviceCatalogCache[
$token] = $serviceCatalog;
1587 throw new \HPCloud\Exception(
'CDN could not be initialized', 1, $e);
1591 return !empty($this->store);
1612 $cdn = $this->
cxt(
'use_cdn', FALSE);
1619 elseif ($cdn instanceof \HPCloud\Storage\
CDN) {
1626 $catalog = $ident->serviceCatalog();
1627 $token = $ident->token();
1632 if (!empty($this->cdn)) {
1633 $this->store->useCDN($this->cdn);
1639 $username = $this->
cxt(
'username');
1640 $password = $this->
cxt(
'password');
1644 $key = $this->
cxt(
'key', $this->
cxt(
'secret'));
1647 $tenantName = $this->
cxt(
'tenantname');
1648 $authUrl = $this->
cxt(
'endpoint');
1650 $ident = new \HPCloud\Services\IdentityServices($authUrl);
1654 if (!empty($username) && !empty($password)) {
1655 $token = $ident->authenticateAsUser($username, $password,
$tenantId, $tenantName);
1661 throw new \HPCloud\Exception(
'Either username/password or account/key must be provided.');
1664 self::$serviceCatalogCache[
$token] = $ident->serviceCatalog();