source: trunk/forum/includes/acp/acp_bbcodes.php

Last change on this file was 702, checked in by george, 15 years ago
  • Upraveno: Aktualizace fóra.
File size: 14.6 KB
Line 
1<?php
2/**
3*
4* @package acp
5* @version $Id$
6* @copyright (c) 2005 phpBB Group
7* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8*
9*/
10
11/**
12* @ignore
13*/
14if (!defined('IN_PHPBB'))
15{
16 exit;
17}
18
19/**
20* @package acp
21*/
22class acp_bbcodes
23{
24 var $u_action;
25
26 function main($id, $mode)
27 {
28 global $db, $user, $auth, $template, $cache;
29 global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
30
31 $user->add_lang('acp/posting');
32
33 // Set up general vars
34 $action = request_var('action', '');
35 $bbcode_id = request_var('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']);
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_var('display_on_posting', 0);
87
88 $bbcode_match = request_var('bbcode_match', '');
89 $bbcode_tpl = htmlspecialchars_decode(utf8_normalize_nfc(request_var('bbcode_tpl', '', true)));
90 $bbcode_helpline = utf8_normalize_nfc(request_var('bbcode_helpline', '', true));
91 break;
92 }
93
94 // Do major work
95 switch ($action)
96 {
97 case 'edit':
98 case 'add':
99
100 $template->assign_vars(array(
101 'S_EDIT_BBCODE' => true,
102 'U_BACK' => $this->u_action,
103 'U_ACTION' => $this->u_action . '&amp;action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&amp;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 foreach ($user->lang['tokens'] as $token => $token_explain)
113 {
114 $template->assign_block_vars('token', array(
115 'TOKEN' => '{' . $token . '}',
116 'EXPLAIN' => $token_explain)
117 );
118 }
119
120 return;
121
122 break;
123
124 case 'modify':
125 case 'create':
126
127 $warn_text = preg_match('%<[^>]*\{text[\d]*\}[^>]*>%i', $bbcode_tpl);
128 if (!$warn_text || confirm_box(true))
129 {
130 $data = $this->build_regexp($bbcode_match, $bbcode_tpl);
131
132 // Make sure the user didn't pick a "bad" name for the BBCode tag.
133 $hard_coded = array('code', 'quote', 'quote=', 'attachment', 'attachment=', 'b', 'i', 'url', 'url=', 'img', 'size', 'size=', 'color', 'color=', 'u', 'list', 'list=', 'email', 'email=', 'flash', 'flash=');
134
135 if (($action == 'modify' && strtolower($data['bbcode_tag']) !== strtolower($row['bbcode_tag'])) || ($action == 'create'))
136 {
137 $sql = 'SELECT 1 as test
138 FROM ' . BBCODES_TABLE . "
139 WHERE LOWER(bbcode_tag) = '" . $db->sql_escape(strtolower($data['bbcode_tag'])) . "'";
140 $result = $db->sql_query($sql);
141 $info = $db->sql_fetchrow($result);
142 $db->sql_freeresult($result);
143
144 // Grab the end, interrogate the last closing tag
145 if ($info['test'] === '1' || in_array(strtolower($data['bbcode_tag']), $hard_coded) || (preg_match('#\[/([^[]*)]$#', $bbcode_match, $regs) && in_array(strtolower($regs[1]), $hard_coded)))
146 {
147 trigger_error($user->lang['BBCODE_INVALID_TAG_NAME'] . adm_back_link($this->u_action), E_USER_WARNING);
148 }
149 }
150
151 if (substr($data['bbcode_tag'], -1) === '=')
152 {
153 $test = substr($data['bbcode_tag'], 0, -1);
154 }
155 else
156 {
157 $test = $data['bbcode_tag'];
158 }
159
160 if (!preg_match('%\\[' . $test . '[^]]*].*?\\[/' . $test . ']%s', $bbcode_match))
161 {
162 trigger_error($user->lang['BBCODE_OPEN_ENDED_TAG'] . adm_back_link($this->u_action), E_USER_WARNING);
163 }
164
165 if (strlen($data['bbcode_tag']) > 16)
166 {
167 trigger_error($user->lang['BBCODE_TAG_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING);
168 }
169
170 if (strlen($bbcode_match) > 4000)
171 {
172 trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING);
173 }
174
175
176 if (strlen($bbcode_helpline) > 255)
177 {
178 trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING);
179 }
180
181 $sql_ary = array(
182 'bbcode_tag' => $data['bbcode_tag'],
183 'bbcode_match' => $bbcode_match,
184 'bbcode_tpl' => $bbcode_tpl,
185 'display_on_posting' => $display_on_posting,
186 'bbcode_helpline' => $bbcode_helpline,
187 'first_pass_match' => $data['first_pass_match'],
188 'first_pass_replace' => $data['first_pass_replace'],
189 'second_pass_match' => $data['second_pass_match'],
190 'second_pass_replace' => $data['second_pass_replace']
191 );
192
193 if ($action == 'create')
194 {
195 $sql = 'SELECT MAX(bbcode_id) as max_bbcode_id
196 FROM ' . BBCODES_TABLE;
197 $result = $db->sql_query($sql);
198 $row = $db->sql_fetchrow($result);
199 $db->sql_freeresult($result);
200
201 if ($row)
202 {
203 $bbcode_id = $row['max_bbcode_id'] + 1;
204
205 // Make sure it is greater than the core bbcode ids...
206 if ($bbcode_id <= NUM_CORE_BBCODES)
207 {
208 $bbcode_id = NUM_CORE_BBCODES + 1;
209 }
210 }
211 else
212 {
213 $bbcode_id = NUM_CORE_BBCODES + 1;
214 }
215
216 if ($bbcode_id > 1511)
217 {
218 trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING);
219 }
220
221 $sql_ary['bbcode_id'] = (int) $bbcode_id;
222
223 $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary));
224 $cache->destroy('sql', BBCODES_TABLE);
225
226 $lang = 'BBCODE_ADDED';
227 $log_action = 'LOG_BBCODE_ADD';
228 }
229 else
230 {
231 $sql = 'UPDATE ' . BBCODES_TABLE . '
232 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
233 WHERE bbcode_id = ' . $bbcode_id;
234 $db->sql_query($sql);
235 $cache->destroy('sql', BBCODES_TABLE);
236
237 $lang = 'BBCODE_EDITED';
238 $log_action = 'LOG_BBCODE_EDIT';
239 }
240
241 add_log('admin', $log_action, $data['bbcode_tag']);
242
243 trigger_error($user->lang[$lang] . adm_back_link($this->u_action));
244 }
245 else
246 {
247 confirm_box(false, $user->lang['BBCODE_DANGER'], build_hidden_fields(array(
248 'action' => $action,
249 'bbcode' => $bbcode_id,
250 'bbcode_match' => $bbcode_match,
251 'bbcode_tpl' => htmlspecialchars($bbcode_tpl),
252 'bbcode_helpline' => $bbcode_helpline,
253 'display_on_posting' => $display_on_posting,
254 ))
255 , 'confirm_bbcode.html');
256 }
257
258 break;
259
260 case 'delete':
261
262 $sql = 'SELECT bbcode_tag
263 FROM ' . BBCODES_TABLE . "
264 WHERE bbcode_id = $bbcode_id";
265 $result = $db->sql_query($sql);
266 $row = $db->sql_fetchrow($result);
267 $db->sql_freeresult($result);
268
269 if ($row)
270 {
271 if (confirm_box(true))
272 {
273 $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");
274 $cache->destroy('sql', BBCODES_TABLE);
275 add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']);
276 }
277 else
278 {
279 confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
280 'bbcode' => $bbcode_id,
281 'i' => $id,
282 'mode' => $mode,
283 'action' => $action))
284 );
285 }
286 }
287
288 break;
289 }
290
291 $template->assign_vars(array(
292 'U_ACTION' => $this->u_action . '&amp;action=add')
293 );
294
295 $sql = 'SELECT *
296 FROM ' . BBCODES_TABLE . '
297 ORDER BY bbcode_tag';
298 $result = $db->sql_query($sql);
299
300 while ($row = $db->sql_fetchrow($result))
301 {
302 $template->assign_block_vars('bbcodes', array(
303 'BBCODE_TAG' => $row['bbcode_tag'],
304 'U_EDIT' => $this->u_action . '&amp;action=edit&amp;bbcode=' . $row['bbcode_id'],
305 'U_DELETE' => $this->u_action . '&amp;action=delete&amp;bbcode=' . $row['bbcode_id'])
306 );
307 }
308 $db->sql_freeresult($result);
309 }
310
311 /*
312 * Build regular expression for custom bbcode
313 */
314 function build_regexp(&$bbcode_match, &$bbcode_tpl)
315 {
316 $bbcode_match = trim($bbcode_match);
317 $bbcode_tpl = trim($bbcode_tpl);
318 $utf8 = strpos($bbcode_match, 'INTTEXT') !== false;
319
320 // make sure we have utf8 support
321 $utf8_pcre_properties = false;
322 if (version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>=')))
323 {
324 // While this is the proper range of PHP versions, PHP may not be linked with the bundled PCRE lib and instead with an older version
325 if (@preg_match('/\p{L}/u', 'a') !== false)
326 {
327 $utf8_pcre_properties = true;
328 }
329 }
330
331 $fp_match = preg_quote($bbcode_match, '!');
332 $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match);
333 $fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1:$uid]', $fp_replace);
334
335 $sp_match = preg_quote($bbcode_match, '!');
336 $sp_match = preg_replace('#^\\\\\[(.*?)\\\\\]#', '\[$1:$uid\]', $sp_match);
337 $sp_match = preg_replace('#\\\\\[/(.*?)\\\\\]$#', '\[/$1:$uid\]', $sp_match);
338 $sp_replace = $bbcode_tpl;
339
340 // @todo Make sure to change this too if something changed in message parsing
341 $tokens = array(
342 'URL' => array(
343 '!(?:(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))!ie' => "\$this->bbcode_specialchars(('\$1') ? '\$1' : 'http://\$2')"
344 ),
345 'LOCAL_URL' => array(
346 '!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')"
347 ),
348 'EMAIL' => array(
349 '!(' . get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')"
350 ),
351 'TEXT' => array(
352 '!(.*?)!es' => "str_replace(array(\"\\r\\n\", '\\\"', '\\'', '(', ')'), array(\"\\n\", '\"', '&#39;', '&#40;', '&#41;'), trim('\$1'))"
353 ),
354 'SIMPLETEXT' => array(
355 '!([a-zA-Z0-9-+.,_ ]+)!' => "$1"
356 ),
357 'INTTEXT' => array(
358 ($utf8_pcre_properties) ? '!([\p{L}\p{N}\-+,_. ]+)!u' : '!([a-zA-Z0-9\-+,_. ]+)!u' => "$1"
359 ),
360 'IDENTIFIER' => array(
361 '!([a-zA-Z0-9-_]+)!' => "$1"
362 ),
363 'COLOR' => array(
364 '!([a-z]+|#[0-9abcdef]+)!i' => '$1'
365 ),
366 'NUMBER' => array(
367 '!([0-9]+)!' => '$1'
368 )
369 );
370
371 $sp_tokens = array(
372 'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))(?-i)',
373 'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)',
374 'EMAIL' => '(' . get_preg_expression('email') . ')',
375 'TEXT' => '(.*?)',
376 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)',
377 'INTTEXT' => ($utf8_pcre_properties) ? '([\p{L}\p{N}\-+,_. ]+)' : '([a-zA-Z0-9\-+,_. ]+)',
378 'IDENTIFIER' => '([a-zA-Z0-9-_]+)',
379 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)',
380 'NUMBER' => '([0-9]+)',
381 );
382
383 $pad = 0;
384 $modifiers = 'i';
385 $modifiers .= ($utf8 && $utf8_pcre_properties) ? 'u' : '';
386
387 if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m))
388 {
389 foreach ($m[0] as $n => $token)
390 {
391 $token_type = $m[1][$n];
392
393 reset($tokens[strtoupper($token_type)]);
394 list($match, $replace) = each($tokens[strtoupper($token_type)]);
395
396 // Pad backreference numbers from tokens
397 if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad))
398 {
399 $repad = $pad + sizeof(array_unique($repad[0]));
400 $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace);
401 $pad = $repad;
402 }
403
404 // Obtain pattern modifiers to use and alter the regex accordingly
405 $regex = preg_replace('/!(.*)!([a-z]*)/', '$1', $match);
406 $regex_modifiers = preg_replace('/!(.*)!([a-z]*)/', '$2', $match);
407
408 for ($i = 0, $size = strlen($regex_modifiers); $i < $size; ++$i)
409 {
410 if (strpos($modifiers, $regex_modifiers[$i]) === false)
411 {
412 $modifiers .= $regex_modifiers[$i];
413
414 if ($regex_modifiers[$i] == 'e')
415 {
416 $fp_replace = "'" . str_replace("'", "\\'", $fp_replace) . "'";
417 }
418 }
419
420 if ($regex_modifiers[$i] == 'e')
421 {
422 $replace = "'.$replace.'";
423 }
424 }
425
426 $fp_match = str_replace(preg_quote($token, '!'), $regex, $fp_match);
427 $fp_replace = str_replace($token, $replace, $fp_replace);
428
429 $sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match);
430 $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace);
431 }
432
433 $fp_match = '!' . $fp_match . '!' . $modifiers;
434 $sp_match = '!' . $sp_match . '!s' . (($utf8) ? 'u' : '');
435
436 if (strpos($fp_match, 'e') !== false)
437 {
438 $fp_replace = str_replace("'.'", '', $fp_replace);
439 $fp_replace = str_replace(".''.", '.', $fp_replace);
440 }
441 }
442 else
443 {
444 // No replacement is present, no need for a second-pass pattern replacement
445 // A simple str_replace will suffice
446 $fp_match = '!' . $fp_match . '!' . $modifiers;
447 $sp_match = $fp_replace;
448 $sp_replace = '';
449 }
450
451 // Lowercase tags
452 $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+=?).*/i', '$1', $bbcode_match);
453 $bbcode_search = preg_replace('/.*?\[([a-z0-9_-]+)=?.*/i', '$1', $bbcode_match);
454
455 if (!preg_match('/^[a-zA-Z0-9_-]+=?$/', $bbcode_tag))
456 {
457 global $user;
458 trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
459 }
460
461 $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match);
462 $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace);
463 $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match);
464 $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace);
465
466 return array(
467 'bbcode_tag' => $bbcode_tag,
468 'first_pass_match' => $fp_match,
469 'first_pass_replace' => $fp_replace,
470 'second_pass_match' => $sp_match,
471 'second_pass_replace' => $sp_replace
472 );
473 }
474}
475
476?>
Note: See TracBrowser for help on using the repository browser.