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