Page MenuHomePhabricator

D16581.id39908.diff
No OneTemporary

D16581.id39908.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2557,6 +2557,7 @@
'PhabricatorFileHasObjectEdgeType' => 'applications/files/edge/PhabricatorFileHasObjectEdgeType.php',
'PhabricatorFileIconSetSelectController' => 'applications/files/controller/PhabricatorFileIconSetSelectController.php',
'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php',
+ 'PhabricatorFileImageProxyController' => 'applications/files/controller/PhabricatorFileImageProxyController.php',
'PhabricatorFileImageTransform' => 'applications/files/transform/PhabricatorFileImageTransform.php',
'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php',
'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php',
@@ -7379,6 +7380,7 @@
'PhabricatorTokenReceiverInterface',
'PhabricatorPolicyInterface',
),
+ 'PhabricatorFileImageProxyController' => 'PhabricatorFileController',
'PhabricatorFileImageTransform' => 'PhabricatorFileTransform',
'PhabricatorFileInfoController' => 'PhabricatorFileController',
'PhabricatorFileLinkView' => 'AphrontView',
diff --git a/src/applications/files/application/PhabricatorFilesApplication.php b/src/applications/files/application/PhabricatorFilesApplication.php
--- a/src/applications/files/application/PhabricatorFilesApplication.php
+++ b/src/applications/files/application/PhabricatorFilesApplication.php
@@ -78,7 +78,7 @@
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController',
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorFileEditController',
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
- 'proxy/' => 'PhabricatorFileProxyController',
+ 'imageproxy/' => 'PhabricatorFileImageProxyController',
'transforms/(?P<id>[1-9]\d*)/' =>
'PhabricatorFileTransformListController',
'uploaddialog/(?P<single>single/)?'
diff --git a/src/applications/files/controller/PhabricatorFileImageProxyController.php b/src/applications/files/controller/PhabricatorFileImageProxyController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/controller/PhabricatorFileImageProxyController.php
@@ -0,0 +1,93 @@
+<?php
+
+final class PhabricatorFileImageProxyController
+ extends PhabricatorFileController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+
+ $show_prototypes = PhabricatorEnv::getEnvConfig(
+ 'phabricator.show-prototypes');
+ if (!$show_prototypes) {
+ throw new Exception(
+ pht('Show prototypes is disabled.
+ Set `phabricator.show-prototypes` to `true` to use the image proxy'));
+ }
+
+ $img_uri = $request->getStr('uri');
+
+ // Check if we already have the specified image URI downloaded
+ $cache = new PhabricatorKeyValueDatabaseCache();
+ $cache = new PhutilKeyValueCacheProfiler($cache);
+ $cache->setProfiler(PhutilServiceProfiler::getInstance());
+ $cache_key = 'file.imageproxy:'.$img_uri;
+ $result = $cache->getKey($cache_key);
+ if ($result) {
+ return id(new AphrontRedirectResponse())
+ ->setIsExternal(true)
+ ->setURI($result);
+ }
+
+ // Cache missed so we'll need to validate and download the image
+ PhabricatorEnv::requireValidRemoteURIForLink($img_uri);
+ $uri = new PhutilURI($img_uri);
+ $proto = $uri->getProtocol();
+ if (!in_array($proto, array('http', 'https'))) {
+ throw new Exception(
+ pht('The provided image URI must be either http or https'));
+ }
+
+ $viewer = $request->getViewer();
+ try {
+ // Rate limit outbound fetches to make this mechanism less useful for
+ // scanning networks and ports.
+ PhabricatorSystemActionEngine::willTakeAction(
+ array($viewer->getPHID()),
+ new PhabricatorFilesOutboundRequestAction(),
+ 1);
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $file = PhabricatorFile::newFromFileDownload(
+ $uri,
+ array(
+ 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
+ 'canCDN' => true,
+ ));
+ if (!$file->isViewableInBrowser()) {
+ $mime_type = $file->getMimeType();
+ $engine = new PhabricatorDestructionEngine();
+ $engine->destroyObject($file);
+ $file = null;
+ throw new Exception(
+ pht(
+ 'The URI "%s" does not correspond to a valid image file, got '.
+ 'a file with MIME type "%s". You must specify the URI of a '.
+ 'valid image file.',
+ $uri,
+ $mime_type));
+ } else {
+ $file
+ ->setAuthorPHID($viewer->getPHID())
+ ->save();
+ }
+ unset($unguarded);
+ $cache->setKey($cache_key, $file->getViewURI());
+ return id(new AphrontRedirectResponse())
+ ->setIsExternal(true)
+ ->setURI($file->getViewURI());
+ } catch (HTTPFutureHTTPResponseStatus $status) {
+ throw new Exception(pht(
+ 'The URI "%s" could not be loaded, got %s error.',
+ $uri,
+ $status->getStatusCode()));
+ } catch (Exception $ex) {
+ throw new Exception(pht(
+ "The URI '%s' could not be loaded due to the following error:\n %s",
+ $uri,
+ $ex->getMessage()));
+ }
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 21, 4:42 AM (1 d, 3 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7714980
Default Alt Text
D16581.id39908.diff (5 KB)

Event Timeline