Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 239 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
acp_bbcodes | |
0.00% |
0 / 237 |
|
0.00% |
0 / 2 |
1892 | |
0.00% |
0 / 1 |
main | |
0.00% |
0 / 225 |
|
0.00% |
0 / 1 |
1722 | |||
build_regexp | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | /** |
15 | * @ignore |
16 | */ |
17 | if (!defined('IN_PHPBB')) |
18 | { |
19 | exit; |
20 | } |
21 | |
22 | class acp_bbcodes |
23 | { |
24 | var $u_action; |
25 | |
26 | function main($id, $mode) |
27 | { |
28 | global $db, $user, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container; |
29 | global $phpbb_log; |
30 | |
31 | $user->add_lang('acp/posting'); |
32 | |
33 | // Set up general vars |
34 | $action = $request->variable('action', ''); |
35 | $bbcode_id = $request->variable('bbcode', 0); |
36 | |
37 | $this->tpl_name = 'acp_bbcodes'; |
38 | $this->page_title = 'ACP_BBCODES'; |
39 | $form_key = 'acp_bbcodes'; |
40 | |
41 | add_form_key($form_key); |
42 | |
43 | // Set up mode-specific vars |
44 | switch ($action) |
45 | { |
46 | case 'add': |
47 | $bbcode_match = $bbcode_tpl = $bbcode_helpline = ''; |
48 | $display_on_posting = 0; |
49 | break; |
50 | |
51 | case 'edit': |
52 | $sql = 'SELECT bbcode_match, bbcode_tpl, display_on_posting, bbcode_helpline |
53 | FROM ' . BBCODES_TABLE . ' |
54 | WHERE bbcode_id = ' . $bbcode_id; |
55 | $result = $db->sql_query($sql); |
56 | $row = $db->sql_fetchrow($result); |
57 | $db->sql_freeresult($result); |
58 | |
59 | if (!$row) |
60 | { |
61 | trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); |
62 | } |
63 | |
64 | $bbcode_match = $row['bbcode_match']; |
65 | $bbcode_tpl = htmlspecialchars($row['bbcode_tpl'], ENT_COMPAT); |
66 | $display_on_posting = $row['display_on_posting']; |
67 | $bbcode_helpline = $row['bbcode_helpline']; |
68 | break; |
69 | |
70 | case 'modify': |
71 | $sql = 'SELECT bbcode_id, bbcode_tag |
72 | FROM ' . BBCODES_TABLE . ' |
73 | WHERE bbcode_id = ' . $bbcode_id; |
74 | $result = $db->sql_query($sql); |
75 | $row = $db->sql_fetchrow($result); |
76 | $db->sql_freeresult($result); |
77 | |
78 | if (!$row) |
79 | { |
80 | trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); |
81 | } |
82 | |
83 | // No break here |
84 | |
85 | case 'create': |
86 | $display_on_posting = $request->variable('display_on_posting', 0); |
87 | |
88 | $bbcode_match = $request->variable('bbcode_match', ''); |
89 | $bbcode_tpl = html_entity_decode($request->variable('bbcode_tpl', '', true), ENT_COMPAT); |
90 | $bbcode_helpline = $request->variable('bbcode_helpline', '', true); |
91 | break; |
92 | } |
93 | |
94 | // Do major work |
95 | switch ($action) |
96 | { |
97 | case 'edit': |
98 | case 'add': |
99 | |
100 | $tpl_ary = array( |
101 | 'S_EDIT_BBCODE' => true, |
102 | 'U_BACK' => $this->u_action, |
103 | 'U_ACTION' => $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&bbcode=$bbcode_id" : ''), |
104 | |
105 | 'L_BBCODE_USAGE_EXPLAIN'=> sprintf($user->lang['BBCODE_USAGE_EXPLAIN'], '<a href="#down">', '</a>'), |
106 | 'BBCODE_MATCH' => $bbcode_match, |
107 | 'BBCODE_TPL' => $bbcode_tpl, |
108 | 'BBCODE_HELPLINE' => $bbcode_helpline, |
109 | 'DISPLAY_ON_POSTING' => $display_on_posting, |
110 | ); |
111 | |
112 | $bbcode_tokens = array('TEXT', 'SIMPLETEXT', 'INTTEXT', 'IDENTIFIER', 'NUMBER', 'EMAIL', 'URL', 'LOCAL_URL', 'RELATIVE_URL', 'COLOR'); |
113 | $bbcode_tokens = array_merge($bbcode_tokens, ['ALNUM', 'CHOICE', 'FLOAT', 'HASHMAP', 'INT', 'IP', 'IPPORT', 'IPV4', 'IPV6', 'MAP', 'RANGE', 'REGEXP', 'TIMESTAMP', 'UINT']); |
114 | |
115 | /** |
116 | * Modify custom bbcode template data before we display the add/edit form |
117 | * |
118 | * @event core.acp_bbcodes_edit_add |
119 | * @var string action Type of the action: add|edit |
120 | * @var array tpl_ary Array with custom bbcode add/edit data |
121 | * @var int bbcode_id When editing: the bbcode id, |
122 | * when creating: 0 |
123 | * @var array bbcode_tokens Array of bbcode tokens |
124 | * @since 3.1.0-a3 |
125 | */ |
126 | $vars = array('action', 'tpl_ary', 'bbcode_id', 'bbcode_tokens'); |
127 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_edit_add', compact($vars))); |
128 | |
129 | $template->assign_vars($tpl_ary); |
130 | |
131 | foreach ($bbcode_tokens as $token) |
132 | { |
133 | $template->assign_block_vars('token', array( |
134 | 'TOKEN' => '{' . $token . '}', |
135 | 'EXPLAIN' => ($token === 'LOCAL_URL') ? $user->lang(array('tokens', $token), generate_board_url() . '/') : $user->lang(array('tokens', $token)), |
136 | )); |
137 | } |
138 | |
139 | return; |
140 | |
141 | break; |
142 | |
143 | case 'modify': |
144 | case 'create': |
145 | |
146 | $sql_ary = $hidden_fields = array(); |
147 | |
148 | /** |
149 | * Modify custom bbcode data before the modify/create action |
150 | * |
151 | * @event core.acp_bbcodes_modify_create |
152 | * @var string action Type of the action: modify|create |
153 | * @var array sql_ary Array with new bbcode data |
154 | * @var int bbcode_id When editing: the bbcode id, |
155 | * when creating: 0 |
156 | * @var bool display_on_posting Display bbcode on posting form |
157 | * @var string bbcode_match The bbcode usage string to match |
158 | * @var string bbcode_tpl The bbcode HTML replacement string |
159 | * @var string bbcode_helpline The bbcode help line string |
160 | * @var array hidden_fields Array of hidden fields for use when |
161 | * submitting form when $warn_unsafe is true |
162 | * @since 3.1.0-a3 |
163 | */ |
164 | $vars = array( |
165 | 'action', |
166 | 'sql_ary', |
167 | 'bbcode_id', |
168 | 'display_on_posting', |
169 | 'bbcode_match', |
170 | 'bbcode_tpl', |
171 | 'bbcode_helpline', |
172 | 'hidden_fields', |
173 | ); |
174 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create', compact($vars))); |
175 | |
176 | $acp_utils = $phpbb_container->get('text_formatter.acp_utils'); |
177 | $bbcode_info = $acp_utils->analyse_bbcode($bbcode_match, $bbcode_tpl); |
178 | $warn_unsafe = ($bbcode_info['status'] === $acp_utils::BBCODE_STATUS_UNSAFE); |
179 | |
180 | if ($bbcode_info['status'] === $acp_utils::BBCODE_STATUS_INVALID_TEMPLATE) |
181 | { |
182 | trigger_error($user->lang['BBCODE_INVALID_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); |
183 | } |
184 | if ($bbcode_info['status'] === $acp_utils::BBCODE_STATUS_INVALID_DEFINITION) |
185 | { |
186 | trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); |
187 | } |
188 | |
189 | if (!$warn_unsafe && !check_form_key($form_key)) |
190 | { |
191 | trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); |
192 | } |
193 | |
194 | if (!$warn_unsafe || confirm_box(true)) |
195 | { |
196 | $data = $this->build_regexp($bbcode_match, $bbcode_tpl); |
197 | |
198 | // Make sure the user didn't pick a "bad" name for the BBCode tag. |
199 | $hard_coded = array('code', 'quote', 'quote=', 'attachment', 'attachment=', 'b', 'i', 'url', 'url=', 'img', 'size', 'size=', 'color', 'color=', 'u', 'list', 'list=', 'email', 'email=', 'mention'); |
200 | |
201 | if (($action == 'modify' && strtolower($data['bbcode_tag']) !== strtolower($row['bbcode_tag'])) || ($action == 'create')) |
202 | { |
203 | $sql = 'SELECT 1 as test |
204 | FROM ' . BBCODES_TABLE . " |
205 | WHERE LOWER(bbcode_tag) = '" . $db->sql_escape(strtolower($data['bbcode_tag'])) . "'"; |
206 | $result = $db->sql_query($sql); |
207 | $info = $db->sql_fetchrow($result); |
208 | $db->sql_freeresult($result); |
209 | |
210 | // Grab the end, interrogate the last closing tag |
211 | if (isset($info['test']) && $info['test'] === '1' |
212 | || in_array(strtolower($data['bbcode_tag']), $hard_coded) |
213 | || (preg_match('#\[/([^[]*)]$#', $bbcode_match, $regs) && in_array(strtolower($regs[1]), $hard_coded)) |
214 | ) |
215 | { |
216 | trigger_error($user->lang['BBCODE_INVALID_TAG_NAME'] . adm_back_link($this->u_action), E_USER_WARNING); |
217 | } |
218 | } |
219 | |
220 | if (strlen($data['bbcode_tag']) > 16) |
221 | { |
222 | trigger_error($user->lang['BBCODE_TAG_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); |
223 | } |
224 | |
225 | if (strlen($bbcode_match) > 4000) |
226 | { |
227 | trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); |
228 | } |
229 | |
230 | if (strlen($bbcode_helpline) > 3000) |
231 | { |
232 | trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); |
233 | } |
234 | |
235 | /** |
236 | * Replace Emojis and other 4bit UTF-8 chars not allowed by MySQL to UCR/NCR. |
237 | * Using their Numeric Character Reference's Hexadecimal notation. |
238 | */ |
239 | $bbcode_helpline = utf8_encode_ucr($bbcode_helpline); |
240 | |
241 | $sql_ary = array_merge($sql_ary, array( |
242 | 'bbcode_tag' => $data['bbcode_tag'], |
243 | 'bbcode_match' => $bbcode_match, |
244 | 'bbcode_tpl' => $bbcode_tpl, |
245 | 'display_on_posting' => $display_on_posting, |
246 | 'bbcode_helpline' => $bbcode_helpline, |
247 | 'first_pass_match' => $data['first_pass_match'], |
248 | 'first_pass_replace' => $data['first_pass_replace'], |
249 | 'second_pass_match' => $data['second_pass_match'], |
250 | 'second_pass_replace' => $data['second_pass_replace'] |
251 | )); |
252 | |
253 | if ($action == 'create') |
254 | { |
255 | $sql = 'SELECT MAX(bbcode_id) as max_bbcode_id |
256 | FROM ' . BBCODES_TABLE; |
257 | $result = $db->sql_query($sql); |
258 | $row = $db->sql_fetchrow($result); |
259 | $db->sql_freeresult($result); |
260 | |
261 | if ($row) |
262 | { |
263 | $bbcode_id = (int) $row['max_bbcode_id'] + 1; |
264 | |
265 | // Make sure it is greater than the core bbcode ids... |
266 | if ($bbcode_id <= NUM_CORE_BBCODES) |
267 | { |
268 | $bbcode_id = NUM_CORE_BBCODES + 1; |
269 | } |
270 | } |
271 | else |
272 | { |
273 | $bbcode_id = NUM_CORE_BBCODES + 1; |
274 | } |
275 | |
276 | if ($bbcode_id > BBCODE_LIMIT) |
277 | { |
278 | trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING); |
279 | } |
280 | |
281 | $sql_ary['bbcode_id'] = (int) $bbcode_id; |
282 | |
283 | $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); |
284 | $cache->destroy('sql', BBCODES_TABLE); |
285 | $phpbb_container->get('text_formatter.cache')->invalidate(); |
286 | |
287 | $lang = 'BBCODE_ADDED'; |
288 | $log_action = 'LOG_BBCODE_ADD'; |
289 | } |
290 | else |
291 | { |
292 | $sql = 'UPDATE ' . BBCODES_TABLE . ' |
293 | SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' |
294 | WHERE bbcode_id = ' . $bbcode_id; |
295 | $db->sql_query($sql); |
296 | $cache->destroy('sql', BBCODES_TABLE); |
297 | $phpbb_container->get('text_formatter.cache')->invalidate(); |
298 | |
299 | $lang = 'BBCODE_EDITED'; |
300 | $log_action = 'LOG_BBCODE_EDIT'; |
301 | } |
302 | |
303 | $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag'])); |
304 | |
305 | /** |
306 | * Event after a BBCode has been added or updated |
307 | * |
308 | * @event core.acp_bbcodes_modify_create_after |
309 | * @var string action Type of the action: modify|create |
310 | * @var int bbcode_id The id of the added or updated bbcode |
311 | * @var array sql_ary Array with bbcode data (read only) |
312 | * @since 3.2.4-RC1 |
313 | */ |
314 | $vars = array( |
315 | 'action', |
316 | 'bbcode_id', |
317 | 'sql_ary', |
318 | ); |
319 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create_after', compact($vars))); |
320 | |
321 | trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); |
322 | } |
323 | else |
324 | { |
325 | confirm_box(false, $user->lang['BBCODE_DANGER'], build_hidden_fields(array_merge($hidden_fields, array( |
326 | 'action' => $action, |
327 | 'bbcode' => $bbcode_id, |
328 | 'bbcode_match' => $bbcode_match, |
329 | 'bbcode_tpl' => htmlspecialchars($bbcode_tpl, ENT_COMPAT), |
330 | 'bbcode_helpline' => $bbcode_helpline, |
331 | 'display_on_posting' => $display_on_posting, |
332 | ))) |
333 | , 'confirm_bbcode.html'); |
334 | } |
335 | |
336 | break; |
337 | |
338 | case 'delete': |
339 | |
340 | $sql = 'SELECT bbcode_tag |
341 | FROM ' . BBCODES_TABLE . " |
342 | WHERE bbcode_id = $bbcode_id"; |
343 | $result = $db->sql_query($sql); |
344 | $row = $db->sql_fetchrow($result); |
345 | $db->sql_freeresult($result); |
346 | |
347 | if ($row) |
348 | { |
349 | if (confirm_box(true)) |
350 | { |
351 | $bbcode_tag = $row['bbcode_tag']; |
352 | |
353 | $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); |
354 | $cache->destroy('sql', BBCODES_TABLE); |
355 | $phpbb_container->get('text_formatter.cache')->invalidate(); |
356 | $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($bbcode_tag)); |
357 | |
358 | /** |
359 | * Event after a BBCode has been deleted |
360 | * |
361 | * @event core.acp_bbcodes_delete_after |
362 | * @var string action Type of the action: delete |
363 | * @var int bbcode_id The id of the deleted bbcode |
364 | * @var string bbcode_tag The tag of the deleted bbcode |
365 | * @since 3.2.4-RC1 |
366 | */ |
367 | $vars = array( |
368 | 'action', |
369 | 'bbcode_id', |
370 | 'bbcode_tag', |
371 | ); |
372 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_delete_after', compact($vars))); |
373 | |
374 | if ($request->is_ajax()) |
375 | { |
376 | $json_response = new \phpbb\json_response; |
377 | $json_response->send(array( |
378 | 'MESSAGE_TITLE' => $user->lang['INFORMATION'], |
379 | 'MESSAGE_TEXT' => $user->lang['BBCODE_DELETED'], |
380 | 'REFRESH_DATA' => array( |
381 | 'time' => 3 |
382 | ) |
383 | )); |
384 | } |
385 | } |
386 | else |
387 | { |
388 | confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( |
389 | 'bbcode' => $bbcode_id, |
390 | 'i' => $id, |
391 | 'mode' => $mode, |
392 | 'action' => $action)) |
393 | ); |
394 | } |
395 | } |
396 | |
397 | break; |
398 | } |
399 | |
400 | $u_action = $this->u_action; |
401 | |
402 | $template_data = array( |
403 | 'U_ACTION' => $this->u_action . '&action=add', |
404 | ); |
405 | |
406 | $sql_ary = array( |
407 | 'SELECT' => 'b.*', |
408 | 'FROM' => array(BBCODES_TABLE => 'b'), |
409 | 'ORDER_BY' => 'b.bbcode_tag', |
410 | ); |
411 | |
412 | /** |
413 | * Modify custom bbcode template data before we display the form |
414 | * |
415 | * @event core.acp_bbcodes_display_form |
416 | * @var string action Type of the action: modify|create |
417 | * @var array sql_ary The SQL array to get custom bbcode data |
418 | * @var array template_data Array with form template data |
419 | * @var string u_action The u_action link |
420 | * @since 3.1.0-a3 |
421 | */ |
422 | $vars = array('action', 'sql_ary', 'template_data', 'u_action'); |
423 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_form', compact($vars))); |
424 | |
425 | $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); |
426 | |
427 | $template->assign_vars($template_data); |
428 | |
429 | while ($row = $db->sql_fetchrow($result)) |
430 | { |
431 | $bbcodes_array = array( |
432 | 'BBCODE_TAG' => $row['bbcode_tag'], |
433 | 'U_EDIT' => $u_action . '&action=edit&bbcode=' . $row['bbcode_id'], |
434 | 'U_DELETE' => $u_action . '&action=delete&bbcode=' . $row['bbcode_id'], |
435 | ); |
436 | |
437 | /** |
438 | * Modify display of custom bbcodes in the form |
439 | * |
440 | * @event core.acp_bbcodes_display_bbcodes |
441 | * @var array row Array with current bbcode data |
442 | * @var array bbcodes_array Array of bbcodes template data |
443 | * @var string u_action The u_action link |
444 | * @since 3.1.0-a3 |
445 | */ |
446 | $vars = array('bbcodes_array', 'row', 'u_action'); |
447 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_bbcodes', compact($vars))); |
448 | |
449 | $template->assign_block_vars('bbcodes', $bbcodes_array); |
450 | |
451 | } |
452 | $db->sql_freeresult($result); |
453 | } |
454 | |
455 | /* |
456 | * Build regular expression for custom bbcode |
457 | */ |
458 | function build_regexp(&$bbcode_match, &$bbcode_tpl) |
459 | { |
460 | $bbcode_match = trim($bbcode_match); |
461 | $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+).*/i', '$1', $bbcode_match); |
462 | |
463 | if (!preg_match('/^[a-zA-Z0-9_-]+$/', $bbcode_tag)) |
464 | { |
465 | global $user; |
466 | trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); |
467 | } |
468 | |
469 | return array( |
470 | 'bbcode_tag' => $bbcode_tag, |
471 | 'first_pass_match' => '/(?!)/', |
472 | 'first_pass_replace' => '', |
473 | // Use a non-matching, valid regexp to effectively disable this BBCode |
474 | 'second_pass_match' => '/(?!)/', |
475 | 'second_pass_replace' => '' |
476 | ); |
477 | } |
478 | } |