Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/markup/markuprule/PhutilRemarkupRule.php
12241 views
1
<?php
2
3
abstract class PhutilRemarkupRule extends Phobject {
4
5
private $engine;
6
private $replaceCallback;
7
8
public function setEngine(PhutilRemarkupEngine $engine) {
9
$this->engine = $engine;
10
return $this;
11
}
12
13
public function getEngine() {
14
return $this->engine;
15
}
16
17
public function getPriority() {
18
return 500.0;
19
}
20
21
abstract public function apply($text);
22
23
public function getPostprocessKey() {
24
return spl_object_hash($this);
25
}
26
27
public function didMarkupText() {
28
return;
29
}
30
31
protected function replaceHTML($pattern, $callback, $text) {
32
$this->replaceCallback = $callback;
33
return phutil_safe_html(preg_replace_callback(
34
$pattern,
35
array($this, 'replaceHTMLCallback'),
36
phutil_escape_html($text)));
37
}
38
39
private function replaceHTMLCallback(array $match) {
40
return phutil_escape_html(call_user_func(
41
$this->replaceCallback,
42
array_map('phutil_safe_html', $match)));
43
}
44
45
46
/**
47
* Safely generate a tag.
48
*
49
* In Remarkup contexts, it's not safe to use arbitrary text in tag
50
* attributes: even though it will be escaped, it may contain replacement
51
* tokens which are then replaced with markup.
52
*
53
* This method acts as @{function:phutil_tag}, but checks attributes before
54
* using them.
55
*
56
* @param string Tag name.
57
* @param dict<string, wild> Tag attributes.
58
* @param wild Tag content.
59
* @return PhutilSafeHTML Tag object.
60
*/
61
protected function newTag($name, array $attrs, $content = null) {
62
foreach ($attrs as $key => $attr) {
63
if ($attr !== null) {
64
$attrs[$key] = $this->assertFlatText($attr);
65
}
66
}
67
68
return phutil_tag($name, $attrs, $content);
69
}
70
71
/**
72
* Assert that a text token is flat (it contains no replacement tokens).
73
*
74
* Because tokens can be replaced with markup, it is dangerous to use
75
* arbitrary input text in tag attributes. Normally, rule precedence should
76
* prevent this. Asserting that text is flat before using it as an attribute
77
* provides an extra layer of security.
78
*
79
* Normally, you can call @{method:newTag} rather than calling this method
80
* directly. @{method:newTag} will check attributes for you.
81
*
82
* @param wild Ostensibly flat text.
83
* @return string Flat text.
84
*/
85
protected function assertFlatText($text) {
86
$text = (string)hsprintf('%s', phutil_safe_html($text));
87
$rich = (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) !== false);
88
if ($rich) {
89
throw new Exception(
90
pht(
91
'Remarkup rule precedence is dangerous: rendering text with tokens '.
92
'as flat text!'));
93
}
94
95
return $text;
96
}
97
98
/**
99
* Check whether text is flat (contains no replacement tokens) or not.
100
*
101
* @param wild Ostensibly flat text.
102
* @return bool True if the text is flat.
103
*/
104
protected function isFlatText($text) {
105
$text = (string)hsprintf('%s', phutil_safe_html($text));
106
return (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) === false);
107
}
108
109
}
110
111