phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / acp / acp_bbcodes.php

History | View | Annotate | Download (14.6 kB)

1
<?php
2
/**
3
*
4
* @package acp
5
* @version $Id: acp_bbcodes.php 10984 2011-02-24 03:15:11Z git-gate $
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
*/
14
if (!defined('IN_PHPBB'))
15
{
16
        exit;
17
}
18
19
/**
20
* @package acp
21
*/
22
class 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 > BBCODE_LIMIT)
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
?>