/** * Get by key * * @param $key * @param array $options * @return bool|string * @throws Exception\ItemNotFoundException|Exception\UnexpectedValueException */ protected function internalGetItem($key, array &$options) { if (!$this->internalHasItem($key, $options) || !($keyInfo = $this->getKeyInfo($key, $options['namespace']))) { if ($options['ignore_missing_items']) { return false; } else { throw new Exception\ItemNotFoundException("Key '{$key}' not found within namespace '{$options['namespace']}'"); } } $baseOptions = $this->getOptions(); try { $data = $this->getFileContent($keyInfo['filespec'] . '.dat'); if ($baseOptions->getReadControl()) { if (($info = $this->readInfoFile($keyInfo['filespec'] . '.ifo')) && isset($info['hash'], $info['algo']) && Utils::generateHash($info['algo'], $data, true) != $info['hash']) { throw new Exception\UnexpectedValueException("ReadControl: Stored hash and computed hash don't match"); } } return $data; } catch (Exception $e) { try { // remove cache file on exception $this->internalRemoveItem($key, $options); } catch (Exception $tmp) { } // do not throw remove exception on this point throw $e; } }
/** * Internal method to store multiple items. * * Options: * - namespace <string> * - The namespace to use * - tags <array> * - An array of tags * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ protected function internalSetItems(array &$normalizedKeyValuePairs, array &$normalizedOptions) { $baseOptions = $this->getOptions(); $oldUmask = null; // create an associated array of files and contents to write $contents = array(); foreach ($normalizedKeyValuePairs as $key => &$value) { $filespec = $this->getFileSpec($key, $normalizedOptions); // init directory level if ($baseOptions->getDirLevel() > 0) { $path = dirname($filespec); if (!file_exists($path)) { $oldUmask = $oldUmask === null ? umask($baseOptions->getDirUmask()) : $oldUmask; ErrorHandler::start(); $mkdir = mkdir($path, 0777, true); $error = ErrorHandler::stop(); if (!$mkdir) { umask($oldUmask); throw new Exception\RuntimeException("Error creating directory '{$path}'", 0, $error); } } } // *.dat file $contents[$filespec . '.dat'] =& $value; // *.ifo file $info = null; if ($baseOptions->getReadControl()) { $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); $info['algo'] = $baseOptions->getReadControlAlgo(); } if (isset($normalizedOptions['tags'])) { $info['tags'] =& $normalizedOptions['tags']; } if ($info) { $contents[$filespec . '.ifo'] = serialize($info); } else { $this->unlink($filespec . '.ifo'); } } // write to disk try { // set umask for files if ($oldUmask !== null) { // $oldUmask could be defined on create directory umask($baseOptions->getFileUmask()); } else { $oldUmask = umask($baseOptions->getFileUmask()); } while ($contents) { $nonBlocking = count($contents) > 1; $wouldblock = null; foreach ($contents as $file => &$content) { $this->putFileContent($file, $content, $nonBlocking, $wouldblock); if (!$nonBlocking || !$wouldblock) { unset($contents[$file]); } } } // reset umask umask($oldUmask); return true; } catch (Exception $e) { // reset umask on exception umask($oldUmask); throw $e; } }
/** * Internal method to store multiple items. * * @param array $normalizedKeyValuePairs * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array &$normalizedKeyValuePairs) { $baseOptions = $this->getOptions(); $oldUmask = null; // create an associated array of files and contents to write $contents = array(); foreach ($normalizedKeyValuePairs as $key => &$value) { $filespec = $this->getFileSpec($key); $this->prepareDirectoryStructure($filespec); // *.dat file $contents[$filespec . '.dat'] =& $value; // *.ifo file $info = null; if ($baseOptions->getReadControl()) { $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); $info['algo'] = $baseOptions->getReadControlAlgo(); } if ($info) { $contents[$filespec . '.ifo'] = serialize($info); } else { $this->unlink($filespec . '.ifo'); $this->unlink($filespec . '.tag'); } } // write to disk try { // set umask for files $oldUmask = umask($baseOptions->getFileUmask()); while ($contents) { $nonBlocking = count($contents) > 1; $wouldblock = null; foreach ($contents as $file => &$content) { $this->putFileContent($file, $content, $nonBlocking, $wouldblock); if (!$nonBlocking || !$wouldblock) { unset($contents[$file]); } } } // reset umask umask($oldUmask); // return OK return array(); } catch (BaseException $e) { // reset umask on exception umask($oldUmask); throw $e; } }
public function testGenerateHashStrlenRaw() { $this->assertEquals(pack('l', strlen('test')), Utils::generateHash('strlen', 'test', true)); }
/** * Internal method to store an item. * * Options: * - namespace <string> * - The namespace to use * - tags <array> * - An array of tags * * @param string $normalizedKey * @param mixed $value * @param array $normalizedOptions * @return boolean * @throws Exception */ protected function internalSetItem(&$normalizedKey, &$value, array &$normalizedOptions) { $baseOptions = $this->getOptions(); $oldUmask = null; $lastInfoId = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() . $normalizedKey; if ($this->lastInfoId == $lastInfoId) { $filespec = $this->lastInfo['filespec']; // if lastKeyInfo is available I'm sure that the cache directory exist } else { $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions['namespace']); if ($baseOptions->getDirLevel() > 0) { $path = dirname($filespec); if (!file_exists($path)) { $oldUmask = umask($baseOptions->getDirUmask()); ErrorHandler::start(); $mkdir = mkdir($path, 0777, true); $error = ErrorHandler::stop(); if (!$mkdir) { throw new Exception\RuntimeException("Error creating directory '{$path}'", 0, $error); } } } } $info = null; if ($baseOptions->getReadControl()) { $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); $info['algo'] = $baseOptions->getReadControlAlgo(); } if (isset($options['tags']) && $normalizedOptions['tags']) { $tags = $normalizedOptions['tags']; if (!is_array($tags)) { $tags = array($tags); } $info['tags'] = array_values(array_unique($tags)); } try { if ($oldUmask !== null) { // $oldUmask could be defined on set directory_umask umask($baseOptions->getFileUmask()); } else { $oldUmask = umask($baseOptions->getFileUmask()); } $ret = $this->putFileContent($filespec . '.dat', $value); if ($ret && $info) { // Don't throw exception if writing of info file failed // -> only return false try { $ret = $this->putFileContent($filespec . '.ifo', serialize($info)); } catch (Exception\RuntimeException $e) { $ret = false; } } $this->lastInfoId = null; // reset file_umask umask($oldUmask); return $ret; } catch (Exception $e) { // reset umask on exception umask($oldUmask); throw $e; } }