1
|
|
|
<?php |
2
|
|
|
class Snippets |
3
|
|
|
{ |
4
|
|
|
public $snippets; |
5
|
|
|
public $total_snippets; |
6
|
|
|
|
7
|
|
|
private $xml_file; |
8
|
|
|
private $xml; |
9
|
|
|
private $allow_edit = false; |
10
|
|
|
private $allow_script = false; |
11
|
|
|
private $allow_php = false; |
12
|
|
|
private $script_found = false; |
13
|
|
|
private $php_found = false; |
14
|
|
|
|
15
|
|
|
public function __construct($xml_file, $allow_edit) |
16
|
|
|
{ |
17
|
|
|
$this->allow_edit = $allow_edit; |
18
|
|
|
$this->xml_file = $xml_file; |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
public function getSnippets() |
22
|
|
|
{ |
23
|
|
|
$this->xml = simplexml_load_file($this->xml_file); |
24
|
|
|
$this->snippets = $this->xml->snippet; |
|
|
|
|
25
|
|
|
$this->total_snippets = count($this->snippets); |
26
|
|
|
} |
27
|
|
|
|
28
|
|
|
public function render() |
29
|
|
|
{ |
30
|
|
|
$html = ''; |
31
|
|
|
if (empty($this->total_snippets)) { |
32
|
|
|
$html .= '<div class="col-xs-12">' . " \n"; |
33
|
|
|
$html .= '<p> </p><p>' . NO_SNIPPET_TO_DISPLAY . '</p>' . " \n"; |
34
|
|
|
$html .= '</div>' . " \n"; |
35
|
|
|
} else { |
36
|
|
|
for ($i=0; $i < $this->total_snippets; $i++) { |
37
|
|
|
$snp = $this->snippets[$i]; |
38
|
|
|
$html .= '<div class="col-sm-6">' . " \n"; |
39
|
|
|
$html .= ' <div class="text-center">' . " \n"; |
40
|
|
|
$html .= ' <div class="choice selector select-snippet" data-index="' . $i . '">' . " \n"; |
41
|
|
|
$html .= ' ' . $snp->title; |
42
|
|
|
$html .= ' </div>' . " \n"; |
43
|
|
|
$html .= ' </div>' . " \n"; |
44
|
|
|
$html .= '</div>' . " \n"; |
45
|
|
|
$html .= '<div class="hidden" id="content-' . $i . '">' . " \n"; |
46
|
|
|
$html .= htmlspecialchars_decode($snp->content); |
47
|
|
|
$html .= '</div>' . " \n"; |
48
|
|
|
} |
49
|
|
|
} |
50
|
|
|
if ('true' === $this->allow_edit) { |
51
|
|
|
$html .= '<div class="col-sm-6">' . " \n"; |
52
|
|
|
$html .= ' <div class="text-center">' . " \n"; |
53
|
|
|
$html .= ' <button class="btn btn-primary" id="add-new-snippet-btn">' . ADD_NEW_SNIPPET . '</button>' . " \n"; |
54
|
|
|
$html .= ' </div>' . " \n"; |
55
|
|
|
$html .= '</div>' . " \n"; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
return $html; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
public function addNewSnippet($title, $content) |
62
|
|
|
{ |
63
|
|
|
if (!empty($title) && !empty($content)) { |
64
|
|
|
libxml_use_internal_errors(true); // avoid warnings if using html5 tags with $dom->loadXML |
65
|
|
View Code Duplication |
if (false == $this->allow_php) { |
|
|
|
|
66
|
|
|
$title = $this->removePhp($title); |
67
|
|
|
$content = $this->removePhp($content); |
68
|
|
|
} |
69
|
|
View Code Duplication |
if (false == $this->allow_script) { |
|
|
|
|
70
|
|
|
$title = $this->removeScripts($title); |
71
|
|
|
$content = $this->removeScripts($content); |
72
|
|
|
} |
73
|
|
|
$xml = $this->xml; |
74
|
|
|
$total_snippets = $this->total_snippets; |
|
|
|
|
75
|
|
|
$dom = dom_import_simplexml($xml)->ownerDocument; |
|
|
|
|
76
|
|
|
$dom = new DOMDocument('1.0'); |
77
|
|
|
$dom->preserveWhiteSpace = false; |
78
|
|
|
$dom->formatOutput = true; |
79
|
|
|
$dom->loadXML($xml->asXML()); |
80
|
|
|
$new_snippet = $dom->createElement('snippet'); |
81
|
|
|
$new_title = $dom->createElement('title'); |
82
|
|
|
$new_content = $dom->createElement('content'); |
83
|
|
|
$title_text = $dom->createTextNode($title); |
84
|
|
|
$content_text = $dom->createTextNode($content); |
85
|
|
|
$new_title->appendChild($title_text); |
86
|
|
|
$new_content->appendChild($content_text); |
87
|
|
|
$new_snippet->appendChild($new_title); |
88
|
|
|
$new_snippet->appendChild($new_content); |
89
|
|
|
$dom->documentElement->appendChild($new_snippet); |
90
|
|
|
$dom->save($this->xml_file); |
91
|
|
|
$this->getSnippets(); |
92
|
|
View Code Duplication |
if (true == $this->script_found) { |
|
|
|
|
93
|
|
|
return 'script_forbidden'; |
94
|
|
|
} elseif (true == $this->php_found) { |
|
|
|
|
95
|
|
|
return 'php_forbidden'; |
96
|
|
|
} else { |
97
|
|
|
return true; |
98
|
|
|
} |
99
|
|
|
} else { |
100
|
|
|
return false; |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
public function editSnippet($index, $title, $content) |
104
|
|
|
{ |
105
|
|
|
libxml_use_internal_errors(true); // avoid warnings if using html5 tags with $dom->loadXML |
106
|
|
View Code Duplication |
if (false == $this->allow_php) { |
|
|
|
|
107
|
|
|
$title = $this->removePhp($title); |
108
|
|
|
$content = $this->removePhp($content); |
109
|
|
|
} |
110
|
|
View Code Duplication |
if (false == $this->allow_script) { |
|
|
|
|
111
|
|
|
$title = $this->removeScripts($title); |
112
|
|
|
$content = $this->removeScripts($content); |
113
|
|
|
} |
114
|
|
|
$xml = $this->xml; |
115
|
|
|
$total_snippets = $this->total_snippets; |
|
|
|
|
116
|
|
|
$dom = dom_import_simplexml($xml)->ownerDocument; |
|
|
|
|
117
|
|
|
$dom = new DOMDocument('1.0'); |
118
|
|
|
$dom->preserveWhiteSpace = false; |
119
|
|
|
$dom->formatOutput = true; |
120
|
|
|
$dom->loadXML($xml->asXML()); |
121
|
|
|
$new_snippet = $dom->createElement('snippet'); |
122
|
|
|
$new_title = $dom->createElement('title'); |
123
|
|
|
$new_content = $dom->createElement('content'); |
124
|
|
|
$title_text = $dom->createTextNode($title); |
125
|
|
|
$content_text = $dom->createTextNode($content); |
126
|
|
|
$new_title->appendChild($title_text); |
127
|
|
|
$new_content->appendChild($content_text); |
128
|
|
|
$new_snippet->appendChild($new_title); |
129
|
|
|
$new_snippet->appendChild($new_content); |
130
|
|
|
$old_snippet = $dom->documentElement->getElementsByTagName('snippet')->item($index); |
131
|
|
|
$dom->documentElement->replaceChild($new_snippet, $old_snippet); |
132
|
|
|
$dom->save($this->xml_file); |
133
|
|
|
$this->getSnippets(); |
134
|
|
View Code Duplication |
if (true == $this->script_found) { |
|
|
|
|
135
|
|
|
return 'script_forbidden'; |
136
|
|
|
} elseif (true == $this->php_found) { |
|
|
|
|
137
|
|
|
return 'php_forbidden'; |
138
|
|
|
} else { |
139
|
|
|
return true; |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
public function deleteSnippet($index) |
144
|
|
|
{ |
145
|
|
|
libxml_use_internal_errors(true); // avoid warnings if using html5 tags with $dom->loadXML |
146
|
|
|
$xml = $this->xml; |
147
|
|
|
$total_snippets = $this->total_snippets; |
|
|
|
|
148
|
|
|
$dom = dom_import_simplexml($xml)->ownerDocument; |
|
|
|
|
149
|
|
|
$dom = new DOMDocument('1.0'); |
150
|
|
|
$dom->preserveWhiteSpace = false; |
151
|
|
|
$dom->formatOutput = true; |
152
|
|
|
$dom->loadXML($xml->asXML()); |
153
|
|
|
$old_snippet = $dom->documentElement->getElementsByTagName('snippet')->item($index); |
154
|
|
|
$dom->documentElement->removeChild($old_snippet); |
155
|
|
|
$dom->save($this->xml_file); |
156
|
|
|
$this->getSnippets(); |
157
|
|
|
|
158
|
|
|
return true; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Removes unwanted script tags from snippet |
163
|
|
|
* @param $element |
164
|
|
|
* @return string|string[]|null $snippet_tag |
165
|
|
|
*/ |
166
|
|
|
private function removeScripts($element) |
167
|
|
|
{ |
168
|
|
|
$dom = new DOMDocument(); |
169
|
|
|
$dom->loadHTML($element); |
170
|
|
|
|
171
|
|
|
$xpath = new DOMXPath($dom); |
172
|
|
|
while ($node = $xpath->query('//script')->item(0)) { |
173
|
|
|
$node->parentNode->removeChild($node); |
174
|
|
|
$this->script_found = true; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
return preg_replace('/^<!DOCTYPE.+?>/', '', str_replace(['<html>', '</html>', '<body>', '</body>'], ['', '', '', ''], $dom->saveHTML())); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Removes unwanted php scripts from snippet |
182
|
|
|
* @param string $element title | content |
183
|
|
|
* @return \content|string|string[]|\title|null $element element cleaned |
184
|
|
|
*/ |
185
|
|
|
private function removePhp($element) |
186
|
|
|
{ |
187
|
|
|
if (preg_match_all('/<\?php(.+?)\?>/is', $element, $out)) { |
188
|
|
|
$this->php_found = true; |
189
|
|
|
$element = preg_replace('/<\?php(.+?)\?>/is', '', $element); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
return $element; |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.