getLocalDiskFileStorageRoot(); // Generate a random, unique file path like "ab/29/1f918a9ac39201ff". We // put a couple of subdirectories up front to avoid a situation where we // have one directory with a zillion files in it, since this is generally // bad news. do { $name = md5(mt_rand()); $name = preg_replace('/^(..)(..)(.*)$/', '\\1/\\2/\\3', $name); if (!Filesystem::pathExists($root.'/'.$name)) { break; } } while (true); $parent = $root.'/'.dirname($name); if (!Filesystem::pathExists($parent)) { execx('mkdir -p %s', $parent); } AphrontWriteGuard::willWrite(); Filesystem::writeFile($root.'/'.$name, $data); return $name; } /** * Read the file data off local disk. * @task impl */ public function readFile($handle) { $path = $this->getLocalDiskFileStorageFullPath($handle); return Filesystem::readFile($path); } /** * Deletes the file from local disk, if it exists. * @task impl */ public function deleteFile($handle) { $path = $this->getLocalDiskFileStorageFullPath($handle); if (Filesystem::pathExists($path)) { AphrontWriteGuard::willWrite(); Filesystem::remove($path); } } /* -( Internals )---------------------------------------------------------- */ /** * Get the configured local disk path for file storage. * * @return string Absolute path to somewhere that files can be stored. * @task internal */ private function getLocalDiskFileStorageRoot() { $root = PhabricatorEnv::getEnvConfig('storage.local-disk.path'); if (!$root || $root == '/' || $root[0] != '/') { throw new PhabricatorFileStorageConfigurationException( "Malformed local disk storage root. You must provide an absolute ". "path, and can not use '/' as the root."); } return rtrim($root, '/'); } /** * Convert a handle into an absolute local disk path. * * @param string File data handle. * @return string Absolute path to the corresponding file. * @task internal */ private function getLocalDiskFileStorageFullPath($handle) { // Make sure there's no funny business going on here. Users normally have // no ability to affect the content of handles, but double-check that // we're only accessing local storage just in case. if (!preg_match('@^[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{28}\z@', $handle)) { throw new Exception( "Local disk filesystem handle '{$handle}' is malformed!"); } $root = $this->getLocalDiskFileStorageRoot(); return $root.'/'.$handle; } }