mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-22 19:49:02 +01:00
Always serve "{meme ...}" from the CDN domain, never from the primary domain
Summary: Ref T13101. This is a minimal change to make "{meme ...}" work with the new Content-Security-Policy by using an Ajax request to generate the image and then swapping the source on the client. This could be much cleaner (see T5258, etc). Test Plan: Used `{meme, src=cat6, above=i am, below=cat}`, chuckled completely unironically. Maniphest Tasks: T13101 Differential Revision: https://secure.phabricator.com/D19196
This commit is contained in:
parent
6095d88998
commit
98cac2cc29
3 changed files with 99 additions and 42 deletions
|
@ -13,18 +13,25 @@ final class PhabricatorMacroMemeController
|
||||||
$lower_text = $request->getStr('lowertext');
|
$lower_text = $request->getStr('lowertext');
|
||||||
$viewer = $request->getViewer();
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
$uri = self::generateMacro($viewer, $macro_name,
|
$uri = self::generateMacro(
|
||||||
$upper_text, $lower_text);
|
$viewer,
|
||||||
if ($uri === false) {
|
$macro_name,
|
||||||
return new Aphront404Response();
|
$upper_text,
|
||||||
}
|
$lower_text);
|
||||||
return id(new AphrontRedirectResponse())
|
|
||||||
->setIsExternal(true)
|
$content = array(
|
||||||
->setURI($uri);
|
'imageURI' => $uri,
|
||||||
|
);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())->setContent($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function generateMacro($viewer, $macro_name, $upper_text,
|
public static function generateMacro(
|
||||||
$lower_text) {
|
PhabricatorUser $viewer,
|
||||||
|
$macro_name,
|
||||||
|
$upper_text,
|
||||||
|
$lower_text) {
|
||||||
|
|
||||||
$macro = id(new PhabricatorMacroQuery())
|
$macro = id(new PhabricatorMacroQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withNames(array($macro_name))
|
->withNames(array($macro_name))
|
||||||
|
@ -35,34 +42,75 @@ final class PhabricatorMacroMemeController
|
||||||
}
|
}
|
||||||
$file = $macro->getFile();
|
$file = $macro->getFile();
|
||||||
|
|
||||||
$upper_text = strtoupper($upper_text);
|
$upper_text = phutil_utf8_strtoupper($upper_text);
|
||||||
$lower_text = strtoupper($lower_text);
|
$lower_text = phutil_utf8_strtoupper($lower_text);
|
||||||
$mixed_text = md5($upper_text).':'.md5($lower_text);
|
|
||||||
$hash = 'meme'.hash('sha256', $mixed_text);
|
|
||||||
$xform = id(new PhabricatorTransformedFile())
|
|
||||||
->loadOneWhere('originalphid=%s and transform=%s',
|
|
||||||
$file->getPHID(), $hash);
|
|
||||||
|
|
||||||
if ($xform) {
|
$hash = PhabricatorHash::digestForIndex(
|
||||||
$memefile = id(new PhabricatorFileQuery())
|
phutil_json_encode(
|
||||||
->setViewer($viewer)
|
array(
|
||||||
->withPHIDs(array($xform->getTransformedPHID()))
|
'kind' => 'meme',
|
||||||
->executeOne();
|
'upper' => $upper_text,
|
||||||
if ($memefile) {
|
'lower' => $lower_text,
|
||||||
return $memefile->getBestURI();
|
)));
|
||||||
}
|
|
||||||
|
$xfile = self::loadTransformedFile($viewer, $file->getPHID(), $hash);
|
||||||
|
if ($xfile) {
|
||||||
|
return $xfile->getViewURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
$transformer = new PhabricatorImageTransformer();
|
||||||
$transformers = (new PhabricatorImageTransformer());
|
|
||||||
$newfile = $transformers
|
|
||||||
->executeMemeTransform($file, $upper_text, $lower_text);
|
|
||||||
$xfile = new PhabricatorTransformedFile();
|
|
||||||
$xfile->setOriginalPHID($file->getPHID());
|
|
||||||
$xfile->setTransformedPHID($newfile->getPHID());
|
|
||||||
$xfile->setTransform($hash);
|
|
||||||
$xfile->save();
|
|
||||||
|
|
||||||
return $newfile->getBestURI();
|
$new_file = $transformer->executeMemeTransform(
|
||||||
|
$file,
|
||||||
|
$upper_text,
|
||||||
|
$lower_text);
|
||||||
|
|
||||||
|
$xfile = id(new PhabricatorTransformedFile())
|
||||||
|
->setOriginalPHID($file->getPHID())
|
||||||
|
->setTransformedPHID($new_file->getPHID())
|
||||||
|
->setTransform($hash);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$caught = null;
|
||||||
|
|
||||||
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
|
try {
|
||||||
|
$xfile->save();
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$caught = $ex;
|
||||||
|
}
|
||||||
|
unset($unguarded);
|
||||||
|
|
||||||
|
if ($caught) {
|
||||||
|
throw $caught;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $new_file->getViewURI();
|
||||||
|
} catch (AphrontDuplicateKeyQueryException $ex) {
|
||||||
|
$xfile = self::loadTransformedFile($viewer, $file->getPHID(), $hash);
|
||||||
|
if (!$xfile) {
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
return $xfile->getViewURI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function loadTransformedFile(
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
$file_phid,
|
||||||
|
$hash) {
|
||||||
|
|
||||||
|
$xform = id(new PhabricatorTransformedFile())->loadOneWhere(
|
||||||
|
'originalPHID = %s AND transform = %s',
|
||||||
|
$file_phid,
|
||||||
|
$hash);
|
||||||
|
if (!$xform) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PhabricatorFileQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(array($xform->getTransformedPHID()))
|
||||||
|
->executeOne();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,13 +50,10 @@ final class PhabricatorMemeRemarkupRule extends PhutilRemarkupRule {
|
||||||
$options['above'],
|
$options['above'],
|
||||||
$options['below']);
|
$options['below']);
|
||||||
|
|
||||||
$img = $this->newTag(
|
$img = id(new PHUIRemarkupImageView())
|
||||||
'img',
|
->setURI($uri)
|
||||||
array(
|
->addClass('phabricator-remarkup-macro')
|
||||||
'src' => $uri,
|
->setAlt($alt_text);
|
||||||
'alt' => $alt_text,
|
|
||||||
'class' => 'phabricator-remarkup-macro',
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getEngine()->storeText($img);
|
return $this->getEngine()->storeText($img);
|
||||||
|
|
|
@ -7,6 +7,7 @@ final class PHUIRemarkupImageView
|
||||||
private $width;
|
private $width;
|
||||||
private $height;
|
private $height;
|
||||||
private $alt;
|
private $alt;
|
||||||
|
private $classes = array();
|
||||||
|
|
||||||
public function setURI($uri) {
|
public function setURI($uri) {
|
||||||
$this->uri = $uri;
|
$this->uri = $uri;
|
||||||
|
@ -44,6 +45,11 @@ final class PHUIRemarkupImageView
|
||||||
return $this->alt;
|
return $this->alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addClass($class) {
|
||||||
|
$this->classes[] = $class;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
$id = celerity_generate_unique_node_id();
|
$id = celerity_generate_unique_node_id();
|
||||||
|
|
||||||
|
@ -54,6 +60,11 @@ final class PHUIRemarkupImageView
|
||||||
'imageID' => $id,
|
'imageID' => $id,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$classes = null;
|
||||||
|
if ($this->classes) {
|
||||||
|
$classes = implode(' ', $this->classes);
|
||||||
|
}
|
||||||
|
|
||||||
return phutil_tag(
|
return phutil_tag(
|
||||||
'img',
|
'img',
|
||||||
array(
|
array(
|
||||||
|
@ -61,6 +72,7 @@ final class PHUIRemarkupImageView
|
||||||
'width' => $this->getWidth(),
|
'width' => $this->getWidth(),
|
||||||
'height' => $this->getHeight(),
|
'height' => $this->getHeight(),
|
||||||
'alt' => $this->getAlt(),
|
'alt' => $this->getAlt(),
|
||||||
|
'class' => $classes,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue