Added default MD5 checksums to RemoteObject.

This commit is contained in:
Matt Butcher
2012-01-09 11:13:54 -06:00
parent bcf1a77c90
commit bcb6afc57f
3 changed files with 87 additions and 17 deletions

View File

@@ -0,0 +1,17 @@
<?php
/**
* @file
*
* Contains the ContentVerificationException object.
*/
namespace HPCloud\Storage\ObjectStorage;
/**
* Content Verification error condition.
*
* This occurs when the server sends content whose value does
* not match the supplied checksum. See
* RemoteObject::setContentVerification().
*
*/
class ContentVerificationException extends \HPCloud\Exception {}

View File

@@ -13,6 +13,8 @@ class RemoteObject extends Object {
protected $etag = '';
protected $lastModified = 0;
protected $contentVerification = TRUE;
/**
* Create a new RemoteObject from JSON data.
*
@@ -144,6 +146,15 @@ class RemoteObject extends Object {
* object to be fetched from the remote data storage. The result will
* be delivered as one large string.
*
* The file size, content type, etag, and modification date of the
* object are all updated during this command, too. This accounts for
* the possibility that the content was modified externally between
* the time this object was constructed and the time this method was
* executed.
*
* The RemoteObject does NOT cache content. Each call to content()
* will initiate a new network request.
*
* Be wary of using this method with large files.
*
* @return string
@@ -165,7 +176,56 @@ class RemoteObject extends Object {
// Get the object, content included.
$response = $this->fetchObject(TRUE);
return $response->content();
$content = $response->content();
$check = md5($content);
if ($check != $this->etag()) {
throw new ContentVerificationException("Checksum $check does not match Etag " . $this->etag());
}
return $content;
}
/**
* Enable or disable content verification (checksum/md5).
*
* The default behavior of a RemoteObject is to verify that the MD5
* provided by the server matches the locally generated MD5 of the
* file contents.
*
* If content verification is enabled, then whenever the content is
* fetched from the remote server, its checksum is calculated and
* tested against the ETag value. This provides a layer of assurance
* that the payload of the HTTP request was not altered during
* transmission.
*
* This featured can be turned off, which is sometimes necessary on
* systems that do not correctly produce MD5s. Turning this off might
* also provide a small performance improvement on large files, but at
* the expense of security.
*
* @param boolean $enabled
* If this is TRUE, content verification is performed. The content
* is hashed and checked against a server-supplied MD5 hashcode. If
* this is FALSE, no checking is done.
*/
public function setContentVerification($enabled) {
$this->contentVerification = $enabled;
}
/**
* Indicate whether this object verifies content (checksum).
*
* When content verification is on, RemoteObject attemts to perform a
* checksum on the object, calculating the MD5 hash of the content
* returned by the remote server, and comparing that to the server's
* supplied ETag hash.
*
* @return boolean
* TRUE if this is verifying, FALSE otherwise.
*/
public function isVerifyingContent() {
return $this->contentVerification;
}
/**
@@ -213,17 +273,4 @@ class RemoteObject extends Object {
return $response;
}
/*
public function setContent($content, $type = NULL) {
throw new ReadOnlyObjectException(__CLASS__ . ' is read-only.');
}
public function setContentType($type) {
throw new ReadOnlyObjectException(__CLASS__ . ' is read-only.');
}
public function setMetadata(array $array) {
throw new ReadOnlyObjectException(__CLASS__ . ' is read-only.');
}
*/
}

View File

@@ -145,12 +145,18 @@ class ContainerTest extends \HPCloud\Tests\TestCase {
$this->assertEquals('1234', $md['Foo']);
$content = $object->content();
$this->assertEquals(self::FCONTENT, $content);
// Make sure I can do this twice (regression).
// Note that this SHOULD perform another request.
$this->assertEquals(self::FCONTENT, $object->content());
// Overwrite the copy:
$object->setContent('HI');
$this->assertEquals('HI', $object->content());
// Make sure I can do this twice (regression check).
$this->assertEquals('HI', $object->content());
}
/**