Changeset View
Changeset View
Standalone View
Standalone View
src/applications/files/storage/PhabricatorFile.php
Show First 20 Lines • Show All 691 Lines • ▼ Show 20 Lines | final class PhabricatorFile extends PhabricatorFileDAO | ||||
public function getViewURI() { | public function getViewURI() { | ||||
if (!$this->getPHID()) { | if (!$this->getPHID()) { | ||||
throw new Exception( | throw new Exception( | ||||
pht('You must save a file before you can generate a view URI.')); | pht('You must save a file before you can generate a view URI.')); | ||||
} | } | ||||
return $this->getCDNURI(null); | return $this->getCDNURI(); | ||||
} | } | ||||
private function getCDNURI($token) { | public function getCDNURI() { | ||||
$name = self::normalizeFileName($this->getName()); | $name = self::normalizeFileName($this->getName()); | ||||
$name = phutil_escape_uri($name); | $name = phutil_escape_uri($name); | ||||
$parts = array(); | $parts = array(); | ||||
$parts[] = 'file'; | $parts[] = 'file'; | ||||
$parts[] = 'data'; | $parts[] = 'data'; | ||||
// If this is an instanced install, add the instance identifier to the URI. | // If this is an instanced install, add the instance identifier to the URI. | ||||
// Instanced configurations behind a CDN may not be able to control the | // Instanced configurations behind a CDN may not be able to control the | ||||
// request domain used by the CDN (as with AWS CloudFront). Embedding the | // request domain used by the CDN (as with AWS CloudFront). Embedding the | ||||
// instance identity in the path allows us to distinguish between requests | // instance identity in the path allows us to distinguish between requests | ||||
// originating from different instances but served through the same CDN. | // originating from different instances but served through the same CDN. | ||||
$instance = PhabricatorEnv::getEnvConfig('cluster.instance'); | $instance = PhabricatorEnv::getEnvConfig('cluster.instance'); | ||||
if (strlen($instance)) { | if (strlen($instance)) { | ||||
$parts[] = '@'.$instance; | $parts[] = '@'.$instance; | ||||
} | } | ||||
$parts[] = $this->getSecretKey(); | $parts[] = $this->getSecretKey(); | ||||
$parts[] = $this->getPHID(); | $parts[] = $this->getPHID(); | ||||
if ($token) { | |||||
$parts[] = $token; | |||||
} | |||||
$parts[] = $name; | $parts[] = $name; | ||||
$path = '/'.implode('/', $parts); | $path = '/'.implode('/', $parts); | ||||
// If this file is only partially uploaded, we're just going to return a | // If this file is only partially uploaded, we're just going to return a | ||||
// local URI to make sure that Ajax works, since the page is inevitably | // local URI to make sure that Ajax works, since the page is inevitably | ||||
// going to give us an error back. | // going to give us an error back. | ||||
if ($this->getIsPartial()) { | if ($this->getIsPartial()) { | ||||
return PhabricatorEnv::getURI($path); | return PhabricatorEnv::getURI($path); | ||||
} else { | } else { | ||||
return PhabricatorEnv::getCDNURI($path); | return PhabricatorEnv::getCDNURI($path); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Get the CDN URI for this file, including a one-time-use security token. | |||||
* | |||||
*/ | |||||
public function getCDNURIWithToken() { | |||||
if (!$this->getPHID()) { | |||||
throw new Exception( | |||||
pht('You must save a file before you can generate a CDN URI.')); | |||||
} | |||||
return $this->getCDNURI($this->generateOneTimeToken()); | |||||
} | |||||
public function getInfoURI() { | public function getInfoURI() { | ||||
return '/'.$this->getMonogram(); | return '/'.$this->getMonogram(); | ||||
} | } | ||||
public function getBestURI() { | public function getBestURI() { | ||||
if ($this->isViewableInBrowser()) { | if ($this->isViewableInBrowser()) { | ||||
return $this->getViewURI(); | return $this->getViewURI(); | ||||
▲ Show 20 Lines • Show All 354 Lines • ▼ Show 20 Lines | public function getIsProfileImage() { | ||||
return idx($this->metadata, self::METADATA_PROFILE); | return idx($this->metadata, self::METADATA_PROFILE); | ||||
} | } | ||||
public function setIsProfileImage($value) { | public function setIsProfileImage($value) { | ||||
$this->metadata[self::METADATA_PROFILE] = $value; | $this->metadata[self::METADATA_PROFILE] = $value; | ||||
return $this; | return $this; | ||||
} | } | ||||
protected function generateOneTimeToken() { | |||||
$key = Filesystem::readRandomCharacters(16); | |||||
$token_type = PhabricatorFileAccessTemporaryTokenType::TOKENTYPE; | |||||
// Save the new secret. | |||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||||
$token = id(new PhabricatorAuthTemporaryToken()) | |||||
->setTokenResource($this->getPHID()) | |||||
->setTokenType($token_type) | |||||
->setTokenExpires(time() + phutil_units('1 hour in seconds')) | |||||
->setTokenCode(PhabricatorHash::digest($key)) | |||||
->save(); | |||||
unset($unguarded); | |||||
return $key; | |||||
} | |||||
public function validateOneTimeToken($token_code) { | |||||
$token_type = PhabricatorFileAccessTemporaryTokenType::TOKENTYPE; | |||||
$token = id(new PhabricatorAuthTemporaryTokenQuery()) | |||||
->setViewer(PhabricatorUser::getOmnipotentUser()) | |||||
->withTokenResources(array($this->getPHID())) | |||||
->withTokenTypes(array($token_type)) | |||||
->withExpired(false) | |||||
->withTokenCodes(array(PhabricatorHash::digest($token_code))) | |||||
->executeOne(); | |||||
return $token; | |||||
} | |||||
/** | /** | ||||
* Write the policy edge between this file and some object. | * Write the policy edge between this file and some object. | ||||
* | * | ||||
* @param phid Object PHID to attach to. | * @param phid Object PHID to attach to. | ||||
* @return this | * @return this | ||||
*/ | */ | ||||
public function attachToObject($phid) { | public function attachToObject($phid) { | ||||
$edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST; | $edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST; | ||||
▲ Show 20 Lines • Show All 217 Lines • Show Last 20 Lines |