PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/w3-total-cache/lib/CF/cloudfiles.php

https://bitbucket.org/mrmustarde/manhattan-beach
PHP | 2149 lines | 765 code | 91 blank | 1293 comment | 158 complexity | c03184d2fb0012c87a2cc60b12c7bb7c MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * This is the PHP Cloud Files API.
  4. *
  5. * <code>
  6. * # Authenticate to Cloud Files. The default is to automatically try
  7. * # to re-authenticate if an authentication token expires.
  8. * #
  9. * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
  10. * # file. This API ships with a newer version obtained directly from
  11. * # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
  12. * # call the CF_Authentication instance's 'ssl_use_cabundle()' method.
  13. * #
  14. * $auth = new CF_Authentication($username, $api_key);
  15. * # $auth->ssl_use_cabundle(); # bypass cURL's old CA bundle
  16. * $auth->authenticate();
  17. *
  18. * # Establish a connection to the storage system
  19. * #
  20. * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
  21. * # file. This API ships with a newer version obtained directly from
  22. * # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
  23. * # call the CF_Connection instance's 'ssl_use_cabundle()' method.
  24. * #
  25. * $conn = new CF_Connection($auth);
  26. * # $conn->ssl_use_cabundle(); # bypass cURL's old CA bundle
  27. *
  28. * # Create a remote Container and storage Object
  29. * #
  30. * $images = $conn->create_container("photos");
  31. * $bday = $images->create_object("first_birthday.jpg");
  32. *
  33. * # Upload content from a local file by streaming it. Note that we use
  34. * # a "float" for the file size to overcome PHP's 32-bit integer limit for
  35. * # very large files.
  36. * #
  37. * $fname = "/home/user/photos/birthdays/birthday1.jpg"; # filename to upload
  38. * $size = (float) sprintf("%u", filesize($fname));
  39. * $fp = open($fname, "r");
  40. * $bday->write($fp, $size);
  41. *
  42. * # Or... use a convenience function instead
  43. * #
  44. * $bday->load_from_filename("/home/user/photos/birthdays/birthday1.jpg");
  45. *
  46. * # Now, publish the "photos" container to serve the images by CDN.
  47. * # Use the "$uri" value to put in your web pages or send the link in an
  48. * # email message, etc.
  49. * #
  50. * $uri = $images->make_public();
  51. *
  52. * # Or... print out the Object's public URI
  53. * #
  54. * print $bday->public_uri();
  55. * </code>
  56. *
  57. * See the included tests directory for additional sample code.
  58. *
  59. * Requres PHP 5.x (for Exceptions and OO syntax) and PHP's cURL module.
  60. *
  61. * It uses the supporting "cloudfiles_http.php" module for HTTP(s) support and
  62. * allows for connection re-use and streaming of content into/out of Cloud Files
  63. * via PHP's cURL module.
  64. *
  65. * See COPYING for license information.
  66. *
  67. * @author Eric "EJ" Johnson <ej@racklabs.com>
  68. * @copyright Copyright (c) 2008, Rackspace US, Inc.
  69. * @package php-cloudfiles
  70. */
  71. /**
  72. */
  73. require_once("cloudfiles_exceptions.php");
  74. require("cloudfiles_http.php");
  75. define("DEFAULT_CF_API_VERSION", 1);
  76. define("MAX_CONTAINER_NAME_LEN", 256);
  77. define("MAX_OBJECT_NAME_LEN", 1024);
  78. define("MAX_OBJECT_SIZE", 5*1024*1024*1024+1);
  79. define("US_AUTHURL", "https://auth.api.rackspacecloud.com");
  80. define("UK_AUTHURL", "https://lon.auth.api.rackspacecloud.com");
  81. /**
  82. * Class for handling Cloud Files Authentication, call it's {@link authenticate()}
  83. * method to obtain authorized service urls and an authentication token.
  84. *
  85. * Example:
  86. * <code>
  87. * # Create the authentication instance
  88. * #
  89. * $auth = new CF_Authentication("username", "api_key");
  90. *
  91. * # NOTE: For UK Customers please specify your AuthURL Manually
  92. * # There is a Predfined constant to use EX:
  93. * #
  94. * # $auth = new CF_Authentication("username, "api_key", NULL, UK_AUTHURL);
  95. * # Using the UK_AUTHURL keyword will force the api to use the UK AuthUrl.
  96. * # rather then the US one. The NULL Is passed for legacy purposes and must
  97. * # be passed to function correctly.
  98. *
  99. * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
  100. * # file. This API ships with a newer version obtained directly from
  101. * # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
  102. * # call the CF_Authentication instance's 'ssl_use_cabundle()' method.
  103. * #
  104. * # $auth->ssl_use_cabundle(); # bypass cURL's old CA bundle
  105. *
  106. * # Perform authentication request
  107. * #
  108. * $auth->authenticate();
  109. * </code>
  110. *
  111. * @package php-cloudfiles
  112. */
  113. class CF_Authentication
  114. {
  115. public $dbug;
  116. public $username;
  117. public $api_key;
  118. public $auth_host;
  119. public $account;
  120. /**
  121. * Instance variables that are set after successful authentication
  122. */
  123. public $storage_url;
  124. public $cdnm_url;
  125. public $auth_token;
  126. /**
  127. * Class constructor (PHP 5 syntax)
  128. *
  129. * @param string $username Mosso username
  130. * @param string $api_key Mosso API Access Key
  131. * @param string $account <i>Account name</i>
  132. * @param string $auth_host <i>Authentication service URI</i>
  133. */
  134. function __construct($username=NULL, $api_key=NULL, $account=NULL, $auth_host=US_AUTHURL)
  135. {
  136. $this->dbug = False;
  137. $this->username = $username;
  138. $this->api_key = $api_key;
  139. $this->account_name = $account;
  140. $this->auth_host = $auth_host;
  141. $this->storage_url = NULL;
  142. $this->cdnm_url = NULL;
  143. $this->auth_token = NULL;
  144. $this->cfs_http = new CF_Http(DEFAULT_CF_API_VERSION);
  145. }
  146. /**
  147. * Use the Certificate Authority bundle included with this API
  148. *
  149. * Most versions of PHP with cURL support include an outdated Certificate
  150. * Authority (CA) bundle (the file that lists all valid certificate
  151. * signing authorities). The SSL certificates used by the Cloud Files
  152. * storage system are perfectly valid but have been created/signed by
  153. * a CA not listed in these outdated cURL distributions.
  154. *
  155. * As a work-around, we've included an updated CA bundle obtained
  156. * directly from cURL's web site (http://curl.haxx.se). You can direct
  157. * the API to use this CA bundle by calling this method prior to making
  158. * any remote calls. The best place to use this method is right after
  159. * the CF_Authentication instance has been instantiated.
  160. *
  161. * You can specify your own CA bundle by passing in the full pathname
  162. * to the bundle. You can use the included CA bundle by leaving the
  163. * argument blank.
  164. *
  165. * @param string $path Specify path to CA bundle (default to included)
  166. */
  167. function ssl_use_cabundle($path=NULL)
  168. {
  169. $this->cfs_http->ssl_use_cabundle($path);
  170. }
  171. /**
  172. * Attempt to validate Username/API Access Key
  173. *
  174. * Attempts to validate credentials with the authentication service. It
  175. * either returns <kbd>True</kbd> or throws an Exception. Accepts a single
  176. * (optional) argument for the storage system API version.
  177. *
  178. * Example:
  179. * <code>
  180. * # Create the authentication instance
  181. * #
  182. * $auth = new CF_Authentication("username", "api_key");
  183. *
  184. * # Perform authentication request
  185. * #
  186. * $auth->authenticate();
  187. * </code>
  188. *
  189. * @param string $version API version for Auth service (optional)
  190. * @return boolean <kbd>True</kbd> if successfully authenticated
  191. * @throws AuthenticationException invalid credentials
  192. * @throws InvalidResponseException invalid response
  193. */
  194. function authenticate($version=DEFAULT_CF_API_VERSION)
  195. {
  196. list($status,$reason,$surl,$curl,$atoken) =
  197. $this->cfs_http->authenticate($this->username, $this->api_key,
  198. $this->account_name, $this->auth_host);
  199. if ($status == 401) {
  200. throw new AuthenticationException("Invalid username or access key.");
  201. }
  202. if ($status != 204) {
  203. throw new InvalidResponseException(
  204. "Unexpected response (".$status."): ".$reason);
  205. }
  206. if (!($surl || $curl) || !$atoken) {
  207. throw new InvalidResponseException(
  208. "Expected headers missing from auth service.");
  209. }
  210. $this->storage_url = $surl;
  211. $this->cdnm_url = $curl;
  212. $this->auth_token = $atoken;
  213. return True;
  214. }
  215. /**
  216. * Use Cached Token and Storage URL's rather then grabbing from the Auth System
  217. *
  218. * Example:
  219. * <code>
  220. * #Create an Auth instance
  221. * $auth = new CF_Authentication();
  222. * #Pass Cached URL's and Token as Args
  223. * $auth->load_cached_credentials("auth_token", "storage_url", "cdn_management_url");
  224. * </code>
  225. *
  226. * @param string $auth_token A Cloud Files Auth Token (Required)
  227. * @param string $storage_url The Cloud Files Storage URL (Required)
  228. * @param string $cdnm_url CDN Management URL (Required)
  229. * @return boolean <kbd>True</kbd> if successful
  230. * @throws SyntaxException If any of the Required Arguments are missing
  231. */
  232. function load_cached_credentials($auth_token, $storage_url, $cdnm_url)
  233. {
  234. if(!$storage_url || !$cdnm_url)
  235. {
  236. throw new SyntaxException("Missing Required Interface URL's!");
  237. return False;
  238. }
  239. if(!$auth_token)
  240. {
  241. throw new SyntaxException("Missing Auth Token!");
  242. return False;
  243. }
  244. $this->storage_url = $storage_url;
  245. $this->cdnm_url = $cdnm_url;
  246. $this->auth_token = $auth_token;
  247. return True;
  248. }
  249. /**
  250. * Grab Cloud Files info to be Cached for later use with the load_cached_credentials method.
  251. *
  252. * Example:
  253. * <code>
  254. * #Create an Auth instance
  255. * $auth = new CF_Authentication("UserName","API_Key");
  256. * $auth->authenticate();
  257. * $array = $auth->export_credentials();
  258. * </code>
  259. *
  260. * @return array of url's and an auth token.
  261. */
  262. function export_credentials()
  263. {
  264. $arr = array();
  265. $arr['storage_url'] = $this->storage_url;
  266. $arr['cdnm_url'] = $this->cdnm_url;
  267. $arr['auth_token'] = $this->auth_token;
  268. return $arr;
  269. }
  270. /**
  271. * Make sure the CF_Authentication instance has authenticated.
  272. *
  273. * Ensures that the instance variables necessary to communicate with
  274. * Cloud Files have been set from a previous authenticate() call.
  275. *
  276. * @return boolean <kbd>True</kbd> if successfully authenticated
  277. */
  278. function authenticated()
  279. {
  280. if (!($this->storage_url || $this->cdnm_url) || !$this->auth_token) {
  281. return False;
  282. }
  283. return True;
  284. }
  285. /**
  286. * Toggle debugging - set cURL verbose flag
  287. */
  288. function setDebug($bool)
  289. {
  290. $this->dbug = $bool;
  291. $this->cfs_http->setDebug($bool);
  292. }
  293. }
  294. /**
  295. * Class for establishing connections to the Cloud Files storage system.
  296. * Connection instances are used to communicate with the storage system at
  297. * the account level; listing and deleting Containers and returning Container
  298. * instances.
  299. *
  300. * Example:
  301. * <code>
  302. * # Create the authentication instance
  303. * #
  304. * $auth = new CF_Authentication("username", "api_key");
  305. *
  306. * # Perform authentication request
  307. * #
  308. * $auth->authenticate();
  309. *
  310. * # Create a connection to the storage/cdn system(s) and pass in the
  311. * # validated CF_Authentication instance.
  312. * #
  313. * $conn = new CF_Connection($auth);
  314. *
  315. * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
  316. * # file. This API ships with a newer version obtained directly from
  317. * # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
  318. * # call the CF_Authentication instance's 'ssl_use_cabundle()' method.
  319. * #
  320. * # $conn->ssl_use_cabundle(); # bypass cURL's old CA bundle
  321. * </code>
  322. *
  323. * @package php-cloudfiles
  324. */
  325. class CF_Connection
  326. {
  327. public $dbug;
  328. public $cfs_http;
  329. public $cfs_auth;
  330. /**
  331. * Pass in a previously authenticated CF_Authentication instance.
  332. *
  333. * Example:
  334. * <code>
  335. * # Create the authentication instance
  336. * #
  337. * $auth = new CF_Authentication("username", "api_key");
  338. *
  339. * # Perform authentication request
  340. * #
  341. * $auth->authenticate();
  342. *
  343. * # Create a connection to the storage/cdn system(s) and pass in the
  344. * # validated CF_Authentication instance.
  345. * #
  346. * $conn = new CF_Connection($auth);
  347. *
  348. * # If you are connecting via Rackspace servers and have access
  349. * # to the servicenet network you can set the $servicenet to True
  350. * # like this.
  351. *
  352. * $conn = new CF_Connection($auth, $servicenet=True);
  353. *
  354. * </code>
  355. *
  356. * If the environement variable RACKSPACE_SERVICENET is defined it will
  357. * force to connect via the servicenet.
  358. *
  359. * @param obj $cfs_auth previously authenticated CF_Authentication instance
  360. * @param boolean $servicenet enable/disable access via Rackspace servicenet.
  361. * @throws AuthenticationException not authenticated
  362. */
  363. function __construct($cfs_auth, $servicenet=False)
  364. {
  365. if (isset($_ENV['RACKSPACE_SERVICENET']))
  366. $servicenet=True;
  367. $this->cfs_http = new CF_Http(DEFAULT_CF_API_VERSION);
  368. $this->cfs_auth = $cfs_auth;
  369. if (!$this->cfs_auth->authenticated()) {
  370. $e = "Need to pass in a previously authenticated ";
  371. $e .= "CF_Authentication instance.";
  372. throw new AuthenticationException($e);
  373. }
  374. $this->cfs_http->setCFAuth($this->cfs_auth, $servicenet=$servicenet);
  375. $this->dbug = False;
  376. }
  377. /**
  378. * Toggle debugging of instance and back-end HTTP module
  379. *
  380. * @param boolean $bool enable/disable cURL debugging
  381. */
  382. function setDebug($bool)
  383. {
  384. $this->dbug = (boolean) $bool;
  385. $this->cfs_http->setDebug($this->dbug);
  386. }
  387. /**
  388. * Close a connection
  389. *
  390. * Example:
  391. * <code>
  392. *
  393. * $conn->close();
  394. *
  395. * </code>
  396. *
  397. * Will close all current cUrl active connections.
  398. *
  399. */
  400. public function close()
  401. {
  402. $this->cfs_http->close();
  403. }
  404. /**
  405. * Cloud Files account information
  406. *
  407. * Return an array of two floats (since PHP only supports 32-bit integers);
  408. * number of containers on the account and total bytes used for the account.
  409. *
  410. * Example:
  411. * <code>
  412. * # ... authentication code excluded (see previous examples) ...
  413. * #
  414. * $conn = new CF_Authentication($auth);
  415. *
  416. * list($quantity, $bytes) = $conn->get_info();
  417. * print "Number of containers: " . $quantity . "\n";
  418. * print "Bytes stored in container: " . $bytes . "\n";
  419. * </code>
  420. *
  421. * @return array (number of containers, total bytes stored)
  422. * @throws InvalidResponseException unexpected response
  423. */
  424. function get_info()
  425. {
  426. list($status, $reason, $container_count, $total_bytes) =
  427. $this->cfs_http->head_account();
  428. #if ($status == 401 && $this->_re_auth()) {
  429. # return $this->get_info();
  430. #}
  431. if ($status < 200 || $status > 299) {
  432. throw new InvalidResponseException(
  433. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  434. }
  435. return array($container_count, $total_bytes);
  436. }
  437. /**
  438. * Create a Container
  439. *
  440. * Given a Container name, return a Container instance, creating a new
  441. * remote Container if it does not exit.
  442. *
  443. * Example:
  444. * <code>
  445. * # ... authentication code excluded (see previous examples) ...
  446. * #
  447. * $conn = new CF_Authentication($auth);
  448. *
  449. * $images = $conn->create_container("my photos");
  450. * </code>
  451. *
  452. * @param string $container_name container name
  453. * @return CF_Container
  454. * @throws SyntaxException invalid name
  455. * @throws InvalidResponseException unexpected response
  456. */
  457. function create_container($container_name=NULL)
  458. {
  459. if ($container_name != "0" and !isset($container_name))
  460. throw new SyntaxException("Container name not set.");
  461. if (!isset($container_name) or $container_name == "")
  462. throw new SyntaxException("Container name not set.");
  463. if (strpos($container_name, "/") !== False) {
  464. $r = "Container name '".$container_name;
  465. $r .= "' cannot contain a '/' character.";
  466. throw new SyntaxException($r);
  467. }
  468. if (strlen($container_name) > MAX_CONTAINER_NAME_LEN) {
  469. throw new SyntaxException(sprintf(
  470. "Container name exeeds %d bytes.",
  471. MAX_CONTAINER_NAME_LEN));
  472. }
  473. $return_code = $this->cfs_http->create_container($container_name);
  474. if (!$return_code) {
  475. throw new InvalidResponseException("Invalid response ("
  476. . $return_code. "): " . $this->cfs_http->get_error());
  477. }
  478. #if ($status == 401 && $this->_re_auth()) {
  479. # return $this->create_container($container_name);
  480. #}
  481. if ($return_code != 201 && $return_code != 202) {
  482. throw new InvalidResponseException(
  483. "Invalid response (".$return_code."): "
  484. . $this->cfs_http->get_error());
  485. }
  486. return new CF_Container($this->cfs_auth, $this->cfs_http, $container_name);
  487. }
  488. /**
  489. * Delete a Container
  490. *
  491. * Given either a Container instance or name, remove the remote Container.
  492. * The Container must be empty prior to removing it.
  493. *
  494. * Example:
  495. * <code>
  496. * # ... authentication code excluded (see previous examples) ...
  497. * #
  498. * $conn = new CF_Authentication($auth);
  499. *
  500. * $conn->delete_container("my photos");
  501. * </code>
  502. *
  503. * @param string|obj $container container name or instance
  504. * @return boolean <kbd>True</kbd> if successfully deleted
  505. * @throws SyntaxException missing proper argument
  506. * @throws InvalidResponseException invalid response
  507. * @throws NonEmptyContainerException container not empty
  508. * @throws NoSuchContainerException remote container does not exist
  509. */
  510. function delete_container($container=NULL)
  511. {
  512. $container_name = NULL;
  513. if (is_object($container)) {
  514. if (get_class($container) == "CF_Container") {
  515. $container_name = $container->name;
  516. }
  517. }
  518. if (is_string($container)) {
  519. $container_name = $container;
  520. }
  521. if ($container_name != "0" and !isset($container_name))
  522. throw new SyntaxException("Must specify container object or name.");
  523. $return_code = $this->cfs_http->delete_container($container_name);
  524. if (!$return_code) {
  525. throw new InvalidResponseException("Failed to obtain http response");
  526. }
  527. #if ($status == 401 && $this->_re_auth()) {
  528. # return $this->delete_container($container);
  529. #}
  530. if ($return_code == 409) {
  531. throw new NonEmptyContainerException(
  532. "Container must be empty prior to removing it.");
  533. }
  534. if ($return_code == 404) {
  535. throw new NoSuchContainerException(
  536. "Specified container did not exist to delete.");
  537. }
  538. if ($return_code != 204) {
  539. throw new InvalidResponseException(
  540. "Invalid response (".$return_code."): "
  541. . $this->cfs_http->get_error());
  542. }
  543. return True;
  544. }
  545. /**
  546. * Return a Container instance
  547. *
  548. * For the given name, return a Container instance if the remote Container
  549. * exists, otherwise throw a Not Found exception.
  550. *
  551. * Example:
  552. * <code>
  553. * # ... authentication code excluded (see previous examples) ...
  554. * #
  555. * $conn = new CF_Authentication($auth);
  556. *
  557. * $images = $conn->get_container("my photos");
  558. * print "Number of Objects: " . $images->count . "\n";
  559. * print "Bytes stored in container: " . $images->bytes . "\n";
  560. * </code>
  561. *
  562. * @param string $container_name name of the remote Container
  563. * @return container CF_Container instance
  564. * @throws NoSuchContainerException thrown if no remote Container
  565. * @throws InvalidResponseException unexpected response
  566. */
  567. function get_container($container_name=NULL)
  568. {
  569. list($status, $reason, $count, $bytes) =
  570. $this->cfs_http->head_container($container_name);
  571. #if ($status == 401 && $this->_re_auth()) {
  572. # return $this->get_container($container_name);
  573. #}
  574. if ($status == 404) {
  575. throw new NoSuchContainerException("Container not found.");
  576. }
  577. if ($status < 200 || $status > 299) {
  578. throw new InvalidResponseException(
  579. "Invalid response: ".$this->cfs_http->get_error());
  580. }
  581. return new CF_Container($this->cfs_auth, $this->cfs_http,
  582. $container_name, $count, $bytes);
  583. }
  584. /**
  585. * Return array of Container instances
  586. *
  587. * Return an array of CF_Container instances on the account. The instances
  588. * will be fully populated with Container attributes (bytes stored and
  589. * Object count)
  590. *
  591. * Example:
  592. * <code>
  593. * # ... authentication code excluded (see previous examples) ...
  594. * #
  595. * $conn = new CF_Authentication($auth);
  596. *
  597. * $clist = $conn->get_containers();
  598. * foreach ($clist as $cont) {
  599. * print "Container name: " . $cont->name . "\n";
  600. * print "Number of Objects: " . $cont->count . "\n";
  601. * print "Bytes stored in container: " . $cont->bytes . "\n";
  602. * }
  603. * </code>
  604. *
  605. * @return array An array of CF_Container instances
  606. * @throws InvalidResponseException unexpected response
  607. */
  608. function get_containers($limit=0, $marker=NULL)
  609. {
  610. list($status, $reason, $container_info) =
  611. $this->cfs_http->list_containers_info($limit, $marker);
  612. #if ($status == 401 && $this->_re_auth()) {
  613. # return $this->get_containers();
  614. #}
  615. if ($status < 200 || $status > 299) {
  616. throw new InvalidResponseException(
  617. "Invalid response: ".$this->cfs_http->get_error());
  618. }
  619. $containers = array();
  620. foreach ($container_info as $name => $info) {
  621. $containers[] = new CF_Container($this->cfs_auth, $this->cfs_http,
  622. $info['name'], $info["count"], $info["bytes"], False);
  623. }
  624. return $containers;
  625. }
  626. /**
  627. * Return list of remote Containers
  628. *
  629. * Return an array of strings containing the names of all remote Containers.
  630. *
  631. * Example:
  632. * <code>
  633. * # ... authentication code excluded (see previous examples) ...
  634. * #
  635. * $conn = new CF_Authentication($auth);
  636. *
  637. * $container_list = $conn->list_containers();
  638. * print_r($container_list);
  639. * Array
  640. * (
  641. * [0] => "my photos",
  642. * [1] => "my docs"
  643. * )
  644. * </code>
  645. *
  646. * @param integer $limit restrict results to $limit Containers
  647. * @param string $marker return results greater than $marker
  648. * @return array list of remote Containers
  649. * @throws InvalidResponseException unexpected response
  650. */
  651. function list_containers($limit=0, $marker=NULL)
  652. {
  653. list($status, $reason, $containers) =
  654. $this->cfs_http->list_containers($limit, $marker);
  655. #if ($status == 401 && $this->_re_auth()) {
  656. # return $this->list_containers($limit, $marker);
  657. #}
  658. if ($status < 200 || $status > 299) {
  659. throw new InvalidResponseException(
  660. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  661. }
  662. return $containers;
  663. }
  664. /**
  665. * Return array of information about remote Containers
  666. *
  667. * Return a nested array structure of Container info.
  668. *
  669. * Example:
  670. * <code>
  671. * # ... authentication code excluded (see previous examples) ...
  672. * #
  673. *
  674. * $container_info = $conn->list_containers_info();
  675. * print_r($container_info);
  676. * Array
  677. * (
  678. * ["my photos"] =>
  679. * Array
  680. * (
  681. * ["bytes"] => 78,
  682. * ["count"] => 2
  683. * )
  684. * ["docs"] =>
  685. * Array
  686. * (
  687. * ["bytes"] => 37323,
  688. * ["count"] => 12
  689. * )
  690. * )
  691. * </code>
  692. *
  693. * @param integer $limit restrict results to $limit Containers
  694. * @param string $marker return results greater than $marker
  695. * @return array nested array structure of Container info
  696. * @throws InvalidResponseException unexpected response
  697. */
  698. function list_containers_info($limit=0, $marker=NULL)
  699. {
  700. list($status, $reason, $container_info) =
  701. $this->cfs_http->list_containers_info($limit, $marker);
  702. #if ($status == 401 && $this->_re_auth()) {
  703. # return $this->list_containers_info($limit, $marker);
  704. #}
  705. if ($status < 200 || $status > 299) {
  706. throw new InvalidResponseException(
  707. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  708. }
  709. return $container_info;
  710. }
  711. /**
  712. * Return list of Containers that have been published to the CDN.
  713. *
  714. * Return an array of strings containing the names of published Containers.
  715. * Note that this function returns the list of any Container that has
  716. * ever been CDN-enabled regardless of it's existence in the storage
  717. * system.
  718. *
  719. * Example:
  720. * <code>
  721. * # ... authentication code excluded (see previous examples) ...
  722. * #
  723. * $conn = new CF_Authentication($auth);
  724. *
  725. * $public_containers = $conn->list_public_containers();
  726. * print_r($public_containers);
  727. * Array
  728. * (
  729. * [0] => "images",
  730. * [1] => "css",
  731. * [2] => "javascript"
  732. * )
  733. * </code>
  734. *
  735. * @param bool $enabled_only Will list all containers ever CDN enabled if * set to false or only currently enabled CDN containers if set to true. * Defaults to false.
  736. * @return array list of published Container names
  737. * @throws InvalidResponseException unexpected response
  738. */
  739. function list_public_containers($enabled_only=False)
  740. {
  741. list($status, $reason, $containers) =
  742. $this->cfs_http->list_cdn_containers($enabled_only);
  743. #if ($status == 401 && $this->_re_auth()) {
  744. # return $this->list_public_containers();
  745. #}
  746. if ($status < 200 || $status > 299) {
  747. throw new InvalidResponseException(
  748. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  749. }
  750. return $containers;
  751. }
  752. /**
  753. * Set a user-supplied callback function to report download progress
  754. *
  755. * The callback function is used to report incremental progress of a data
  756. * download functions (e.g. $container->list_objects(), $obj->read(), etc).
  757. * The specified function will be periodically called with the number of
  758. * bytes transferred until the entire download is complete. This callback
  759. * function can be useful for implementing "progress bars" for large
  760. * downloads.
  761. *
  762. * The specified callback function should take a single integer parameter.
  763. *
  764. * <code>
  765. * function read_callback($bytes_transferred) {
  766. * print ">> downloaded " . $bytes_transferred . " bytes.\n";
  767. * # ... do other things ...
  768. * return;
  769. * }
  770. *
  771. * $conn = new CF_Connection($auth_obj);
  772. * $conn->set_read_progress_function("read_callback");
  773. * print_r($conn->list_containers());
  774. *
  775. * # output would look like this:
  776. * #
  777. * >> downloaded 10 bytes.
  778. * >> downloaded 11 bytes.
  779. * Array
  780. * (
  781. * [0] => fuzzy.txt
  782. * [1] => space name
  783. * )
  784. * </code>
  785. *
  786. * @param string $func_name the name of the user callback function
  787. */
  788. function set_read_progress_function($func_name)
  789. {
  790. $this->cfs_http->setReadProgressFunc($func_name);
  791. }
  792. /**
  793. * Set a user-supplied callback function to report upload progress
  794. *
  795. * The callback function is used to report incremental progress of a data
  796. * upload functions (e.g. $obj->write() call). The specified function will
  797. * be periodically called with the number of bytes transferred until the
  798. * entire upload is complete. This callback function can be useful
  799. * for implementing "progress bars" for large uploads/downloads.
  800. *
  801. * The specified callback function should take a single integer parameter.
  802. *
  803. * <code>
  804. * function write_callback($bytes_transferred) {
  805. * print ">> uploaded " . $bytes_transferred . " bytes.\n";
  806. * # ... do other things ...
  807. * return;
  808. * }
  809. *
  810. * $conn = new CF_Connection($auth_obj);
  811. * $conn->set_write_progress_function("write_callback");
  812. * $container = $conn->create_container("stuff");
  813. * $obj = $container->create_object("foo");
  814. * $obj->write("The callback function will be called during upload.");
  815. *
  816. * # output would look like this:
  817. * # >> uploaded 51 bytes.
  818. * #
  819. * </code>
  820. *
  821. * @param string $func_name the name of the user callback function
  822. */
  823. function set_write_progress_function($func_name)
  824. {
  825. $this->cfs_http->setWriteProgressFunc($func_name);
  826. }
  827. /**
  828. * Use the Certificate Authority bundle included with this API
  829. *
  830. * Most versions of PHP with cURL support include an outdated Certificate
  831. * Authority (CA) bundle (the file that lists all valid certificate
  832. * signing authorities). The SSL certificates used by the Cloud Files
  833. * storage system are perfectly valid but have been created/signed by
  834. * a CA not listed in these outdated cURL distributions.
  835. *
  836. * As a work-around, we've included an updated CA bundle obtained
  837. * directly from cURL's web site (http://curl.haxx.se). You can direct
  838. * the API to use this CA bundle by calling this method prior to making
  839. * any remote calls. The best place to use this method is right after
  840. * the CF_Authentication instance has been instantiated.
  841. *
  842. * You can specify your own CA bundle by passing in the full pathname
  843. * to the bundle. You can use the included CA bundle by leaving the
  844. * argument blank.
  845. *
  846. * @param string $path Specify path to CA bundle (default to included)
  847. */
  848. function ssl_use_cabundle($path=NULL)
  849. {
  850. $this->cfs_http->ssl_use_cabundle($path);
  851. }
  852. #private function _re_auth()
  853. #{
  854. # $new_auth = new CF_Authentication(
  855. # $this->cfs_auth->username,
  856. # $this->cfs_auth->api_key,
  857. # $this->cfs_auth->auth_host,
  858. # $this->cfs_auth->account);
  859. # $new_auth->authenticate();
  860. # $this->cfs_auth = $new_auth;
  861. # $this->cfs_http->setCFAuth($this->cfs_auth);
  862. # return True;
  863. #}
  864. }
  865. /**
  866. * Container operations
  867. *
  868. * Containers are storage compartments where you put your data (objects).
  869. * A container is similar to a directory or folder on a conventional filesystem
  870. * with the exception that they exist in a flat namespace, you can not create
  871. * containers inside of containers.
  872. *
  873. * You also have the option of marking a Container as "public" so that the
  874. * Objects stored in the Container are publicly available via the CDN.
  875. *
  876. * @package php-cloudfiles
  877. */
  878. class CF_Container
  879. {
  880. public $cfs_auth;
  881. public $cfs_http;
  882. public $name;
  883. public $object_count;
  884. public $bytes_used;
  885. public $cdn_enabled;
  886. public $cdn_uri;
  887. public $cdn_ttl;
  888. public $cdn_log_retention;
  889. public $cdn_acl_user_agent;
  890. public $cdn_acl_referrer;
  891. /**
  892. * Class constructor
  893. *
  894. * Constructor for Container
  895. *
  896. * @param obj $cfs_auth CF_Authentication instance
  897. * @param obj $cfs_http HTTP connection manager
  898. * @param string $name name of Container
  899. * @param int $count number of Objects stored in this Container
  900. * @param int $bytes number of bytes stored in this Container
  901. * @throws SyntaxException invalid Container name
  902. */
  903. function __construct(&$cfs_auth, &$cfs_http, $name, $count=0,
  904. $bytes=0, $docdn=True)
  905. {
  906. if (strlen($name) > MAX_CONTAINER_NAME_LEN) {
  907. throw new SyntaxException("Container name exceeds "
  908. . "maximum allowed length.");
  909. }
  910. if (strpos($name, "/") !== False) {
  911. throw new SyntaxException(
  912. "Container names cannot contain a '/' character.");
  913. }
  914. $this->cfs_auth = $cfs_auth;
  915. $this->cfs_http = $cfs_http;
  916. $this->name = $name;
  917. $this->object_count = $count;
  918. $this->bytes_used = $bytes;
  919. $this->cdn_enabled = NULL;
  920. $this->cdn_uri = NULL;
  921. $this->cdn_ttl = NULL;
  922. $this->cdn_log_retention = NULL;
  923. $this->cdn_acl_user_agent = NULL;
  924. $this->cdn_acl_referrer = NULL;
  925. if ($this->cfs_http->getCDNMUrl() != NULL && $docdn) {
  926. $this->_cdn_initialize();
  927. }
  928. }
  929. /**
  930. * String representation of Container
  931. *
  932. * Pretty print the Container instance.
  933. *
  934. * @return string Container details
  935. */
  936. function __toString()
  937. {
  938. $me = sprintf("name: %s, count: %.0f, bytes: %.0f",
  939. $this->name, $this->object_count, $this->bytes_used);
  940. if ($this->cfs_http->getCDNMUrl() != NULL) {
  941. $me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f, logs retention: %s",
  942. $this->is_public() ? "Yes" : "No",
  943. $this->cdn_uri, $this->cdn_ttl,
  944. $this->cdn_log_retention ? "Yes" : "No"
  945. );
  946. if ($this->cdn_acl_user_agent != NULL) {
  947. $me .= ", cdn acl user agent: " . $this->cdn_acl_user_agent;
  948. }
  949. if ($this->cdn_acl_referrer != NULL) {
  950. $me .= ", cdn acl referrer: " . $this->cdn_acl_referrer;
  951. }
  952. }
  953. return $me;
  954. }
  955. /**
  956. * Enable Container content to be served via CDN or modify CDN attributes
  957. *
  958. * Either enable this Container's content to be served via CDN or
  959. * adjust its CDN attributes. This Container will always return the
  960. * same CDN-enabled URI each time it is toggled public/private/public.
  961. *
  962. * Example:
  963. * <code>
  964. * # ... authentication code excluded (see previous examples) ...
  965. * #
  966. * $conn = new CF_Authentication($auth);
  967. *
  968. * $public_container = $conn->create_container("public");
  969. *
  970. * # CDN-enable the container and set it's TTL for a month
  971. * #
  972. * $public_container->make_public(86400/2); # 12 hours (86400 seconds/day)
  973. * </code>
  974. *
  975. * @param int $ttl the time in seconds content will be cached in the CDN
  976. * @returns string the CDN enabled Container's URI
  977. * @throws CDNNotEnabledException CDN functionality not returned during auth
  978. * @throws AuthenticationException if auth token is not valid/expired
  979. * @throws InvalidResponseException unexpected response
  980. */
  981. function make_public($ttl=86400)
  982. {
  983. if ($this->cfs_http->getCDNMUrl() == NULL) {
  984. throw new CDNNotEnabledException(
  985. "Authentication response did not indicate CDN availability");
  986. }
  987. if ($this->cdn_uri != NULL) {
  988. # previously published, assume we're setting new attributes
  989. list($status, $reason, $cdn_uri) =
  990. $this->cfs_http->update_cdn_container($this->name,$ttl,
  991. $this->cdn_log_retention,
  992. $this->cdn_acl_user_agent,
  993. $this->cdn_acl_referrer);
  994. #if ($status == 401 && $this->_re_auth()) {
  995. # return $this->make_public($ttl);
  996. #}
  997. if ($status == 404) {
  998. # this instance _thinks_ the container was published, but the
  999. # cdn management system thinks otherwise - try again with a PUT
  1000. list($status, $reason, $cdn_uri) =
  1001. $this->cfs_http->add_cdn_container($this->name,$ttl);
  1002. }
  1003. } else {
  1004. # publish it for first time
  1005. list($status, $reason, $cdn_uri) =
  1006. $this->cfs_http->add_cdn_container($this->name,$ttl);
  1007. }
  1008. #if ($status == 401 && $this->_re_auth()) {
  1009. # return $this->make_public($ttl);
  1010. #}
  1011. if (!in_array($status, array(201,202))) {
  1012. throw new InvalidResponseException(
  1013. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1014. }
  1015. $this->cdn_enabled = True;
  1016. $this->cdn_ttl = $ttl;
  1017. $this->cdn_uri = $cdn_uri;
  1018. $this->cdn_log_retention = False;
  1019. $this->cdn_acl_user_agent = "";
  1020. $this->cdn_acl_referrer = "";
  1021. return $this->cdn_uri;
  1022. }
  1023. /**
  1024. * Enable ACL restriction by User Agent for this container.
  1025. *
  1026. * Example:
  1027. * <code>
  1028. * # ... authentication code excluded (see previous examples) ...
  1029. * #
  1030. * $conn = new CF_Authentication($auth);
  1031. *
  1032. * $public_container = $conn->get_container("public");
  1033. *
  1034. * # Enable ACL by Referrer
  1035. * $public_container->acl_referrer("Mozilla");
  1036. * </code>
  1037. *
  1038. * @returns boolean True if successful
  1039. * @throws CDNNotEnabledException CDN functionality not returned during auth
  1040. * @throws AuthenticationException if auth token is not valid/expired
  1041. * @throws InvalidResponseException unexpected response
  1042. */
  1043. function acl_user_agent($cdn_acl_user_agent="") {
  1044. if ($this->cfs_http->getCDNMUrl() == NULL) {
  1045. throw new CDNNotEnabledException(
  1046. "Authentication response did not indicate CDN availability");
  1047. }
  1048. list($status,$reason) =
  1049. $this->cfs_http->update_cdn_container($this->name,
  1050. $this->cdn_ttl,
  1051. $this->cdn_log_retention,
  1052. $cdn_acl_user_agent,
  1053. $this->cdn_acl_referrer
  1054. );
  1055. if (!in_array($status, array(202,404))) {
  1056. throw new InvalidResponseException(
  1057. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1058. }
  1059. $this->cdn_acl_user_agent = $cdn_acl_user_agent;
  1060. return True;
  1061. }
  1062. /**
  1063. * Enable ACL restriction by referer for this container.
  1064. *
  1065. * Example:
  1066. * <code>
  1067. * # ... authentication code excluded (see previous examples) ...
  1068. * #
  1069. * $conn = new CF_Authentication($auth);
  1070. *
  1071. * $public_container = $conn->get_container("public");
  1072. *
  1073. * # Enable Referrer
  1074. * $public_container->acl_referrer("http://www.example.com/gallery.php");
  1075. * </code>
  1076. *
  1077. * @returns boolean True if successful
  1078. * @throws CDNNotEnabledException CDN functionality not returned during auth
  1079. * @throws AuthenticationException if auth token is not valid/expired
  1080. * @throws InvalidResponseException unexpected response
  1081. */
  1082. function acl_referrer($cdn_acl_referrer="") {
  1083. if ($this->cfs_http->getCDNMUrl() == NULL) {
  1084. throw new CDNNotEnabledException(
  1085. "Authentication response did not indicate CDN availability");
  1086. }
  1087. list($status,$reason) =
  1088. $this->cfs_http->update_cdn_container($this->name,
  1089. $this->cdn_ttl,
  1090. $this->cdn_log_retention,
  1091. $this->cdn_acl_user_agent,
  1092. $cdn_acl_referrer
  1093. );
  1094. if (!in_array($status, array(202,404))) {
  1095. throw new InvalidResponseException(
  1096. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1097. }
  1098. $this->cdn_acl_referrer = $cdn_acl_referrer;
  1099. return True;
  1100. }
  1101. /**
  1102. * Enable log retention for this CDN container.
  1103. *
  1104. * Enable CDN log retention on the container. If enabled logs will
  1105. * be periodically (at unpredictable intervals) compressed and
  1106. * uploaded to a ".CDN_ACCESS_LOGS" container in the form of
  1107. * "container_name.YYYYMMDDHH-XXXX.gz". Requires CDN be enabled on
  1108. * the account.
  1109. *
  1110. * Example:
  1111. * <code>
  1112. * # ... authentication code excluded (see previous examples) ...
  1113. * #
  1114. * $conn = new CF_Authentication($auth);
  1115. *
  1116. * $public_container = $conn->get_container("public");
  1117. *
  1118. * # Enable logs retention.
  1119. * $public_container->log_retention(True);
  1120. * </code>
  1121. *
  1122. * @returns boolean True if successful
  1123. * @throws CDNNotEnabledException CDN functionality not returned during auth
  1124. * @throws AuthenticationException if auth token is not valid/expired
  1125. * @throws InvalidResponseException unexpected response
  1126. */
  1127. function log_retention($cdn_log_retention=False) {
  1128. if ($this->cfs_http->getCDNMUrl() == NULL) {
  1129. throw new CDNNotEnabledException(
  1130. "Authentication response did not indicate CDN availability");
  1131. }
  1132. list($status,$reason) =
  1133. $this->cfs_http->update_cdn_container($this->name,
  1134. $this->cdn_ttl,
  1135. $cdn_log_retention,
  1136. $this->cdn_acl_user_agent,
  1137. $this->cdn_acl_referrer
  1138. );
  1139. if (!in_array($status, array(202,404))) {
  1140. throw new InvalidResponseException(
  1141. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1142. }
  1143. $this->cdn_log_retention = $cdn_log_retention;
  1144. return True;
  1145. }
  1146. /**
  1147. * Disable the CDN sharing for this container
  1148. *
  1149. * Use this method to disallow distribution into the CDN of this Container's
  1150. * content.
  1151. *
  1152. * NOTE: Any content already cached in the CDN will continue to be served
  1153. * from its cache until the TTL expiration transpires. The default
  1154. * TTL is typically one day, so "privatizing" the Container will take
  1155. * up to 24 hours before the content is purged from the CDN cache.
  1156. *
  1157. * Example:
  1158. * <code>
  1159. * # ... authentication code excluded (see previous examples) ...
  1160. * #
  1161. * $conn = new CF_Authentication($auth);
  1162. *
  1163. * $public_container = $conn->get_container("public");
  1164. *
  1165. * # Disable CDN accessability
  1166. * # ... still cached up to a month based on previous example
  1167. * #
  1168. * $public_container->make_private();
  1169. * </code>
  1170. *
  1171. * @returns boolean True if successful
  1172. * @throws CDNNotEnabledException CDN functionality not returned during auth
  1173. * @throws AuthenticationException if auth token is not valid/expired
  1174. * @throws InvalidResponseException unexpected response
  1175. */
  1176. function make_private()
  1177. {
  1178. if ($this->cfs_http->getCDNMUrl() == NULL) {
  1179. throw new CDNNotEnabledException(
  1180. "Authentication response did not indicate CDN availability");
  1181. }
  1182. list($status,$reason) = $this->cfs_http->remove_cdn_container($this->name);
  1183. #if ($status == 401 && $this->_re_auth()) {
  1184. # return $this->make_private();
  1185. #}
  1186. if (!in_array($status, array(202,404))) {
  1187. throw new InvalidResponseException(
  1188. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1189. }
  1190. $this->cdn_enabled = False;
  1191. $this->cdn_ttl = NULL;
  1192. $this->cdn_uri = NULL;
  1193. $this->cdn_log_retention = NULL;
  1194. $this->cdn_acl_user_agent = NULL;
  1195. $this->cdn_acl_referrer = NULL;
  1196. return True;
  1197. }
  1198. /**
  1199. * Check if this Container is being publicly served via CDN
  1200. *
  1201. * Use this method to determine if the Container's content is currently
  1202. * available through the CDN.
  1203. *
  1204. * Example:
  1205. * <code>
  1206. * # ... authentication code excluded (see previous examples) ...
  1207. * #
  1208. * $conn = new CF_Authentication($auth);
  1209. *
  1210. * $public_container = $conn->get_container("public");
  1211. *
  1212. * # Display CDN accessability
  1213. * #
  1214. * $public_container->is_public() ? print "Yes" : print "No";
  1215. * </code>
  1216. *
  1217. * @returns boolean True if enabled, False otherwise
  1218. */
  1219. function is_public()
  1220. {
  1221. return $this->cdn_enabled == True ? True : False;
  1222. }
  1223. /**
  1224. * Create a new remote storage Object
  1225. *
  1226. * Return a new Object instance. If the remote storage Object exists,
  1227. * the instance's attributes are populated.
  1228. *
  1229. * Example:
  1230. * <code>
  1231. * # ... authentication code excluded (see previous examples) ...
  1232. * #
  1233. * $conn = new CF_Authentication($auth);
  1234. *
  1235. * $public_container = $conn->get_container("public");
  1236. *
  1237. * # This creates a local instance of a storage object but only creates
  1238. * # it in the storage system when the object's write() method is called.
  1239. * #
  1240. * $pic = $public_container->create_object("baby.jpg");
  1241. * </code>
  1242. *
  1243. * @param string $obj_name name of storage Object
  1244. * @return obj CF_Object instance
  1245. */
  1246. function create_object($obj_name=NULL)
  1247. {
  1248. return new CF_Object($this, $obj_name);
  1249. }
  1250. /**
  1251. * Return an Object instance for the remote storage Object
  1252. *
  1253. * Given a name, return a Object instance representing the
  1254. * remote storage object.
  1255. *
  1256. * Example:
  1257. * <code>
  1258. * # ... authentication code excluded (see previous examples) ...
  1259. * #
  1260. * $conn = new CF_Authentication($auth);
  1261. *
  1262. * $public_container = $conn->get_container("public");
  1263. *
  1264. * # This call only fetches header information and not the content of
  1265. * # the storage object. Use the Object's read() or stream() methods
  1266. * # to obtain the object's data.
  1267. * #
  1268. * $pic = $public_container->get_object("baby.jpg");
  1269. * </code>
  1270. *
  1271. * @param string $obj_name name of storage Object
  1272. * @return obj CF_Object instance
  1273. */
  1274. function get_object($obj_name=NULL)
  1275. {
  1276. return new CF_Object($this, $obj_name, True);
  1277. }
  1278. /**
  1279. * Return a list of Objects
  1280. *
  1281. * Return an array of strings listing the Object names in this Container.
  1282. *
  1283. * Example:
  1284. * <code>
  1285. * # ... authentication code excluded (see previous examples) ...
  1286. * #
  1287. * $images = $conn->get_container("my photos");
  1288. *
  1289. * # Grab the list of all storage objects
  1290. * #
  1291. * $all_objects = $images->list_objects();
  1292. *
  1293. * # Grab subsets of all storage objects
  1294. * #
  1295. * $first_ten = $images->list_objects(10);
  1296. *
  1297. * # Note the use of the previous result's last object name being
  1298. * # used as the 'marker' parameter to fetch the next 10 objects
  1299. * #
  1300. * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
  1301. *
  1302. * # Grab images starting with "birthday_party" and default limit/marker
  1303. * # to match all photos with that prefix
  1304. * #
  1305. * $prefixed = $images->list_objects(0, NULL, "birthday");
  1306. *
  1307. * # Assuming you have created the appropriate directory marker Objects,
  1308. * # you can traverse your pseudo-hierarchical containers
  1309. * # with the "path" argument.
  1310. * #
  1311. * $animals = $images->list_objects(0,NULL,NULL,"pictures/animals");
  1312. * $dogs = $images->list_objects(0,NULL,NULL,"pictures/animals/dogs");
  1313. * </code>
  1314. *
  1315. * @param int $limit <i>optional</i> only return $limit names
  1316. * @param int $marker <i>optional</i> subset of names starting at $marker
  1317. * @param string $prefix <i>optional</i> Objects whose names begin with $prefix
  1318. * @param string $path <i>optional</i> only return results under "pathname"
  1319. * @return array array of strings
  1320. * @throws InvalidResponseException unexpected response
  1321. */
  1322. function list_objects($limit=0, $marker=NULL, $prefix=NULL, $path=NULL)
  1323. {
  1324. list($status, $reason, $obj_list) =
  1325. $this->cfs_http->list_objects($this->name, $limit,
  1326. $marker, $prefix, $path);
  1327. #if ($status == 401 && $this->_re_auth()) {
  1328. # return $this->list_objects($limit, $marker, $prefix, $path);
  1329. #}
  1330. if ($status < 200 || $status > 299) {
  1331. throw new InvalidResponseException(
  1332. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1333. }
  1334. return $obj_list;
  1335. }
  1336. /**
  1337. * Return an array of Objects
  1338. *
  1339. * Return an array of Object instances in this Container.
  1340. *
  1341. * Example:
  1342. * <code>
  1343. * # ... authentication code excluded (see previous examples) ...
  1344. * #
  1345. * $images = $conn->get_container("my photos");
  1346. *
  1347. * # Grab the list of all storage objects
  1348. * #
  1349. * $all_objects = $images->get_objects();
  1350. *
  1351. * # Grab subsets of all storage objects
  1352. * #
  1353. * $first_ten = $images->get_objects(10);
  1354. *
  1355. * # Note the use of the previous result's last object name being
  1356. * # used as the 'marker' parameter to fetch the next 10 objects
  1357. * #
  1358. * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
  1359. *
  1360. * # Grab images starting with "birthday_party" and default limit/marker
  1361. * # to match all photos with that prefix
  1362. * #
  1363. * $prefixed = $images->get_objects(0, NULL, "birthday");
  1364. *
  1365. * # Assuming you have created the appropriate directory marker Objects,
  1366. * # you can traverse your pseudo-hierarchical containers
  1367. * # with the "path" argument.
  1368. * #
  1369. * $animals = $images->get_objects(0,NULL,NULL,"pictures/animals");
  1370. * $dogs = $images->get_objects(0,NULL,NULL,"pictures/animals/dogs");
  1371. * </code>
  1372. *
  1373. * @param int $limit <i>optional</i> only return $limit names
  1374. * @param int $marker <i>optional</i> subset of names starting at $marker
  1375. * @param string $prefix <i>optional</i> Objects whose names begin with $prefix
  1376. * @param string $path <i>optional</i> only return results under "pathname"
  1377. * @return array array of strings
  1378. * @throws InvalidResponseException unexpected response
  1379. */
  1380. function get_objects($limit=0, $marker=NULL, $prefix=NULL, $path=NULL)
  1381. {
  1382. list($status, $reason, $obj_array) =
  1383. $this->cfs_http->get_objects($this->name, $limit,
  1384. $marker, $prefix, $path);
  1385. #if ($status == 401 && $this->_re_auth()) {
  1386. # return $this->get_objects($limit, $marker, $prefix, $path);
  1387. #}
  1388. if ($status < 200 || $status > 299) {
  1389. throw new InvalidResponseException(
  1390. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1391. }
  1392. $objects = array();
  1393. foreach ($obj_array as $obj) {
  1394. $tmp = new CF_Object($this, $obj["name"], False, False);
  1395. $tmp->content_type = $obj["content_type"];
  1396. $tmp->content_length = (float) $obj["bytes"];
  1397. $tmp->set_etag($obj["hash"]);
  1398. $tmp->last_modified = $obj["last_modified"];
  1399. $objects[] = $tmp;
  1400. }
  1401. return $objects;
  1402. }
  1403. /**
  1404. * Delete a remote storage Object
  1405. *
  1406. * Given an Object instance or name, permanently remove the remote Object
  1407. * and all associated metadata.
  1408. *
  1409. * Example:
  1410. * <code>
  1411. * # ... authentication code excluded (see previous examples) ...
  1412. * #
  1413. * $conn = new CF_Authentication($auth);
  1414. *
  1415. * $images = $conn->get_container("my photos");
  1416. *
  1417. * # Delete specific object
  1418. * #
  1419. * $images->delete_object("disco_dancing.jpg");
  1420. * </code>
  1421. *
  1422. * @param obj $obj name or instance of Object to delete
  1423. * @return boolean <kbd>True</kbd> if successfully removed
  1424. * @throws SyntaxException invalid Object name
  1425. * @throws NoSuchObjectException remote Object does not exist
  1426. * @throws InvalidResponseException unexpected response
  1427. */
  1428. function delete_object($obj)
  1429. {
  1430. $obj_name = NULL;
  1431. if (is_object($obj)) {
  1432. if (get_class($obj) == "CF_Object") {
  1433. $obj_name = $obj->name;
  1434. }
  1435. }
  1436. if (is_string($obj)) {
  1437. $obj_name = $obj;
  1438. }
  1439. if (!$obj_name) {
  1440. throw new SyntaxException("Object name not set.");
  1441. }
  1442. $status = $this->cfs_http->delete_object($this->name, $obj_name);
  1443. #if ($status == 401 && $this->_re_auth()) {
  1444. # return $this->delete_object($obj);
  1445. #}
  1446. if ($status == 404) {
  1447. $m = "Specified object '".$this->name."/".$obj_name;
  1448. $m.= "' did not exist to delete.";
  1449. throw new NoSuchObjectException($m);
  1450. }
  1451. if ($status != 204) {
  1452. throw new InvalidResponseException(
  1453. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1454. }
  1455. return True;
  1456. }
  1457. /**
  1458. * Helper function to create "path" elements for a given Object name
  1459. *
  1460. * Given an Object whos name contains '/' path separators, this function
  1461. * will create the "directory marker" Objects of one byte with the
  1462. * Content-Type of "application/folder".
  1463. *
  1464. * It assumes the last element of the full path is the "real" Object
  1465. * and does NOT create a remote storage Object for that last element.
  1466. */
  1467. function create_paths($path_name)
  1468. {
  1469. if ($path_name[0] == '/') {
  1470. $path_name = mb_substr($path_name, 0, 1);
  1471. }
  1472. $elements = explode('/', $path_name, -1);
  1473. $build_path = "";
  1474. foreach ($elements as $idx => $val) {
  1475. if (!$build_path) {
  1476. $build_path = $val;
  1477. } else {
  1478. $build_path .= "/" . $val;
  1479. }
  1480. $obj = new CF_Object($this, $build_path);
  1481. $obj->content_type = "application/directory";
  1482. $obj->write(".", 1);
  1483. }
  1484. }
  1485. /**
  1486. * Internal method to grab CDN/Container info if appropriate to do so
  1487. *
  1488. * @throws InvalidResponseException unexpected response
  1489. */
  1490. private function _cdn_initialize()
  1491. {
  1492. list($status, $reason, $cdn_enabled, $cdn_uri, $cdn_ttl,
  1493. $cdn_log_retention, $cdn_acl_user_agent, $cdn_acl_referrer) =
  1494. $this->cfs_http->head_cdn_container($this->name);
  1495. #if ($status == 401 && $this->_re_auth()) {
  1496. # return $this->_cdn_initialize();
  1497. #}
  1498. if (!in_array($status, array(204,404))) {
  1499. throw new InvalidResponseException(
  1500. "Invalid response (".$status."): ".$this->cfs_http->get_error());
  1501. }
  1502. $this->cdn_enabled = $cdn_enabled;
  1503. $this->cdn_uri = $cdn_uri;
  1504. $this->cdn_ttl = $cdn_ttl;
  1505. $this->cdn_log_retention = $cdn_log_retention;
  1506. $this->cdn_acl_user_agent = $cdn_acl_user_agent;
  1507. $this->cdn_acl_referrer = $cdn_acl_referrer;
  1508. }
  1509. #private function _re_auth()
  1510. #{
  1511. # $new_auth = new CF_Authentication(
  1512. # $this->cfs_auth->username,
  1513. # $this->cfs_auth->api_key,
  1514. # $this->cfs_auth->auth_host,
  1515. # $this->cfs_auth->account);
  1516. # $new_auth->authenticate();
  1517. # $this->cfs_auth = $new_auth;
  1518. # $this->cfs_http->setCFAuth($this->cfs_auth);
  1519. # return True;
  1520. #}
  1521. }
  1522. /**
  1523. * Object operations
  1524. *
  1525. * An Object is analogous to a file on a conventional filesystem. You can
  1526. * read data from, or write data to your Objects. You can also associate
  1527. * arbitrary metadata with them.
  1528. *
  1529. * @package php-cloudfiles
  1530. */
  1531. class CF_Object
  1532. {
  1533. public $container;
  1534. public $name;
  1535. public $last_modified;
  1536. public $content_type;
  1537. public $content_length;
  1538. public $metadata;
  1539. private $etag;
  1540. /**
  1541. * Class constructor
  1542. *
  1543. * @param obj $container CF_Container instance
  1544. * @param string $name name of Object
  1545. * @param boolean $force_exists if set, throw an error if Object doesn't exist
  1546. */
  1547. function __construct(&$container, $name, $force_exists=False, $dohead=True)
  1548. {
  1549. if ($name[0] == "/") {
  1550. $r = "Object name '".$name;
  1551. $r .= "' cannot contain begin with a '/' character.";
  1552. throw new SyntaxException($r);
  1553. }
  1554. if (strlen($name) > MAX_OBJECT_NAME_LEN) {
  1555. throw new SyntaxException("Object name exceeds "
  1556. . "maximum allowed length.");
  1557. }
  1558. $this->container = $container;
  1559. $this->name = $name;
  1560. $this->etag = NULL;
  1561. $this->_etag_override = False;
  1562. $this->last_modified = NULL;
  1563. $this->content_type = NULL;
  1564. $this->content_length = 0;
  1565. $this->metadata = array();
  1566. if ($dohead) {
  1567. if (!$this->_initialize() && $force_exists) {
  1568. throw new NoSuchObjectException("No such object '".$name."'");
  1569. }
  1570. }
  1571. }
  1572. /**
  1573. * String representation of Object
  1574. *
  1575. * Pretty print the Object's location and name
  1576. *
  1577. * @return string Object information
  1578. */
  1579. function __toString()
  1580. {
  1581. return $this->container->name . "/" . $this->name;
  1582. }
  1583. /**
  1584. * Internal check to get the proper mimetype.
  1585. *
  1586. * This function would go over the available PHP methods to get
  1587. * the MIME type.
  1588. *
  1589. * By default it will try to use the PHP fileinfo library which is
  1590. * available from PHP 5.3 or as an PECL extension
  1591. * (http://pecl.php.net/package/Fileinfo).
  1592. *
  1593. * It will get the magic file by default from the system wide file
  1594. * which is usually available in /usr/share/magic on Unix or try
  1595. * to use the file specified in the source directory of the API
  1596. * (share directory).
  1597. *
  1598. * if fileinfo is not available it will try to use the internal
  1599. * mime_content_type function.
  1600. *
  1601. * @param string $handle name of file or buffer to guess the type from
  1602. * @return boolean <kbd>True</kbd> if successful
  1603. * @throws BadContentTypeException
  1604. */
  1605. function _guess_content_type($handle) {
  1606. if ($this->content_type)
  1607. return;
  1608. w3_require_once(W3TC_INC_DIR . '/functions/mime.php');
  1609. $this->content_type = w3_get_mime_type($handle);
  1610. if (!$this->content_type) {
  1611. throw new BadContentTypeException("Required Content-Type not set");
  1612. }
  1613. return True;
  1614. }
  1615. /**
  1616. * String representation of the Object's public URI
  1617. *
  1618. * A string representing the Object's public URI assuming that it's
  1619. * parent Container is CDN-enabled.
  1620. *
  1621. * Example:
  1622. * <code>
  1623. * # ... authentication/connection/container code excluded
  1624. * # ... see previous examples
  1625. *
  1626. * # Print out the Object's CDN URI (if it has one) in an HTML img-tag
  1627. * #
  1628. * print "<img src='$pic->public_uri()' />\n";
  1629. * </code>
  1630. *
  1631. * @return string Object's public URI or NULL
  1632. */
  1633. function public_uri()
  1634. {
  1635. if ($this->container->cdn_enabled) {
  1636. return $this->container->cdn_uri . "/" . $this->name;
  1637. }
  1638. return NULL;
  1639. }
  1640. /**
  1641. * Read the remote Object's data
  1642. *
  1643. * Returns the Object's data. This is useful for smaller Objects such
  1644. * as images or office documents. Object's with larger content should use
  1645. * the stream() method below.
  1646. *
  1647. * Pass in $hdrs array to set specific custom HTTP headers such as
  1648. * If-Match, If-None-Match, If-Modified-Since, Range, etc.
  1649. *
  1650. * Example:
  1651. * <code>
  1652. * # ... authentication/connection/container code excluded
  1653. * # ... see previous examples
  1654. *
  1655. * $my_docs = $conn->get_container("documents");
  1656. * $doc = $my_docs->get_object("README");
  1657. * $data = $doc->read(); # read image content into a string variable
  1658. * print $data;
  1659. *
  1660. * # Or see stream() below for a different example.
  1661. * #
  1662. * </code>
  1663. *
  1664. * @param array $hdrs user-defined headers (Range, If-Match, etc.)
  1665. * @return string Object's data
  1666. * @throws InvalidResponseException unexpected response
  1667. */
  1668. function read($hdrs=array())
  1669. {
  1670. list($status, $reason, $data) =
  1671. $this->container->cfs_http->get_object_to_string($this, $hdrs);
  1672. #if ($status == 401 && $this->_re_auth()) {
  1673. # return $this->read($hdrs);
  1674. #}
  1675. if (($status < 200) || ($status > 299
  1676. && $status != 412 && $status != 304)) {
  1677. throw new InvalidResponseException("Invalid response (".$status."): "
  1678. . $this->container->cfs_http->get_error());
  1679. }
  1680. return $data;
  1681. }
  1682. /**
  1683. * Streaming read of Object's data
  1684. *
  1685. * Given an open PHP resource (see PHP's fopen() method), fetch the Object's
  1686. * data and write it to the open resource handle. This is useful for
  1687. * streaming an Object's content to the browser (videos, images) or for
  1688. * fetching content to a local file.
  1689. *
  1690. * Pass in $hdrs array to set specific custom HTTP headers such as
  1691. * If-Match, If-None-Match, If-Modified-Since, Range, etc.
  1692. *
  1693. * Example:
  1694. * <code>
  1695. * # ... authentication/connection/container code excluded
  1696. * # ... see previous examples
  1697. *
  1698. * # Assuming this is a web script to display the README to the
  1699. * # user's browser:
  1700. * #
  1701. * <?php
  1702. * // grab README from storage system
  1703. * //
  1704. * $my_docs = $conn->get_container("documents");
  1705. * $doc = $my_docs->get_object("README");
  1706. *
  1707. * // Hand it back to user's browser with appropriate content-type
  1708. * //
  1709. * header("Content-Type: " . $doc->content_type);
  1710. * $output = fopen("php://output", "w");
  1711. * $doc->stream($output); # stream object content to PHP's output buffer
  1712. * fclose($output);
  1713. * ?>
  1714. *
  1715. * # See read() above for a more simple example.
  1716. * #
  1717. * </code>
  1718. *
  1719. * @param resource $fp open resource for writing data to
  1720. * @param array $hdrs user-defined headers (Range, If-Match, etc.)
  1721. * @return string Object's data
  1722. * @throws InvalidResponseException unexpected response
  1723. */
  1724. function stream(&$fp, $hdrs=array())
  1725. {
  1726. list($status, $reason) =
  1727. $this->container->cfs_http->get_object_to_stream($this,$fp,$hdrs);
  1728. #if ($status == 401 && $this->_re_auth()) {
  1729. # return $this->stream($fp, $hdrs);
  1730. #}
  1731. if (($status < 200) || ($status > 299
  1732. && $status != 412 && $status != 304)) {
  1733. throw new InvalidResponseException("Invalid response (".$status."): "
  1734. .$reason);
  1735. }
  1736. return True;
  1737. }
  1738. /**
  1739. * Store new Object metadata
  1740. *
  1741. * Write's an Object's metadata to the remote Object. This will overwrite
  1742. * an prior Object metadata.
  1743. *
  1744. * Example:
  1745. * <code>
  1746. * # ... authentication/connection/container code excluded
  1747. * # ... see previous examples
  1748. *
  1749. * $my_docs = $conn->get_container("documents");
  1750. * $doc = $my_docs->get_object("README");
  1751. *
  1752. * # Define new metadata for the object
  1753. * #
  1754. * $doc->metadata = array(
  1755. * "Author" => "EJ",
  1756. * "Subject" => "How to use the PHP tests",
  1757. * "Version" => "1.2.2"
  1758. * );
  1759. *
  1760. * # Push the new metadata up to the storage system
  1761. * #
  1762. * $doc->sync_metadata();
  1763. * </code>
  1764. *
  1765. * @return boolean <kbd>True</kbd> if successful, <kbd>False</kbd> otherwise
  1766. * @throws InvalidResponseException unexpected response
  1767. */
  1768. function sync_metadata()
  1769. {
  1770. if (!empty($this->metadata)) {
  1771. $status = $this->container->cfs_http->update_object($this);
  1772. #if ($status == 401 && $this->_re_auth()) {
  1773. # return $this->sync_metadata();
  1774. #}
  1775. if ($status != 202) {
  1776. throw new InvalidResponseException("Invalid response ("
  1777. .$status."): ".$this->container->cfs_http->get_error());
  1778. }
  1779. return True;
  1780. }
  1781. return False;
  1782. }
  1783. /**
  1784. * Upload Object's data to Cloud Files
  1785. *
  1786. * Write data to the remote Object. The $data argument can either be a
  1787. * PHP resource open for reading (see PHP's fopen() method) or an in-memory
  1788. * variable. If passing in a PHP resource, you must also include the $bytes
  1789. * parameter.
  1790. *
  1791. * Example:
  1792. * <code>
  1793. * # ... authentication/connection/container code excluded
  1794. * # ... see previous examples
  1795. *
  1796. * $my_docs = $conn->get_container("documents");
  1797. * $doc = $my_docs->get_object("README");
  1798. *
  1799. * # Upload placeholder text in my README
  1800. * #
  1801. * $doc->write("This is just placeholder text for now...");
  1802. * </code>
  1803. *
  1804. * @param string|resource $data string or open resource
  1805. * @param float $bytes amount of data to upload (required for resources)
  1806. * @param boolean $verify generate, send, and compare MD5 checksums
  1807. * @return boolean <kbd>True</kbd> when data uploaded successfully
  1808. * @throws SyntaxException missing required parameters
  1809. * @throws BadContentTypeException if no Content-Type was/could be set
  1810. * @throws MisMatchedChecksumException $verify is set and checksums unequal
  1811. * @throws InvalidResponseException unexpected response
  1812. */
  1813. function write($data=NULL, $bytes=0, $verify=True)
  1814. {
  1815. if (!$data) {
  1816. throw new SyntaxException("Missing data source.");
  1817. }
  1818. if ($bytes > MAX_OBJECT_SIZE) {
  1819. throw new SyntaxException("Bytes exceeds maximum object size.");
  1820. }
  1821. if ($verify) {
  1822. if (!$this->_etag_override) {
  1823. $this->etag = $this->compute_md5sum($data);
  1824. }
  1825. } else {
  1826. $this->etag = NULL;
  1827. }
  1828. $close_fh = False;
  1829. if (!is_resource($data)) {
  1830. # A hack to treat string data as a file handle. php://memory feels
  1831. # like a better option, but it seems to break on Windows so use
  1832. # a temporary file instead.
  1833. #
  1834. $fp = fopen("php://temp", "wb+");
  1835. #$fp = fopen("php://memory", "wb+");
  1836. fwrite($fp, $data, strlen($data));
  1837. rewind($fp);
  1838. $close_fh = True;
  1839. $this->content_length = (float) strlen($data);
  1840. if ($this->content_length > MAX_OBJECT_SIZE) {
  1841. throw new SyntaxException("Data exceeds maximum object size");
  1842. }
  1843. $ct_data = substr($data, 0, 64);
  1844. } else {
  1845. $this->content_length = $bytes;
  1846. $fp = $data;
  1847. $ct_data = fread($data, 64);
  1848. rewind($data);
  1849. }
  1850. $this->_guess_content_type($ct_data);
  1851. list($status, $reason, $etag) =
  1852. $this->container->cfs_http->put_object($this, $fp);
  1853. #if ($status == 401 && $this->_re_auth()) {
  1854. # return $this->write($data, $bytes, $verify);
  1855. #}
  1856. if ($status == 412) {
  1857. if ($close_fh) { fclose($fp); }
  1858. throw new SyntaxException("Missing Content-Type header");
  1859. }
  1860. if ($status == 422) {
  1861. if ($close_fh) { fclose($fp); }
  1862. throw new MisMatchedChecksumException(
  1863. "Supplied and computed checksums do not match.");
  1864. }
  1865. if ($status != 201) {
  1866. if ($close_fh) { fclose($fp); }
  1867. throw new InvalidResponseException("Invalid response (".$status."): "
  1868. . $this->container->cfs_http->get_error());
  1869. }
  1870. if (!$verify) {
  1871. $this->etag = $etag;
  1872. }
  1873. if ($close_fh) { fclose($fp); }
  1874. return True;
  1875. }
  1876. /**
  1877. * Upload Object data from local filename
  1878. *
  1879. * This is a convenience function to upload the data from a local file. A
  1880. * True value for $verify will cause the method to compute the Object's MD5
  1881. * checksum prior to uploading.
  1882. *
  1883. * Example:
  1884. * <code>
  1885. * # ... authentication/connection/container code excluded
  1886. * # ... see previous examples
  1887. *
  1888. * $my_docs = $conn->get_container("documents");
  1889. * $doc = $my_docs->get_object("README");
  1890. *
  1891. * # Upload my local README's content
  1892. * #
  1893. * $doc->load_from_filename("/home/ej/cloudfiles/readme");
  1894. * </code>
  1895. *
  1896. * @param string $filename full path to local file
  1897. * @param boolean $verify enable local/remote MD5 checksum validation
  1898. * @return boolean <kbd>True</kbd> if data uploaded successfully
  1899. * @throws SyntaxException missing required parameters
  1900. * @throws BadContentTypeException if no Content-Type was/could be set
  1901. * @throws MisMatchedChecksumException $verify is set and checksums unequal
  1902. * @throws InvalidResponseException unexpected response
  1903. * @throws IOException error opening file
  1904. */
  1905. function load_from_filename($filename, $verify=True)
  1906. {
  1907. $fp = @fopen($filename, "r");
  1908. if (!$fp) {
  1909. throw new IOException("Could not open file for reading: ".$filename);
  1910. }
  1911. clearstatcache();
  1912. $size = (float) sprintf("%u", filesize($filename));
  1913. if ($size > MAX_OBJECT_SIZE) {
  1914. throw new SyntaxException("File size exceeds maximum object size.");
  1915. }
  1916. $this->_guess_content_type($filename);
  1917. $this->write($fp, $size, $verify);
  1918. fclose($fp);
  1919. return True;
  1920. }
  1921. /**
  1922. * Save Object's data to local filename
  1923. *
  1924. * Given a local filename, the Object's data will be written to the newly
  1925. * created file.
  1926. *
  1927. * Example:
  1928. * <code>
  1929. * # ... authentication/connection/container code excluded
  1930. * # ... see previous examples
  1931. *
  1932. * # Whoops! I deleted my local README, let me download/save it
  1933. * #
  1934. * $my_docs = $conn->get_container("documents");
  1935. * $doc = $my_docs->get_object("README");
  1936. *
  1937. * $doc->save_to_filename("/home/ej/cloudfiles/readme.restored");
  1938. * </code>
  1939. *
  1940. * @param string $filename name of local file to write data to
  1941. * @return boolean <kbd>True</kbd> if successful
  1942. * @throws IOException error opening file
  1943. * @throws InvalidResponseException unexpected response
  1944. */
  1945. function save_to_filename($filename)
  1946. {
  1947. $fp = @fopen($filename, "wb");
  1948. if (!$fp) {
  1949. throw new IOException("Could not open file for writing: ".$filename);
  1950. }
  1951. $result = $this->stream($fp);
  1952. fclose($fp);
  1953. return $result;
  1954. }
  1955. /**
  1956. * Set Object's MD5 checksum
  1957. *
  1958. * Manually set the Object's ETag. Including the ETag is mandatory for
  1959. * Cloud Files to perform end-to-end verification. Omitting the ETag forces
  1960. * the user to handle any data integrity checks.
  1961. *
  1962. * @param string $etag MD5 checksum hexidecimal string
  1963. */
  1964. function set_etag($etag)
  1965. {
  1966. $this->etag = $etag;
  1967. $this->_etag_override = True;
  1968. }
  1969. /**
  1970. * Object's MD5 checksum
  1971. *
  1972. * Accessor method for reading Object's private ETag attribute.
  1973. *
  1974. * @return string MD5 checksum hexidecimal string
  1975. */
  1976. function getETag()
  1977. {
  1978. return $this->etag;
  1979. }
  1980. /**
  1981. * Compute the MD5 checksum
  1982. *
  1983. * Calculate the MD5 checksum on either a PHP resource or data. The argument
  1984. * may either be a local filename, open resource for reading, or a string.
  1985. *
  1986. * <b>WARNING:</b> if you are uploading a big file over a stream
  1987. * it could get very slow to compute the md5 you probably want to
  1988. * set the $verify parameter to False in the write() method and
  1989. * compute yourself the md5 before if you have it.
  1990. *
  1991. * @param filename|obj|string $data filename, open resource, or string
  1992. * @return string MD5 checksum hexidecimal string
  1993. */
  1994. function compute_md5sum(&$data)
  1995. {
  1996. if (function_exists("hash_init") && is_resource($data)) {
  1997. $ctx = hash_init('md5');
  1998. while (!feof($data)) {
  1999. $buffer = fgets($data, 65536);
  2000. hash_update($ctx, $buffer);
  2001. }
  2002. $md5 = hash_final($ctx, false);
  2003. rewind($data);
  2004. } elseif ((string)is_file($data)) {
  2005. $md5 = md5_file($data);
  2006. } else {
  2007. $md5 = md5($data);
  2008. }
  2009. return $md5;
  2010. }
  2011. /**
  2012. * PRIVATE: fetch information about the remote Object if it exists
  2013. */
  2014. private function _initialize()
  2015. {
  2016. list($status, $reason, $etag, $last_modified, $content_type,
  2017. $content_length, $metadata) =
  2018. $this->container->cfs_http->head_object($this);
  2019. #if ($status == 401 && $this->_re_auth()) {
  2020. # return $this->_initialize();
  2021. #}
  2022. if ($status == 404) {
  2023. return False;
  2024. }
  2025. if ($status < 200 || $status > 299) {
  2026. throw new InvalidResponseException("Invalid response (".$status."): "
  2027. . $this->container->cfs_http->get_error());
  2028. }
  2029. $this->etag = $etag;
  2030. $this->last_modified = $last_modified;
  2031. $this->content_type = $content_type;
  2032. $this->content_length = $content_length;
  2033. $this->metadata = $metadata;
  2034. return True;
  2035. }
  2036. #private function _re_auth()
  2037. #{
  2038. # $new_auth = new CF_Authentication(
  2039. # $this->cfs_auth->username,
  2040. # $this->cfs_auth->api_key,
  2041. # $this->cfs_auth->auth_host,
  2042. # $this->cfs_auth->account);
  2043. # $new_auth->authenticate();
  2044. # $this->container->cfs_auth = $new_auth;
  2045. # $this->container->cfs_http->setCFAuth($this->cfs_auth);
  2046. # return True;
  2047. #}
  2048. }
  2049. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  2050. /*
  2051. * Local variables:
  2052. * tab-width: 4
  2053. * c-basic-offset: 4
  2054. * c-hanging-comment-ender-p: nil
  2055. * End:
  2056. */
  2057. ?>