Path: blob/master/src/infrastructure/markup/markuprule/PhutilRemarkupRule.php
12241 views
<?php12abstract class PhutilRemarkupRule extends Phobject {34private $engine;5private $replaceCallback;67public function setEngine(PhutilRemarkupEngine $engine) {8$this->engine = $engine;9return $this;10}1112public function getEngine() {13return $this->engine;14}1516public function getPriority() {17return 500.0;18}1920abstract public function apply($text);2122public function getPostprocessKey() {23return spl_object_hash($this);24}2526public function didMarkupText() {27return;28}2930protected function replaceHTML($pattern, $callback, $text) {31$this->replaceCallback = $callback;32return phutil_safe_html(preg_replace_callback(33$pattern,34array($this, 'replaceHTMLCallback'),35phutil_escape_html($text)));36}3738private function replaceHTMLCallback(array $match) {39return phutil_escape_html(call_user_func(40$this->replaceCallback,41array_map('phutil_safe_html', $match)));42}434445/**46* Safely generate a tag.47*48* In Remarkup contexts, it's not safe to use arbitrary text in tag49* attributes: even though it will be escaped, it may contain replacement50* tokens which are then replaced with markup.51*52* This method acts as @{function:phutil_tag}, but checks attributes before53* using them.54*55* @param string Tag name.56* @param dict<string, wild> Tag attributes.57* @param wild Tag content.58* @return PhutilSafeHTML Tag object.59*/60protected function newTag($name, array $attrs, $content = null) {61foreach ($attrs as $key => $attr) {62if ($attr !== null) {63$attrs[$key] = $this->assertFlatText($attr);64}65}6667return phutil_tag($name, $attrs, $content);68}6970/**71* Assert that a text token is flat (it contains no replacement tokens).72*73* Because tokens can be replaced with markup, it is dangerous to use74* arbitrary input text in tag attributes. Normally, rule precedence should75* prevent this. Asserting that text is flat before using it as an attribute76* provides an extra layer of security.77*78* Normally, you can call @{method:newTag} rather than calling this method79* directly. @{method:newTag} will check attributes for you.80*81* @param wild Ostensibly flat text.82* @return string Flat text.83*/84protected function assertFlatText($text) {85$text = (string)hsprintf('%s', phutil_safe_html($text));86$rich = (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) !== false);87if ($rich) {88throw new Exception(89pht(90'Remarkup rule precedence is dangerous: rendering text with tokens '.91'as flat text!'));92}9394return $text;95}9697/**98* Check whether text is flat (contains no replacement tokens) or not.99*100* @param wild Ostensibly flat text.101* @return bool True if the text is flat.102*/103protected function isFlatText($text) {104$text = (string)hsprintf('%s', phutil_safe_html($text));105return (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) === false);106}107108}109110111