public function updateStream($handle) { if ($this->ctx === null) { $this->ctx = hash_init($this->algo); } hash_update_stream($this->ctx, $handle); return $this; }
/** * @param $resource * * @return string */ public function hash($resource) { rewind($resource); $context = hash_init($this->algo); hash_update_stream($context, $resource); fclose($resource); return hash_final($context); }
public function getFileHash($path) { $stream = $this->filesystem->readStream($path); if ($stream !== false) { $context = hash_init(self::HASH_ALGORITHM); hash_update_stream($context, $stream); return hash_final($context); } return false; }
/** * @param resource $fp The opened file * @param number $offset The offset. * @param number $length Maximum number of characters to copy from * $fp into the hashing context. * @param boolean $raw_output When TRUE, returns the digest in raw * binary format with a length of 16 * * @return string */ public static function md5FromStream($fp, $offset = 0, $length = -1) { $pos = ftell($fp); $ctx = hash_init('md5'); fseek($fp, $offset, SEEK_SET); hash_update_stream($ctx, $fp, $length); if ($pos !== false) { fseek($fp, $pos, SEEK_SET); } return hash_final($ctx, true); }
/** * @param resource $fp The opened file * @param number $offset The offset. * @param number $length Maximum number of characters to copy from * $fp into the hashing context. * @param boolean $raw_output When TRUE, returns the digest in raw * binary format with a length of 16 * * @return string */ static function md5FromStream($fp, $offset = 0, $length = -1, $raw_output = false) { $pos = ftell($fp); $ctx = hash_init('md5'); fseek($fp, $offset, SEEK_SET); hash_update_stream($ctx, $fp, $length); // TODO(leeight) restore ftell value? if ($pos !== false) { fseek($fp, $pos, SEEK_SET); } return hash_final($ctx, $raw_output); }
/** * Returns hash value of given path using supplied hash algorithm * * @param string $path * @param string $algo any algorithm supported by hash() * @return string|bool * @see http://php.net/hash */ public function handle($path, $algo = 'sha256') { if (!in_array($algo, hash_algos())) { throw new \InvalidArgumentException('Hash algorithm ' . $algo . ' is not supported'); } $stream = $this->filesystem->readStream($path); if ($stream === false) { return false; } $hc = hash_init($algo); hash_update_stream($hc, $stream); return hash_final($hc); }
private function serve($path) { $stream = fopen($path, 'rb'); $mtime = gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT'; $stat = fstat($stream); $hash = hash_init('sha1'); hash_update_stream($hash, $stream); hash_update($hash, $mtime); $etag = hash_final($hash); fseek($stream, 0, SEEK_SET); $headers = array('Content-Type', self::getContentType($path), 'Content-Length', $stat['size'], 'Last-Modified', $mtime, 'ETag', $etag); return array(200, $headers, $stream); }
private function serve($path, $req_etag, $req_lastmod) { $stream = fopen($path, 'rb'); $mtime = gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT'; $stat = fstat($stream); $hash = hash_init('sha1'); hash_update_stream($hash, $stream); hash_update($hash, $mtime); $etag = hash_final($hash); if ($req_etag === $etag) { return array(304, array(), ''); } if ($req_lastmod === $mtime) { return array(304, array(), ''); } $headers = array('Content-Type', self::getContentType($path), 'Content-Length', $stat['size'], 'Last-Modified', $mtime, 'ETag', $etag); return array(200, $headers, $stream); }
/** * close file handle * * @param handle $_handle * @return boolean */ public function fclose($_handle) { if (!is_resource($_handle)) { return false; } $options = stream_context_get_options($_handle); switch ($options['tine20']['mode']) { case 'w': case 'wb': case 'x': case 'xb': rewind($_handle); $ctx = hash_init('sha1'); hash_update_stream($ctx, $_handle); $hash = hash_final($ctx); $hashDirectory = $this->_basePath . '/' . substr($hash, 0, 3); if (!file_exists($hashDirectory)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' create hash directory: ' . $hashDirectory); if (mkdir($hashDirectory, 0700) === false) { throw new Tinebase_Exception_UnexpectedValue('failed to create directory'); } } $hashFile = $hashDirectory . '/' . substr($hash, 3); if (!file_exists($hashFile)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' create hash file: ' . $hashFile); rewind($_handle); $hashHandle = fopen($hashFile, 'x'); stream_copy_to_stream($_handle, $hashHandle); fclose($hashHandle); } $this->_updateFileObject($options['tine20']['node']->object_id, $hash, $hashFile); $this->clearStatCache($options['tine20']['path']); break; } fclose($_handle); return true; }
/** * Pump data into an active hashing context * from an open stream. Returns the actual * number of bytes added to the hashing * context from handle. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param resource * @param resource * @param int * @return int */ public function updateStream($context, $handle, $length = -1) { if (!is_resource($context) || !is_resource($handle)) { return false; } return hash_update_stream($context, $handle, $length); }
/** * A quick wrapper for a streamable implementation of md5. * * @param string|resource $source * @return string */ private function md5($source) { $ctx = hash_init('md5'); if (is_resource($source)) { hash_update_stream($ctx, $source); rewind($source); } else { hash_update_file($ctx, $source); } return hash_final($ctx); }
/** * Save an Object into Object Storage. * * This takes an \OpenStack\ObjectStore\v1\Resource\Object * and stores it in the given container in the present * container on the remote object store. * * @param object $obj \OpenStack\ObjectStore\v1\Resource\Object The object to * store. * @param resource $file An optional file argument that, if set, will be * treated as the contents of the object. * * @return boolean true if the object was saved. * * @throws \OpenStack\Common\Transport\Exception\LengthRequiredException if the Content-Length could not be * determined and chunked encoding was * not enabled. This should not occur for * this class, which always automatically * generates Content-Length headers. * However, subclasses could generate * this error. * @throws \OpenStack\Common\Transport\Exception\UnprocessableEntityException if the checksum passed here does not * match the checksum calculated remotely. * @throws \OpenStack\Common\Exception when an unexpected (usually * network-related) error condition arises. */ public function save(Object $obj, $file = null) { if (empty($this->token)) { throw new Exception('Container does not have an auth token.'); } if (empty($this->url)) { throw new Exception('Container does not have a URL to send data.'); } //$url = $this->url . '/' . rawurlencode($obj->name()); $url = self::objectUrl($this->url, $obj->name()); // See if we have any metadata. $headers = []; $md = $obj->metadata(); if (!empty($md)) { $headers = self::generateMetadataHeaders($md, Container::METADATA_HEADER_PREFIX); } // Set the content type. $headers['Content-Type'] = $obj->contentType(); // Add content encoding, if necessary. $encoding = $obj->encoding(); if (!empty($encoding)) { $headers['Content-Encoding'] = rawurlencode($encoding); } // Add content disposition, if necessary. $disposition = $obj->disposition(); if (!empty($disposition)) { $headers['Content-Disposition'] = $disposition; } // Auth token. $headers['X-Auth-Token'] = $this->token; // Add any custom headers: $moreHeaders = $obj->additionalHeaders(); if (!empty($moreHeaders)) { $headers += $moreHeaders; } if (empty($file)) { // Now build up the rest of the headers: $headers['Etag'] = $obj->eTag(); // If chunked, we set transfer encoding; else // we set the content length. if ($obj->isChunked()) { // How do we handle this? Does the underlying // stream wrapper pay any attention to this? $headers['Transfer-Encoding'] = 'chunked'; } else { $headers['Content-Length'] = $obj->contentLength(); } $response = $this->client->put($url, $obj->content(), ['headers' => $headers]); } else { // Rewind the file. rewind($file); // XXX: What do we do about Content-Length header? //$headers['Transfer-Encoding'] = 'chunked'; $stat = fstat($file); $headers['Content-Length'] = $stat['size']; // Generate an eTag: $hash = hash_init('md5'); hash_update_stream($hash, $file); $etag = hash_final($hash); $headers['Etag'] = $etag; // Not sure if this is necessary: rewind($file); $response = $this->client->put($url, $file, ['headers' => $headers]); } if ($response->getStatusCode() != 201) { throw new Exception('An unknown error occurred while saving: ' . $response->status()); } return true; }
/** * places contents into a file blob * * @param stream|string|tempFile $contents * @return string hash */ public function createFileBlob($contents) { if (!is_resource($contents)) { throw new Tinebase_Exception_NotImplemented('please implement me!'); } $handle = $contents; rewind($handle); $ctx = hash_init('sha1'); hash_update_stream($ctx, $handle); $hash = hash_final($ctx); $hashDirectory = $this->_basePath . '/' . substr($hash, 0, 3); if (!file_exists($hashDirectory)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' create hash directory: ' . $hashDirectory); if (mkdir($hashDirectory, 0700) === false) { throw new Tinebase_Exception_UnexpectedValue('failed to create directory'); } } $hashFile = $hashDirectory . '/' . substr($hash, 3); if (!file_exists($hashFile)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' create hash file: ' . $hashFile); rewind($handle); $hashHandle = fopen($hashFile, 'x'); stream_copy_to_stream($handle, $hashHandle); fclose($hashHandle); } return array($hash, $hashFile); }
/** * {@inheritdoc} */ public function getHashOfStream(StreamInterface $stream, $binary = false) { $res = hash_init($this->alg); hash_update_stream($res, $stream->detach()); return hash_final($res); }
/** * Gets SHA1 hash (binary) of a piece of a file. * * @param integer $n_piece 0 bases index of the current peice. * @param integer $size_piece Generic piece size of the file in bytes. * @return string Byte string of the SHA1 hash of this piece. */ protected function hashPiece($n_piece, $size_piece) { $file_handle = $this->getReadHandle(); $hash_handle = hash_init('sha1'); fseek($file_handle, $n_piece * $size_piece); hash_update_stream($hash_handle, $file_handle, $size_piece); // Getting hash of the piece as raw binary. return hash_final($hash_handle, true); }
public function setFileContents($file) { if (is_resource($file)) { $hash_ctx = hash_init('md5'); $length = hash_update_stream($hash_ctx, $file); $md5 = hash_final($hash_ctx, true); rewind($file); curl_setopt($this->curl, CURLOPT_PUT, true); curl_setopt($this->curl, CURLOPT_INFILE, $file); curl_setopt($this->curl, CURLOPT_INFILESIZE, $length); } else { curl_setopt($this->curl, CURLOPT_POSTFIELDS, $file); $md5 = md5($file, true); } $this->headers['Content-MD5'] = base64_encode($md5); return $this; }
/** * see http://php.net/manual/en/function.hash.php * * @param string $type * @param string $path * @param bool $raw * @return string */ public function hash($type, $path, $raw = false) { $fh = $this->fopen($path, 'rb'); $ctx = hash_init($type); hash_update_stream($ctx, $fh); fclose($fh); return hash_final($ctx, $raw); }
/** * @param resource $handle * @param int $length * @return int */ public function updateStream($handle, $length = -1) { $hash = @hash_update_stream($this->context, $handle, $length); if (false === $hash) { throw new HashException(); } return $hash; }
$write_dir($files, $path); break; default: throw new UnexpectedValueException(sprintf('The type "%d" for "%s" in "%s" is not recognized.', $path['type'], $path['path'], __FILE__)); } } }; /** * Checks if the signature is valid. * * @return boolean Returns `true` if it is, `false` if not. */ $is_verified = function () use(&$signature, &$size) { $stream = fopen(__FILE__, 'rb'); $context = hash_init('sha1'); hash_update_stream($context, $stream, $size - 20); fclose($stream); return $signature === hash_final($context, true); }; if (!is_dir($cache)) { if (!$is_verified()) { throw new RuntimeException(sprintf('The signature for "%s" is not valid.', __FILE__)); } mkdir($cache, 0755, true); $extract_database(); $extract_files(); } restore_error_handler(); if (is_file($primary)) { return "require '{$primary}';"; }
/** * Computes more of the hash from a stream. * * @param resource $stream The handle of an open stream. * @param int $maxNumInputBytes **OPTIONAL. Default is** *determine automatically*. The maximum number of bytes * to be processed from the stream. * * @return int The actual number of bytes that were processed from the stream. */ public function computeMoreFromStream($stream, $maxNumInputBytes = null) { assert('is_resource($stream) && (!isset($maxNumInputBytes) || is_int($maxNumInputBytes))', vs(isset($this), get_defined_vars())); if (!isset($maxNumInputBytes)) { return hash_update_stream($this->m_hashingContext, $stream); } else { return hash_update_stream($this->m_hashingContext, $stream, $maxNumInputBytes); } }
/** * Uploads a file to a bucket and returns a File object. * * @param array $options * @return File */ public function upload(array $options) { // Clean the path if it starts with /. if (substr($options['FileName'], 0, 1) === '/') { $options['FileName'] = ltrim($options['FileName'], '/'); } if (!isset($options['BucketId']) && isset($options['BucketName'])) { $options['BucketId'] = $this->getBucketIdFromName($options['BucketName']); } // Retrieve the URL that we should be uploading to. $response = $this->client->request('POST', $this->apiUrl . '/b2_get_upload_url', ['headers' => ['Authorization' => $this->authToken], 'json' => ['bucketId' => $options['BucketId']]]); $uploadEndpoint = $response['uploadUrl']; $uploadAuthToken = $response['authorizationToken']; if (is_resource($options['Body'])) { // We need to calculate the file's hash incrementally from the stream. $context = hash_init('sha1'); hash_update_stream($context, $options['Body']); $hash = hash_final($context); // Similarly, we have to use fstat to get the size of the stream. $size = fstat($options['Body'])['size']; // Rewind the stream before passing it to the HTTP client. rewind($options['Body']); } else { // We've been given a simple string body, it's super simple to calculate the hash and size. $hash = sha1($options['Body']); $size = mb_strlen($options['Body']); } if (!isset($options['FileLastModified'])) { $options['FileLastModified'] = round(microtime(true) * 1000); } if (!isset($options['FileContentType'])) { $options['FileContentType'] = 'b2/x-auto'; } $response = $this->client->request('POST', $uploadEndpoint, ['headers' => ['Authorization' => $uploadAuthToken, 'Content-Type' => $options['FileContentType'], 'Content-Length' => $size, 'X-Bz-File-Name' => $options['FileName'], 'X-Bz-Content-Sha1' => $hash, 'X-Bz-Info-src_last_modified_millis' => $options['FileLastModified']], 'body' => $options['Body']]); return new File($response['fileId'], $response['fileName'], $response['contentSha1'], $response['contentLength'], $response['contentType'], $response['fileInfo']); }
private function readSignature() { fseek($this->fd, -8, SEEK_END); $sig = $this->readFormat("Vflags/Z4magic", $this->fd, 8); $end = ftell($this->fd); if ($sig["magic"] !== "GBMB") { throw new Exception("Invalid signature magic value '{$sig["magic"]}"); } switch ($sig["flags"]) { case self::SIG_OPENSSL: fseek($this->fd, -12, SEEK_END); if ($hash = $this->readSingleFormat("V", $this->fd, 4)) { $offset = 4 + $hash; fseek($this->fd, -$offset, SEEK_CUR); $hash = $this->readVerified($this->fd, $hash); fseek($this->fd, 0, SEEK_SET); $valid = openssl_verify($this->readVerified($this->fd, $end - $offset - 8), $hash, @file_get_contents($this->file . ".pubkey")) === 1; } break; case self::SIG_MD5: case self::SIG_SHA1: case self::SIG_SHA256: case self::SIG_SHA512: $offset = 8 + self::$siglen[$sig["flags"]]; fseek($this->fd, -$offset, SEEK_END); $hash = $this->readVerified($this->fd, self::$siglen[$sig["flags"]]); $algo = hash_init(self::$sigalg[$sig["flags"]]); fseek($this->fd, 0, SEEK_SET); hash_update_stream($algo, $this->fd, $end - $offset); $valid = hash_final($algo, true) === $hash; break; default: throw new Exception("Invalid signature type '{$sig["flags"]}"); } return $sig + compact("hash", "valid"); }
/** * get sha1 hash from stream * * @param resource $stream * @return string str1 hash */ protected function getStreamSHA1($stream) { Util::rewindStream($stream); $context = hash_init('sha1'); hash_update_stream($context, $stream); return hash_final($context); }
/** * The main method to create the content that is at least delivered to the client. * * @return array Returns an array with the keys `header` (array - the header data) and `content` (stream - the stream handle for the generated content of the view handler). */ public function get() { // get the underlying display handler $displayHandler = $this->_getDisplayHandler($this->_handler_name); // overwrite default properties $mimetype_changed = false; if (isset($this->_properties[$this->_handler_name])) { foreach ($this->_properties[$this->_handler_name] as $key => $value) { if (!isset($displayHandler->{$key})) { throw new \Exception(__CLASS__ . ': the property "' . $key . '" does not exist for handler "' . $this->_handler_name . '".'); } $displayHandler->{$key} = $value; if ($key === 'mimetype') { $mimetype_changed = true; } } } // add charset and mimetype to the "page" array $this->_content['page']['charset'] = $displayHandler->charset; $this->_content['page']['mimetype'] = $displayHandler->mimetype; // set standard header lines (those headers will be cached) // set download header if (!empty($displayHandler->downloadable)) { if (!$mimetype_changed) { $displayHandler->mimetype = $this->getMimeType($displayHandler->downloadable); } $this->_header[] = 'Content-Disposition: attachment; filename=' . basename($displayHandler->downloadable); // this is a workaround for ie // see http://support.microsoft.com/kb/316431 $this->_header[] = 'Pragma: protected'; $this->_header[] = 'Cache-control: protected, must-revalidate'; } // set content type $this->_header[] = 'Content-Type: ' . $displayHandler->mimetype . '; charset=' . $displayHandler->charset; // output // create stream handle for the output $handle = fopen('php://temp/maxmemory:' . 1 * 1024 * 1024, 'r+'); // 1MB // get body stream $handle = $displayHandler->getOutput($this->getContent(), $handle); // process Filters if (isset($this->_filters[$this->_handler_name])) { $handle = $this->_processFilters($handle); } // do not compress files bigger than 1 MB to preserve memory and save cpu power $stats = fstat($handle); $size = $stats['size']; if ($size > 1 * 1024 * 1024) { $content = ob_get_clean(); ob_start(); echo $content; } // use etag for content validation (only HTTP1.1) rewind($handle); $hash = hash_init('md5'); hash_update_stream($hash, $handle); $hash = hash_final($hash); // add charset and mimetype to hash // if we change one of those we also want to see the actual view $hash = md5($hash . $displayHandler->charset . $displayHandler->mimetype); if ($this->_cacheetag) { $this->_header[] = 'ETag: ' . $hash; } // HTTP 1.1 $this->_header[] = 'Vary:'; if ($this->_cachetime === null) { // no caching if ($this->_cacheetag) { $this->_header[] = 'Cache-Control: no-cache, must-revalidate'; } else { $this->_header[] = 'Cache-Control: no-store, no-cache, must-revalidate'; } // to overwrite default php setting with "no-store" } else { // caching $fileexpired = strtotime($this->_cachetime); $filemaxage = $fileexpired - time(); // HTTP 1.0 $this->_header[] = 'Pragma: '; $this->_header[] = 'Expires: ' . gmdate("D, d M Y H:i:s", $fileexpired) . " GMT"; // HTTP 1.1 $this->_header[] = 'Cache-Control: public, max-age=' . $filemaxage; } // check for etag if (!isset($_SERVER['HTTP_CACHE_CONTROL']) || !preg_match('/max-age=0|no-cache/i', $_SERVER['HTTP_CACHE_CONTROL'])) { // by-pass "not modified" on explicit reload if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $hash) { $this->_header[] = 'HTTP/1.1 304 Not Modified'; // create empty stream $handle = fopen('php://temp/maxmemory:' . 1 * 1024, 'r+'); // 1kb } } // rewind handle rewind($handle); return array('headers' => $this->_header, 'content' => $handle); }
/** * Calculate a hash of a Stream * * @param string $algo Hash algorithm (e.g. md5, crc32, etc) * @param bool $raw Whether or not to use raw output * @return bool|string Returns false on failure or a hash string on success */ public function getHash($algo = 'sha1', $raw = false) { $result = false; if ($this->isReadable() && $this->isSeekable()) { $current = $this->peek(); if ($this->seek(0) && in_array($algo, hash_algos())) { $hash = hash_init($algo); hash_update_stream($hash, $this->_resource); $result = hash_final($hash, (bool) $raw); $this->seek($current); } } return $result; }
/** * @param array[string]string $arSettings * @param string $RequestMethod * @param string $bucket * @param string $RequestURI * @param string $ContentType * @param array[string]string $additional_headers * @param string $params * @param string|resource $content * @return array[string]string */ function SignRequest($arSettings, $RequestMethod, $bucket, $RequestURI, $ContentType, $additional_headers, $params = "", $content = "") { static $search = array("+", "="); static $replace = array("%20", "%3D"); $CanonicalizedResource = strlen($RequestURI) ? str_replace($search, $replace, $RequestURI) : "/"; $CanonicalQuery = explode("&", ltrim($params, "?")); sort($CanonicalQuery); $CanonicalQueryString = implode("&", $CanonicalQuery); $CanonicalHeaders = array(); foreach ($additional_headers as $key => $value) { $key = strtolower($key); if (isset($CanonicalHeaders[$key])) { $CanonicalHeaders[$key] .= ","; } else { $CanonicalHeaders[$key] = $key . ":"; } $CanonicalHeaders[$key] .= trim($value, " \t\n\r"); } ksort($CanonicalHeaders); $CanonicalHeadersString = implode("\n", $CanonicalHeaders); $SignedHeaders = implode(";", array_keys($CanonicalHeaders)); if (is_resource($content)) { $streamPosition = ftell($content); $hashResource = hash_init("sha256"); hash_update_stream($hashResource, $content); $HashedPayload = hash_final($hashResource); fseek($content, $streamPosition); } else { $HashedPayload = hash("sha256", $content, false); } $CanonicalRequest = ""; $CanonicalRequest .= $RequestMethod . "\n"; $CanonicalRequest .= $CanonicalizedResource . "\n"; $CanonicalRequest .= $CanonicalQueryString . "\n"; $CanonicalRequest .= $CanonicalHeadersString . "\n\n"; $CanonicalRequest .= $SignedHeaders . "\n"; $CanonicalRequest .= $HashedPayload; $Algorithm = "AWS4-HMAC-SHA256"; $Time = time(); $RequestDate = gmdate('Ymd', $Time); $RequestTime = gmdate('D, d M Y H:i:s', $Time) . ' GMT'; $Region = $this->location ? $this->location : 'us-east-1'; $Service = "s3"; $Scope = $RequestDate . "/" . $Region . "/" . $Service . "/aws4_request"; $StringToSign = ""; $StringToSign .= $Algorithm . "\n"; $StringToSign .= $RequestTime . "\n"; $StringToSign .= $Scope . "\n"; $StringToSign .= hash("sha256", $CanonicalRequest, false); $kSecret = $arSettings["SECRET_KEY"]; $kDate = hash_hmac("sha256", $RequestDate, "AWS4" . $kSecret, true); $kRegion = hash_hmac("sha256", $Region, $kDate, true); $kService = hash_hmac("sha256", $Service, $kRegion, true); $kSigning = hash_hmac("sha256", "aws4_request", $kService, true); $Signature = hash_hmac("sha256", $StringToSign, $kSigning, false); $Authorization = "{$Algorithm} Credential={$arSettings['ACCESS_KEY']}/{$Scope}, SignedHeaders={$SignedHeaders}, Signature={$Signature}"; return array("Date" => gmdate('D, d M Y H:i:s', $Time) . ' GMT', "Authorization" => $Authorization, "x-amz-content-sha256" => $HashedPayload); }
/** * @param AJXP_Node $node * @param float $offset * @param float $length * @return String md5 */ public function getPartialHash($node, $offset, $length) { $this->logDebug('Getting partial hash from ' . $offset . ' to ' . $length); $fp = fopen($node->getUrl(), "r"); $ctx = hash_init('md5'); if ($offset > 0) { fseek($fp, $offset); } hash_update_stream($ctx, $fp, $length); $hash = hash_final($ctx); $this->logDebug('Partial hash is ' . $hash); fclose($fp); return $hash; }
/** * @param resource $stream * * @throws RuntimeException */ public function pushStream($stream) { $result = hash_update_stream($this->getHandle(), $stream); if (!$result) { throw new RuntimeException(); } }