@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add flat text assertions to Phabricator remarkup rules

Summary: Remarkup rules can not safely use arbitrary text in tag attributes,
because it may include tokens which are later replaced. Precedence rules
should prevent this in general. Use flat text assertions and adjust precedence
rules in cases where they may not prevent tokens from appearing in attributes.

Auditors: btrahan

+61 -45
+22 -22
resources/celerity/map.php
··· 8 8 'names' => 9 9 array( 10 10 'core.pkg.css' => 'c2c68e64', 11 - 'core.pkg.js' => '834b4eda', 11 + 'core.pkg.js' => 'f8ec7ddc', 12 12 'darkconsole.pkg.js' => 'df001cab', 13 13 'differential.pkg.css' => '4a93db37', 14 - 'differential.pkg.js' => 'd1443567', 14 + 'differential.pkg.js' => '7528cfc9', 15 15 'diffusion.pkg.css' => '471bc9eb', 16 16 'diffusion.pkg.js' => 'bfc0737b', 17 17 'maniphest.pkg.css' => 'f5d89daf', ··· 362 362 'rsrc/js/application/differential/ChangesetViewManager.js' => 'd2907473', 363 363 'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => 'f2441746', 364 364 'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18', 365 - 'rsrc/js/application/differential/behavior-comment-jump.js' => '2bc7a5e0', 365 + 'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d', 366 366 'rsrc/js/application/differential/behavior-comment-preview.js' => '127f2018', 367 367 'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1', 368 368 'rsrc/js/application/differential/behavior-dropdown-menus.js' => '710f209e', ··· 473 473 'rsrc/js/core/behavior-object-selector.js' => '39841ead', 474 474 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 475 475 'rsrc/js/core/behavior-phabricator-nav.js' => '14d7a8b8', 476 - 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'eff6a142', 476 + 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'e32d14ab', 477 477 'rsrc/js/core/behavior-refresh-csrf.js' => '7814b593', 478 478 'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45', 479 479 'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e', ··· 567 567 'javelin-behavior-dashboard-tab-panel' => 'd4eecc63', 568 568 'javelin-behavior-device' => '03d6ed07', 569 569 'javelin-behavior-differential-add-reviewers-and-ccs' => 'e10f8e18', 570 - 'javelin-behavior-differential-comment-jump' => '2bc7a5e0', 570 + 'javelin-behavior-differential-comment-jump' => '4fdb476d', 571 571 'javelin-behavior-differential-diff-radios' => 'e1ff79b1', 572 572 'javelin-behavior-differential-dropdown-menus' => '710f209e', 573 573 'javelin-behavior-differential-edit-inline-comments' => '00861799', ··· 621 621 'javelin-behavior-phabricator-notification-example' => '7a9677fc', 622 622 'javelin-behavior-phabricator-object-selector' => '39841ead', 623 623 'javelin-behavior-phabricator-oncopy' => '2926fff2', 624 - 'javelin-behavior-phabricator-remarkup-assist' => 'eff6a142', 624 + 'javelin-behavior-phabricator-remarkup-assist' => 'e32d14ab', 625 625 'javelin-behavior-phabricator-reveal-content' => '60821bc7', 626 626 'javelin-behavior-phabricator-search-typeahead' => '5a376f34', 627 627 'javelin-behavior-phabricator-show-all-transactions' => '7c273581', ··· 1047 1047 3 => 'javelin-workflow', 1048 1048 4 => 'javelin-json', 1049 1049 ), 1050 - '2bc7a5e0' => 1051 - array( 1052 - 0 => 'javelin-behavior', 1053 - 1 => 'javelin-stratcom', 1054 - 2 => 'javelin-dom', 1055 - ), 1056 1050 '2cad29d1' => 1057 1051 array( 1058 1052 0 => 'javelin-install', ··· 1225 1219 3 => 'javelin-stratcom', 1226 1220 4 => 'javelin-request', 1227 1221 ), 1222 + '4fdb476d' => 1223 + array( 1224 + 0 => 'javelin-behavior', 1225 + 1 => 'javelin-stratcom', 1226 + 2 => 'javelin-dom', 1227 + ), 1228 1228 '519705ea' => 1229 1229 array( 1230 1230 0 => 'javelin-install', ··· 1952 1952 1 => 'javelin-stratcom', 1953 1953 2 => 'javelin-dom', 1954 1954 ), 1955 + 'e32d14ab' => 1956 + array( 1957 + 0 => 'javelin-behavior', 1958 + 1 => 'javelin-stratcom', 1959 + 2 => 'javelin-dom', 1960 + 3 => 'phabricator-phtize', 1961 + 4 => 'phabricator-textareautils', 1962 + 5 => 'javelin-workflow', 1963 + 6 => 'javelin-vector', 1964 + ), 1955 1965 'e379b58e' => 1956 1966 array( 1957 1967 0 => 'javelin-behavior', ··· 1994 2004 array( 1995 2005 0 => 'javelin-install', 1996 2006 1 => 'javelin-util', 1997 - ), 1998 - 'eff6a142' => 1999 - array( 2000 - 0 => 'javelin-behavior', 2001 - 1 => 'javelin-stratcom', 2002 - 2 => 'javelin-dom', 2003 - 3 => 'phabricator-phtize', 2004 - 4 => 'phabricator-textareautils', 2005 - 5 => 'javelin-workflow', 2006 - 6 => 'javelin-vector', 2007 2007 ), 2008 2008 'f0a41b9f' => 2009 2009 array(
+6 -2
src/applications/diviner/markup/DivinerRemarkupRuleSymbol.php
··· 4 4 5 5 const KEY_RULE_ATOM_REF = 'rule.diviner.atomref'; 6 6 7 + public function getPriority() { 8 + return 40.0; 9 + } 10 + 7 11 public function apply($text) { 8 12 // Grammar here is: 9 13 // ··· 132 136 $link = $title; 133 137 } 134 138 } else if ($href) { 135 - $link = phutil_tag( 139 + $link = $this->newTag( 136 140 'a', 137 141 array( 138 142 'class' => 'atom-ref', ··· 140 144 ), 141 145 $title); 142 146 } else { 143 - $link = phutil_tag( 147 + $link = $this->newTag( 144 148 'span', 145 149 array( 146 150 'class' => 'atom-ref-invalid',
+2 -2
src/applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php
··· 48 48 } else { 49 49 $view = id(new PHUITagView()) 50 50 ->setID($tag_id) 51 - ->setName($spec['href']) 52 - ->setHref($spec['href']) 51 + ->setName($this->assertFlatText($spec['href'])) 52 + ->setHref($this->assertFlatText($spec['href'])) 53 53 ->setType(PHUITagView::TYPE_OBJECT) 54 54 ->setExternal(true); 55 55 }
+4 -4
src/applications/files/remarkup/PhabricatorRemarkupRuleEmbedFile.php
··· 180 180 $autoplay = null; 181 181 } 182 182 183 - return phutil_tag( 183 + return $this->newTag( 184 184 'audio', 185 185 array( 186 186 'controls' => 'controls', ··· 188 188 'autoplay' => $autoplay, 189 189 'loop' => idx($options, 'loop') ? 'loop' : null, 190 190 ), 191 - phutil_tag( 191 + $this->newTag( 192 192 'source', 193 193 array( 194 194 'src' => $file->getBestURI(), ··· 203 203 204 204 return id(new PhabricatorFileLinkView()) 205 205 ->setFilePHID($file->getPHID()) 206 - ->setFileName($options['name']) 206 + ->setFileName($this->assertFlatText($options['name'])) 207 207 ->setFileDownloadURI($file->getDownloadURI()) 208 208 ->setFileViewURI($file->getBestURI()) 209 - ->setFileViewable($options['viewable']); 209 + ->setFileViewable((bool)$options['viewable']); 210 210 } 211 211 212 212 private function parseDimension($string) {
+3 -3
src/applications/macro/remarkup/PhabricatorRemarkupRuleIcon.php
··· 3 3 final class PhabricatorRemarkupRuleIcon 4 4 extends PhutilRemarkupRule { 5 5 6 - private $macros; 7 - 8 - const KEY_RULE_MACRO = 'rule.macro'; 6 + public function getPriority() { 7 + return 50.0; 8 + } 9 9 10 10 public function apply($text) { 11 11 return preg_replace_callback(
+1 -1
src/applications/macro/remarkup/PhabricatorRemarkupRuleImageMacro.php
··· 147 147 )); 148 148 } 149 149 150 - $result = phutil_tag( 150 + $result = $this->newTag( 151 151 'img', 152 152 array( 153 153 'id' => $id,
+6 -2
src/applications/macro/remarkup/PhabricatorRemarkupRuleMeme.php
··· 8 8 9 9 private $images; 10 10 11 + public function getPriority() { 12 + return 50.0; 13 + } 14 + 11 15 public function apply($text) { 12 16 return preg_replace_callback( 13 17 '@{meme,((?:[^}\\\\]+|\\\\.)+)}$@m', ··· 42 46 $options['above'], 43 47 $options['below']); 44 48 45 - $img = phutil_tag( 49 + $img = $this->newTag( 46 50 'img', 47 51 array( 48 - 'src' => (string)$uri, 52 + 'src' => $uri, 49 53 'alt' => $alt_text, 50 54 )); 51 55 }
+1 -2
src/applications/paste/remarkup/PhabricatorPasteRemarkupRule.php
··· 54 54 55 55 } 56 56 57 - return $embed_paste->render(); 58 - 57 + return $embed_paste; 59 58 } 60 59 }
+1 -1
src/applications/phriction/remarkup/PhrictionRemarkupRule.php
··· 38 38 } else if ($this->getEngine()->isTextMode()) { 39 39 return PhabricatorEnv::getProductionURI($href); 40 40 } else { 41 - $text = phutil_tag( 41 + $text = $this->newTag( 42 42 'a', 43 43 array( 44 44 'href' => $href,
+9 -3
src/infrastructure/markup/rule/PhabricatorRemarkupRuleObject.php
··· 12 12 abstract protected function getObjectNamePrefix(); 13 13 abstract protected function loadObjects(array $ids); 14 14 15 + public function getPriority() { 16 + return 50.0; 17 + } 18 + 15 19 protected function getObjectNamePrefixBeginsWithWordCharacter() { 16 20 $prefix = $this->getObjectNamePrefix(); 17 21 return preg_match('/^\w/', $prefix); ··· 116 120 } 117 121 118 122 // NOTE: The "(?<!#)" prevents us from linking "#abcdef" or similar. The 119 - // "\b" allows us to link "(abcdef)" or similar without linking things 120 - // in the middle of words. 123 + // "(?<!/)" prevents us from linking things in URLs. The "\b" allows us to 124 + // link "(abcdef)" or similar without linking things in the middle of 125 + // words. 121 126 122 127 $text = preg_replace_callback( 123 - '((?<!#)'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?\b)', 128 + '((?<!#)(?<!/)'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?\b)', 124 129 array($this, 'markupObjectReference'), 125 130 $text); 126 131 ··· 212 217 $spec['id']); 213 218 break; 214 219 case 'embed': 220 + $spec['options'] = $this->assertFlatText($spec['options']); 215 221 $view = $this->renderObjectEmbed($object, $handle, $spec['options']); 216 222 break; 217 223 }
+6 -3
src/infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php
··· 30 30 } 31 31 32 32 $youtube_src = 'https://www.youtube.com/embed/'.$v; 33 - $iframe = phutil_tag_div( 34 - 'embedded-youtube-video', 35 - phutil_tag( 33 + $iframe = $this->newTag( 34 + 'div', 35 + array( 36 + 'class' => 'embedded-youtube-video', 37 + ), 38 + $this->newTag( 36 39 'iframe', 37 40 array( 38 41 'width' => '650',