Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 238 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
acp_bbcodes | |
0.00% |
0 / 236 |
|
0.00% |
0 / 2 |
1892 | |
0.00% |
0 / 1 |
main | |
0.00% |
0 / 224 |
|
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 | |
114 | /** |
115 | * Modify custom bbcode template data before we display the add/edit form |
116 | * |
117 | * @event core.acp_bbcodes_edit_add |
118 | * @var string action Type of the action: add|edit |
119 | * @var array tpl_ary Array with custom bbcode add/edit data |
120 | * @var int bbcode_id When editing: the bbcode id, |
121 | * when creating: 0 |
122 | * @var array bbcode_tokens Array of bbcode tokens |
123 | * @since 3.1.0-a3 |
124 | */ |
125 | $vars = array('action', 'tpl_ary', 'bbcode_id', 'bbcode_tokens'); |
126 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_edit_add', compact($vars))); |
127 | |
128 | $template->assign_vars($tpl_ary); |
129 | |
130 | foreach ($bbcode_tokens as $token) |
131 | { |
132 | $template->assign_block_vars('token', array( |
133 | 'TOKEN' => '{' . $token . '}', |
134 | 'EXPLAIN' => ($token === 'LOCAL_URL') ? $user->lang(array('tokens', $token), generate_board_url() . '/') : $user->lang(array('tokens', $token)), |
135 | )); |
136 | } |
137 | |
138 | return; |
139 | |
140 | break; |
141 | |
142 | case 'modify': |
143 | case 'create': |
144 | |
145 | $sql_ary = $hidden_fields = array(); |
146 | |
147 | /** |
148 | * Modify custom bbcode data before the modify/create action |
149 | * |
150 | * @event core.acp_bbcodes_modify_create |
151 | * @var string action Type of the action: modify|create |
152 | * @var array sql_ary Array with new bbcode data |
153 | * @var int bbcode_id When editing: the bbcode id, |
154 | * when creating: 0 |
155 | * @var bool display_on_posting Display bbcode on posting form |
156 | * @var string bbcode_match The bbcode usage string to match |
157 | * @var string bbcode_tpl The bbcode HTML replacement string |
158 | * @var string bbcode_helpline The bbcode help line string |
159 | * @var array hidden_fields Array of hidden fields for use when |
160 | * submitting form when $warn_unsafe is true |
161 | * @since 3.1.0-a3 |
162 | */ |
163 | $vars = array( |
164 | 'action', |
165 | 'sql_ary', |
166 | 'bbcode_id', |
167 | 'display_on_posting', |
168 | 'bbcode_match', |
169 | 'bbcode_tpl', |
170 | 'bbcode_helpline', |
171 | 'hidden_fields', |
172 | ); |
173 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create', compact($vars))); |
174 | |
175 | $acp_utils = $phpbb_container->get('text_formatter.acp_utils'); |
176 | $bbcode_info = $acp_utils->analyse_bbcode($bbcode_match, $bbcode_tpl); |
177 | $warn_unsafe = ($bbcode_info['status'] === $acp_utils::BBCODE_STATUS_UNSAFE); |
178 | |
179 | if ($bbcode_info['status'] === $acp_utils::BBCODE_STATUS_INVALID_TEMPLATE) |
180 | { |
181 | trigger_error($user->lang['BBCODE_INVALID_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); |
182 | } |
183 | if ($bbcode_info['status'] === $acp_utils::BBCODE_STATUS_INVALID_DEFINITION) |
184 | { |
185 | trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); |
186 | } |
187 | |
188 | if (!$warn_unsafe && !check_form_key($form_key)) |
189 | { |
190 | trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); |
191 | } |
192 | |
193 | if (!$warn_unsafe || confirm_box(true)) |
194 | { |
195 | $data = $this->build_regexp($bbcode_match, $bbcode_tpl); |
196 | |
197 | // Make sure the user didn't pick a "bad" name for the BBCode tag. |
198 | $hard_coded = array('code', 'quote', 'quote=', 'attachment', 'attachment=', 'b', 'i', 'url', 'url=', 'img', 'size', 'size=', 'color', 'color=', 'u', 'list', 'list=', 'email', 'email=', 'mention'); |
199 | |
200 | if (($action == 'modify' && strtolower($data['bbcode_tag']) !== strtolower($row['bbcode_tag'])) || ($action == 'create')) |
201 | { |
202 | $sql = 'SELECT 1 as test |
203 | FROM ' . BBCODES_TABLE . " |
204 | WHERE LOWER(bbcode_tag) = '" . $db->sql_escape(strtolower($data['bbcode_tag'])) . "'"; |
205 | $result = $db->sql_query($sql); |
206 | $info = $db->sql_fetchrow($result); |
207 | $db->sql_freeresult($result); |
208 | |
209 | // Grab the end, interrogate the last closing tag |
210 | if (isset($info['test']) && $info['test'] === '1' |
211 | || in_array(strtolower($data['bbcode_tag']), $hard_coded) |
212 | || (preg_match('#\[/([^[]*)]$#', $bbcode_match, $regs) && in_array(strtolower($regs[1]), $hard_coded)) |
213 | ) |
214 | { |
215 | trigger_error($user->lang['BBCODE_INVALID_TAG_NAME'] . adm_back_link($this->u_action), E_USER_WARNING); |
216 | } |
217 | } |
218 | |
219 | if (strlen($data['bbcode_tag']) > 16) |
220 | { |
221 | trigger_error($user->lang['BBCODE_TAG_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); |
222 | } |
223 | |
224 | if (strlen($bbcode_match) > 4000) |
225 | { |
226 | trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); |
227 | } |
228 | |
229 | if (strlen($bbcode_helpline) > 3000) |
230 | { |
231 | trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); |
232 | } |
233 | |
234 | /** |
235 | * Replace Emojis and other 4bit UTF-8 chars not allowed by MySQL to UCR/NCR. |
236 | * Using their Numeric Character Reference's Hexadecimal notation. |
237 | */ |
238 | $bbcode_helpline = utf8_encode_ucr($bbcode_helpline); |
239 | |
240 | $sql_ary = array_merge($sql_ary, array( |
241 | 'bbcode_tag' => $data['bbcode_tag'], |
242 | 'bbcode_match' => $bbcode_match, |
243 | 'bbcode_tpl' => $bbcode_tpl, |
244 | 'display_on_posting' => $display_on_posting, |
245 | 'bbcode_helpline' => $bbcode_helpline, |
246 | 'first_pass_match' => $data['first_pass_match'], |
247 | 'first_pass_replace' => $data['first_pass_replace'], |
248 | 'second_pass_match' => $data['second_pass_match'], |
249 | 'second_pass_replace' => $data['second_pass_replace'] |
250 | )); |
251 | |
252 | if ($action == 'create') |
253 | { |
254 | $sql = 'SELECT MAX(bbcode_id) as max_bbcode_id |
255 | FROM ' . BBCODES_TABLE; |
256 | $result = $db->sql_query($sql); |
257 | $row = $db->sql_fetchrow($result); |
258 | $db->sql_freeresult($result); |
259 | |
260 | if ($row) |
261 | { |
262 | $bbcode_id = (int) $row['max_bbcode_id'] + 1; |
263 | |
264 | // Make sure it is greater than the core bbcode ids... |
265 | if ($bbcode_id <= NUM_CORE_BBCODES) |
266 | { |
267 | $bbcode_id = NUM_CORE_BBCODES + 1; |
268 | } |
269 | } |
270 | else |
271 | { |
272 | $bbcode_id = NUM_CORE_BBCODES + 1; |
273 | } |
274 | |
275 | if ($bbcode_id > BBCODE_LIMIT) |
276 | { |
277 | trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING); |
278 | } |
279 | |
280 | $sql_ary['bbcode_id'] = (int) $bbcode_id; |
281 | |
282 | $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); |
283 | $cache->destroy('sql', BBCODES_TABLE); |
284 | $phpbb_container->get('text_formatter.cache')->invalidate(); |
285 | |
286 | $lang = 'BBCODE_ADDED'; |
287 | $log_action = 'LOG_BBCODE_ADD'; |
288 | } |
289 | else |
290 | { |
291 | $sql = 'UPDATE ' . BBCODES_TABLE . ' |
292 | SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' |
293 | WHERE bbcode_id = ' . $bbcode_id; |
294 | $db->sql_query($sql); |
295 | $cache->destroy('sql', BBCODES_TABLE); |
296 | $phpbb_container->get('text_formatter.cache')->invalidate(); |
297 | |
298 | $lang = 'BBCODE_EDITED'; |
299 | $log_action = 'LOG_BBCODE_EDIT'; |
300 | } |
301 | |
302 | $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag'])); |
303 | |
304 | /** |
305 | * Event after a BBCode has been added or updated |
306 | * |
307 | * @event core.acp_bbcodes_modify_create_after |
308 | * @var string action Type of the action: modify|create |
309 | * @var int bbcode_id The id of the added or updated bbcode |
310 | * @var array sql_ary Array with bbcode data (read only) |
311 | * @since 3.2.4-RC1 |
312 | */ |
313 | $vars = array( |
314 | 'action', |
315 | 'bbcode_id', |
316 | 'sql_ary', |
317 | ); |
318 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create_after', compact($vars))); |
319 | |
320 | trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); |
321 | } |
322 | else |
323 | { |
324 | confirm_box(false, $user->lang['BBCODE_DANGER'], build_hidden_fields(array_merge($hidden_fields, array( |
325 | 'action' => $action, |
326 | 'bbcode' => $bbcode_id, |
327 | 'bbcode_match' => $bbcode_match, |
328 | 'bbcode_tpl' => htmlspecialchars($bbcode_tpl, ENT_COMPAT), |
329 | 'bbcode_helpline' => $bbcode_helpline, |
330 | 'display_on_posting' => $display_on_posting, |
331 | ))) |
332 | , 'confirm_bbcode.html'); |
333 | } |
334 | |
335 | break; |
336 | |
337 | case 'delete': |
338 | |
339 | $sql = 'SELECT bbcode_tag |
340 | FROM ' . BBCODES_TABLE . " |
341 | WHERE bbcode_id = $bbcode_id"; |
342 | $result = $db->sql_query($sql); |
343 | $row = $db->sql_fetchrow($result); |
344 | $db->sql_freeresult($result); |
345 | |
346 | if ($row) |
347 | { |
348 | if (confirm_box(true)) |
349 | { |
350 | $bbcode_tag = $row['bbcode_tag']; |
351 | |
352 | $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); |
353 | $cache->destroy('sql', BBCODES_TABLE); |
354 | $phpbb_container->get('text_formatter.cache')->invalidate(); |
355 | $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($bbcode_tag)); |
356 | |
357 | /** |
358 | * Event after a BBCode has been deleted |
359 | * |
360 | * @event core.acp_bbcodes_delete_after |
361 | * @var string action Type of the action: delete |
362 | * @var int bbcode_id The id of the deleted bbcode |
363 | * @var string bbcode_tag The tag of the deleted bbcode |
364 | * @since 3.2.4-RC1 |
365 | */ |
366 | $vars = array( |
367 | 'action', |
368 | 'bbcode_id', |
369 | 'bbcode_tag', |
370 | ); |
371 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_delete_after', compact($vars))); |
372 | |
373 | if ($request->is_ajax()) |
374 | { |
375 | $json_response = new \phpbb\json_response; |
376 | $json_response->send(array( |
377 | 'MESSAGE_TITLE' => $user->lang['INFORMATION'], |
378 | 'MESSAGE_TEXT' => $user->lang['BBCODE_DELETED'], |
379 | 'REFRESH_DATA' => array( |
380 | 'time' => 3 |
381 | ) |
382 | )); |
383 | } |
384 | } |
385 | else |
386 | { |
387 | confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( |
388 | 'bbcode' => $bbcode_id, |
389 | 'i' => $id, |
390 | 'mode' => $mode, |
391 | 'action' => $action)) |
392 | ); |
393 | } |
394 | } |
395 | |
396 | break; |
397 | } |
398 | |
399 | $u_action = $this->u_action; |
400 | |
401 | $template_data = array( |
402 | 'U_ACTION' => $this->u_action . '&action=add', |
403 | ); |
404 | |
405 | $sql_ary = array( |
406 | 'SELECT' => 'b.*', |
407 | 'FROM' => array(BBCODES_TABLE => 'b'), |
408 | 'ORDER_BY' => 'b.bbcode_tag', |
409 | ); |
410 | |
411 | /** |
412 | * Modify custom bbcode template data before we display the form |
413 | * |
414 | * @event core.acp_bbcodes_display_form |
415 | * @var string action Type of the action: modify|create |
416 | * @var array sql_ary The SQL array to get custom bbcode data |
417 | * @var array template_data Array with form template data |
418 | * @var string u_action The u_action link |
419 | * @since 3.1.0-a3 |
420 | */ |
421 | $vars = array('action', 'sql_ary', 'template_data', 'u_action'); |
422 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_form', compact($vars))); |
423 | |
424 | $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); |
425 | |
426 | $template->assign_vars($template_data); |
427 | |
428 | while ($row = $db->sql_fetchrow($result)) |
429 | { |
430 | $bbcodes_array = array( |
431 | 'BBCODE_TAG' => $row['bbcode_tag'], |
432 | 'U_EDIT' => $u_action . '&action=edit&bbcode=' . $row['bbcode_id'], |
433 | 'U_DELETE' => $u_action . '&action=delete&bbcode=' . $row['bbcode_id'], |
434 | ); |
435 | |
436 | /** |
437 | * Modify display of custom bbcodes in the form |
438 | * |
439 | * @event core.acp_bbcodes_display_bbcodes |
440 | * @var array row Array with current bbcode data |
441 | * @var array bbcodes_array Array of bbcodes template data |
442 | * @var string u_action The u_action link |
443 | * @since 3.1.0-a3 |
444 | */ |
445 | $vars = array('bbcodes_array', 'row', 'u_action'); |
446 | extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_bbcodes', compact($vars))); |
447 | |
448 | $template->assign_block_vars('bbcodes', $bbcodes_array); |
449 | |
450 | } |
451 | $db->sql_freeresult($result); |
452 | } |
453 | |
454 | /* |
455 | * Build regular expression for custom bbcode |
456 | */ |
457 | function build_regexp(&$bbcode_match, &$bbcode_tpl) |
458 | { |
459 | $bbcode_match = trim($bbcode_match); |
460 | $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+).*/i', '$1', $bbcode_match); |
461 | |
462 | if (!preg_match('/^[a-zA-Z0-9_-]+$/', $bbcode_tag)) |
463 | { |
464 | global $user; |
465 | trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); |
466 | } |
467 | |
468 | return array( |
469 | 'bbcode_tag' => $bbcode_tag, |
470 | 'first_pass_match' => '/(?!)/', |
471 | 'first_pass_replace' => '', |
472 | // Use a non-matching, valid regexp to effectively disable this BBCode |
473 | 'second_pass_match' => '/(?!)/', |
474 | 'second_pass_replace' => '' |
475 | ); |
476 | } |
477 | } |