[ Index ] |
PHP Cross Reference of phpBB 3.0 Beta 3 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package phpBB3 5 * @version $Id: bbcode.php,v 1.103 2006/10/07 17:40:06 acydburn Exp $ 6 * @copyright (c) 2005 phpBB Group 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 8 * 9 */ 10 11 /** 12 * BBCode class 13 * @package phpBB3 14 */ 15 class bbcode 16 { 17 var $bbcode_uid = ''; 18 var $bbcode_bitfield = ''; 19 var $bbcode_cache = array(); 20 var $bbcode_template = array(); 21 22 var $bbcodes = array(); 23 24 var $template_bitfield = 0; 25 var $template_filename = ''; 26 27 /** 28 * Constructor 29 * Init bbcode cache entries if bitfield is specified 30 */ 31 function bbcode($bitfield = '') 32 { 33 if ($bitfield) 34 { 35 $this->bbcode_bitfield = $bitfield; 36 $this->bbcode_cache_init(); 37 } 38 } 39 40 /** 41 * Second pass bbcodes 42 */ 43 function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false) 44 { 45 if ($bbcode_uid) 46 { 47 $this->bbcode_uid = $bbcode_uid; 48 } 49 50 if ($bbcode_bitfield !== false) 51 { 52 $this->bbcode_bitfield = $bbcode_bitfield; 53 54 // Init those added with a new bbcode_bitfield (already stored codes will not get parsed again) 55 $this->bbcode_cache_init(); 56 } 57 58 if (!$this->bbcode_bitfield) 59 { 60 // Remove the uid from tags that have not been transformed into HTML 61 if ($this->bbcode_uid) 62 { 63 $message = str_replace(':' . $this->bbcode_uid, '', $message); 64 } 65 66 return; 67 } 68 69 $str = array('search' => array(), 'replace' => array()); 70 $preg = array('search' => array(), 'replace' => array()); 71 72 $bitfield = new bitfield($this->bbcode_bitfield); 73 $bbcodes_set = $bitfield->get_all_set(); 74 75 foreach ($bbcodes_set as $bbcode_id) 76 { 77 if (!empty($this->bbcode_cache[$bbcode_id])) 78 { 79 foreach ($this->bbcode_cache[$bbcode_id] as $type => $array) 80 { 81 foreach ($array as $search => $replace) 82 { 83 ${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search); 84 ${$type}['replace'][] = $replace; 85 } 86 87 if (sizeof($str['search'])) 88 { 89 $message = str_replace($str['search'], $str['replace'], $message); 90 $str = array('search' => array(), 'replace' => array()); 91 } 92 93 if (sizeof($preg['search'])) 94 { 95 $message = preg_replace($preg['search'], $preg['replace'], $message); 96 $preg = array('search' => array(), 'replace' => array()); 97 } 98 } 99 } 100 } 101 102 // Remove the uid from tags that have not been transformed into HTML 103 $message = str_replace(':' . $this->bbcode_uid, '', $message); 104 } 105 106 /** 107 * Init bbcode cache 108 * 109 * requires: $this->bbcode_bitfield 110 * sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield 111 */ 112 function bbcode_cache_init() 113 { 114 global $user, $phpbb_root_path; 115 116 if (empty($this->template_filename)) 117 { 118 $this->template_bitfield = $user->theme['bbcode_bitfield']; 119 $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html'; 120 121 if (!@file_exists($this->template_filename)) 122 { 123 trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); 124 } 125 } 126 127 $bbcode_ids = $rowset = $sql = array(); 128 129 $bitfield = new bitfield($this->bbcode_bitfield); 130 $bbcodes_set = $bitfield->get_all_set(); 131 132 foreach ($bbcodes_set as $bbcode_id) 133 { 134 if (isset($this->bbcode_cache[$bbcode_id])) 135 { 136 // do not try to re-cache it if it's already in 137 continue; 138 } 139 $bbcode_ids[] = $bbcode_id; 140 141 if ($bbcode_id > NUM_CORE_BBCODES) 142 { 143 $sql[] = $bbcode_id; 144 } 145 } 146 147 if (sizeof($sql)) 148 { 149 global $db; 150 151 $sql = 'SELECT * 152 FROM ' . BBCODES_TABLE . ' 153 WHERE ' . $db->sql_in_set('bbcode_id', $sql); 154 $result = $db->sql_query($sql, 3600); 155 156 while ($row = $db->sql_fetchrow($result)) 157 { 158 // To circumvent replacing newlines with <br /> for the generated html, 159 // we just remove newlines here. We do not do this within the admin panel to 160 // let the admin lay out his html code nicely 161 $row['bbcode_tpl'] = str_replace(array("\n", "\r"), '', $row['bbcode_tpl']); 162 $row['second_pass_replace'] = str_replace(array("\n", "\r"), '', $row['second_pass_replace']); 163 164 $rowset[$row['bbcode_id']] = $row; 165 } 166 $db->sql_freeresult($result); 167 } 168 169 foreach ($bbcode_ids as $bbcode_id) 170 { 171 switch ($bbcode_id) 172 { 173 case 0: 174 $this->bbcode_cache[$bbcode_id] = array( 175 'str' => array( 176 '[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id) 177 ), 178 'preg' => array( 179 '#\[quote(?:="(.*?)")?:$uid\](.)#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')" 180 ) 181 ); 182 break; 183 184 case 1: 185 $this->bbcode_cache[$bbcode_id] = array( 186 'str' => array( 187 '[b:$uid]' => $this->bbcode_tpl('b_open', $bbcode_id), 188 '[/b:$uid]' => $this->bbcode_tpl('b_close', $bbcode_id), 189 ) 190 ); 191 break; 192 193 case 2: 194 $this->bbcode_cache[$bbcode_id] = array( 195 'str' => array( 196 '[i:$uid]' => $this->bbcode_tpl('i_open', $bbcode_id), 197 '[/i:$uid]' => $this->bbcode_tpl('i_close', $bbcode_id), 198 ) 199 ); 200 break; 201 202 case 3: 203 $this->bbcode_cache[$bbcode_id] = array( 204 'preg' => array( 205 '#\[url:$uid\]((.*?))\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id), 206 '#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id), 207 ) 208 ); 209 break; 210 211 case 4: 212 if ($user->optionget('viewimg')) 213 { 214 $this->bbcode_cache[$bbcode_id] = array( 215 'preg' => array( 216 '#\[img:$uid\](.*?)\[/img:$uid\]#s' => $this->bbcode_tpl('img', $bbcode_id), 217 ) 218 ); 219 } 220 else 221 { 222 $this->bbcode_cache[$bbcode_id] = array( 223 'preg' => array( 224 '#\[img:$uid\](.*?)\[/img:$uid\]#s' => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id)), 225 ) 226 ); 227 } 228 break; 229 230 case 5: 231 $this->bbcode_cache[$bbcode_id] = array( 232 'preg' => array( 233 '#\[size=([\-\+]?[1-2]?[0-9]):$uid\](.*?)\[/size:$uid\]#s' => $this->bbcode_tpl('size', $bbcode_id), 234 ) 235 ); 236 break; 237 238 case 6: 239 $this->bbcode_cache[$bbcode_id] = array( 240 'preg' => array( 241 '!\[color=(#[0-9a-fA-F]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!s' => $this->bbcode_tpl('color', $bbcode_id), 242 ) 243 ); 244 break; 245 246 case 7: 247 $this->bbcode_cache[$bbcode_id] = array( 248 'str' => array( 249 '[u:$uid]' => $this->bbcode_tpl('u_open', $bbcode_id), 250 '[/u:$uid]' => $this->bbcode_tpl('u_close', $bbcode_id), 251 ) 252 ); 253 break; 254 255 case 8: 256 $this->bbcode_cache[$bbcode_id] = array( 257 'preg' => array( 258 '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')", 259 ) 260 ); 261 break; 262 263 case 9: 264 $this->bbcode_cache[$bbcode_id] = array( 265 'preg' => array( 266 '#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1", 267 '#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1", 268 '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')", 269 ), 270 'str' => array( 271 '[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id), 272 '[/list:u:$uid]' => $this->bbcode_tpl('ulist_close', $bbcode_id), 273 '[/list:o:$uid]' => $this->bbcode_tpl('olist_close', $bbcode_id), 274 '[*:$uid]' => $this->bbcode_tpl('listitem', $bbcode_id), 275 '[/*:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id), 276 '[/*:m:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id) 277 ), 278 ); 279 break; 280 281 case 10: 282 $this->bbcode_cache[$bbcode_id] = array( 283 'preg' => array( 284 '#\[email:$uid\]((.*?))\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id), 285 '#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id) 286 ) 287 ); 288 break; 289 290 case 11: 291 if ($user->optionget('viewflash')) 292 { 293 $this->bbcode_cache[$bbcode_id] = array( 294 'preg' => array( 295 '#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => $this->bbcode_tpl('flash', $bbcode_id), 296 ) 297 ); 298 } 299 else 300 { 301 $this->bbcode_cache[$bbcode_id] = array( 302 'preg' => array( 303 '#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id))) 304 ) 305 ); 306 } 307 break; 308 309 case 12: 310 $this->bbcode_cache[$bbcode_id] = array( 311 'str' => array( 312 '[/attachment:$uid]' => $this->bbcode_tpl('inline_attachment_close', $bbcode_id) 313 ), 314 'preg' => array( 315 '#\[attachment=([0-9]+):$uid\]#' => $this->bbcode_tpl('inline_attachment_open', $bbcode_id) 316 ) 317 ); 318 break; 319 320 default: 321 if (!isset($template_bitfield)) 322 { 323 $template_bitfield = new bitfield($this->template_bitfield); 324 } 325 if (isset($rowset[$bbcode_id])) 326 { 327 if ($template_bitfield->get($bbcode_id)) 328 { 329 // The bbcode requires a custom template to be loaded 330 if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id)) 331 { 332 // For some reason, the required template seems not to be available, use the default template 333 $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl']; 334 } 335 else 336 { 337 // In order to use templates with custom bbcodes we need 338 // to replace all {VARS} to corresponding backreferences 339 // Note that backreferences are numbered from bbcode_match 340 if (preg_match_all('/\{(URL|EMAIL|TEXT|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m)) 341 { 342 foreach ($m[0] as $i => $tok) 343 { 344 $bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl); 345 } 346 } 347 } 348 } 349 else 350 { 351 // Default template 352 $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl']; 353 } 354 355 // Replace {L_*} lang strings 356 $bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl); 357 358 if (!empty($rowset[$bbcode_id]['second_pass_replace'])) 359 { 360 // The custom BBCode requires second-pass pattern replacements 361 $this->bbcode_cache[$bbcode_id] = array( 362 'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl) 363 ); 364 } 365 else 366 { 367 $this->bbcode_cache[$bbcode_id] = array( 368 'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl) 369 ); 370 } 371 } 372 else 373 { 374 $this->bbcode_cache[$bbcode_id] = false; 375 } 376 break; 377 } 378 } 379 } 380 381 /** 382 * Return bbcode template 383 */ 384 function bbcode_tpl($tpl_name, $bbcode_id = -1) 385 { 386 if (empty($bbcode_hardtpl)) 387 { 388 global $user; 389 static $bbcode_hardtpl = array(); 390 391 $bbcode_hardtpl = array( 392 'b_open' => '<span style="font-weight: bold">', 393 'b_close' => '</span>', 394 'i_open' => '<span style="font-style: italic">', 395 'i_close' => '</span>', 396 'u_open' => '<span style="text-decoration: underline">', 397 'u_close' => '</span>', 398 'img' => '<img src="$1" alt="' . $user->lang['IMAGE'] . '" />', 399 'size' => '<span style="font-size: $1px; line-height: normal">$2</span>', 400 'color' => '<span style="color: $1">$2</span>', 401 'email' => '<a href="mailto:$1">$2</a>' 402 ); 403 $template_bitfield = new bitfield($this->template_bitfield); 404 } 405 406 if ($bbcode_id != -1 && !$template_bitfield->get($bbcode_id)) 407 { 408 return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false; 409 } 410 411 if (empty($this->bbcode_template)) 412 { 413 if (($tpl = file_get_contents($this->template_filename)) === false) 414 { 415 trigger_error('Could not load bbcode template', E_USER_ERROR); 416 } 417 418 // replace \ with \\ and then ' with \'. 419 $tpl = str_replace('\\', '\\\\', $tpl); 420 $tpl = str_replace("'", "\'", $tpl); 421 422 // strip newlines and indent 423 $tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl); 424 425 // Turn template blocks into PHP assignment statements for the values of $bbcode_tpl.. 426 $this->bbcode_template = array(); 427 428 $matches = preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match); 429 430 for ($i = 0; $i < $matches; $i++) 431 { 432 if (empty($match[1][$i])) 433 { 434 continue; 435 } 436 437 $this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]); 438 } 439 } 440 441 return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false); 442 } 443 444 /** 445 * Return bbcode template replacement 446 */ 447 function bbcode_tpl_replace($tpl_name, $tpl) 448 { 449 global $user; 450 451 static $replacements = array( 452 'quote_username_open' => array('{USERNAME}' => '$1'), 453 'color' => array('{COLOR}' => '$1', '{TEXT}' => '$2'), 454 'size' => array('{SIZE}' => '$1', '{TEXT}' => '$2'), 455 'img' => array('{URL}' => '$1'), 456 'flash' => array('{WIDTH}' => '$1', '{HEIGHT}' => '$2', '{URL}' => '$3'), 457 'url' => array('{URL}' => '$1', '{DESCRIPTION}' => '$2'), 458 'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2') 459 ); 460 461 $tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl); 462 463 if (!empty($replacements[$tpl_name])) 464 { 465 $tpl = strtr($tpl, $replacements[$tpl_name]); 466 } 467 468 return trim($tpl); 469 } 470 471 /** 472 * Second parse list bbcode 473 */ 474 function bbcode_list($type) 475 { 476 if ($type == '') 477 { 478 $tpl = 'ulist_open_default'; 479 $type = 'default'; 480 $start = 0; 481 } 482 else if ($type == 'i') 483 { 484 $tpl = 'olist_open'; 485 $type = 'lower-roman'; 486 $start = 1; 487 } 488 else if ($type == 'I') 489 { 490 $tpl = 'olist_open'; 491 $type = 'upper-roman'; 492 $start = 1; 493 } 494 else if (preg_match('#^(disc|circle|square)$#i', $type)) 495 { 496 $tpl = 'ulist_open'; 497 $type = strtolower($type); 498 $start = 1; 499 } 500 else if (preg_match('#^[a-z]$#', $type)) 501 { 502 $tpl = 'olist_open'; 503 $type = 'lower-alpha'; 504 $start = ord($type) - 96; 505 } 506 else if (preg_match('#[A-Z]#', $type)) 507 { 508 $tpl = 'olist_open'; 509 $type = 'upper-alpha'; 510 $start = ord($type) - 64; 511 } 512 else if (is_numeric($type)) 513 { 514 $tpl = 'olist_open'; 515 $type = 'arabic-numbers'; 516 $start = intval($type); 517 } 518 else 519 { 520 $tpl = 'olist_open'; 521 $type = 'arabic-numbers'; 522 $start = 1; 523 } 524 525 return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl)); 526 } 527 528 /** 529 * Second parse quote tag 530 */ 531 function bbcode_second_pass_quote($username, $quote) 532 { 533 // when using the /e modifier, preg_replace slashes double-quotes but does not 534 // seem to slash anything else 535 $quote = str_replace('\"', '"', $quote); 536 $username = str_replace('\"', '"', $username); 537 538 // remove newline at the beginning 539 if ($quote[0] == "\n") 540 { 541 $quote = substr($quote, 1); 542 } 543 544 $quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote; 545 546 return $quote; 547 } 548 549 /** 550 * Second parse code tag 551 */ 552 function bbcode_second_pass_code($type, $code) 553 { 554 // when using the /e modifier, preg_replace slashes double-quotes but does not 555 // seem to slash anything else 556 $code = str_replace('\"', '"', $code); 557 558 switch ($type) 559 { 560 case 'php': 561 // Not the english way, but valid because of hardcoded syntax highlighting 562 if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0) 563 { 564 $code = substr($code, 41); 565 } 566 567 // no break; 568 569 default: 570 $code = str_replace("\t", ' ', $code); 571 $code = str_replace(' ', ' ', $code); 572 $code = str_replace(' ', ' ', $code); 573 574 // remove newline at the beginning 575 if (!empty($code) && $code[0] == "\n") 576 { 577 $code = substr($code, 1); 578 } 579 break; 580 } 581 582 $code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close'); 583 584 return $code; 585 } 586 } 587 588 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 22 00:35:05 2006 | Cross-referenced by PHPXref 0.6 |