[sources] bbcode parser

Conventional discussion only. No politics, religion and other topics that might cause conflicts.
Strictly appropriate discussions only, meaning spammers and trolls will be banned on first offense.

Moderator: Moderators

[sources] bbcode parser

Postby PostBot on Tue May 31, 2005 7:38 am

Hello,

I've decided to make sources of bbcode parser that is used on this website available. I won't be creating any mods from it, but there are lots of coders on this forum who might do something useful with it. You have full permission to do whatever you want with this code.

bbcode.php:[code file="bbcode.php"]<?php

if ( !defined('IN_PHPBB') )
{
die("Hacking attempt");
}

define("BBCODE_UID_LEN", 10);
define('BBCODE_NOSMILIES_START', '<!-- no smilies start -->');
define('BBCODE_NOSMILIES_END', '<!-- no smilies end -->');
global $current_domain_short, $board_config;
$urls_local = array(
'http://www.' . $current_domain_short . $board_config['forum_path_short'],
'http://' . $current_domain_short . $board_config['forum_path_short']
);

define('AUTOURL', time());

class BBCode {
var $text = '';
var $html = '';

var $allow_html = false;
var $allow_styling = true;
var $allow_bbcode = true;
var $allow_smilies = true;
var $is_sig = false;

var $code_counter = 0;

var $allowed_bbcode = array(
// simple tags
'b' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'i' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'u' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'strong' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'em' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'span' => array(
'nested' => true,
'inurl' => true,
),
// size
'size' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
// image
'img' => array(
'nested' => false,
'inurl' => true,
),
// color
'color' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
// urls
'url' => array(
'nested' => false,
'inurl' => false,
),
'a' => array(
'nested' => false,
'inurl' => false,
),
'email' => array(
'nested' => false,
'inurl' => false,
),
// lists
'list' => array(
'nested' => true,
'inurl' => false,
),
'ul' => array(
'nested' => true,
'inurl' => false,
),
'ol' => array(
'nested' => true,
'inurl' => false,
),
'*' => array(
'nested' => true,
'inurl' => false,
),
'li' => array(
'nested' => true,
'inurl' => false,
),
// quote
'quote' => array(
'nested' => true,
'inurl' => false,
),
// code
'code' => array(
'nested' => false,
'inurl' => false,
),
);
var $allowed_html = array(
// simple tags
'b' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'i' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'u' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'strong' => array(
'nested' => true,
'inurl' => true,
),
'allow_empty' => false,
'em' => array(
'nested' => true,
'inurl' => true,
'allow_empty' => false,
),
'span' => array(
'nested' => true,
'inurl' => true,
),
// url
'a' => array(
'nested' => false,
'inurl' => false,
),
// lists
'ul' => array(
'nested' => true,
'inurl' => false,
),
'ol' => array(
'nested' => true,
'inurl' => false,
),
'li' => array(
'nested' => true,
'inurl' => false,
),
// quote
'blockquote' => array(
'nested' => true,
'inurl' => false,
),
);

var $allowed_smilies = array(
array(
'code' => ':wink:',
'replace' => '(wink)',
),
array(
'code' => ';)',
'replace' => '(smile1)',
),
array(
'code' => ':)',
'replace' => '(smile2)',
),
);
var $replaced_smilies = array();

var $data = array();

var $tag = '';
var $params = array();

/**
* Process bbcode/html tag.
* This is the only function you would want to modify to add your own bbcode/html tags.
* Note: this bbcode parser doesn't make any differece of bbcode and html, so <b> and [b] are treated exactly same way
*/
function process_tag(&$item)
{
$tag = $item['tag'];
//echo 'process_tag(', $tag, ')<br />';
$start = substr($this->text, $item['start'], $item['start_len']);
$end = substr($this->text, $item['end'], $item['end_len']);
$content = substr($this->text, $item['start'] + $item['start_len'], $item['end'] - $item['start'] - $item['start_len']);
$error = array(
'valid' => false,
'start' => $this->process_text($start),
'end' => $this->process_text($end)
);
if(isset($item['valid']) && $item['valid'] == false)
{
return $error;
}
// check if empty item is allowed
if(!strlen($content))
{
$allow_empty = true;
if($item['is_html'] && isset($this->allowed_html[$tag]['allow_empty']) && !$this->allowed_html[$tag]['allow_empty'])
{
$allow_empty = false;
}
if(!$item['is_html'] && isset($this->allowed_bbcode[$tag]['allow_empty']) && !$this->allowed_bbcode[$tag]['allow_empty'])
{
$allow_empty = false;
}
if(!$allow_empty)
{
return array(
'valid' => true,
'html' => '',
'end' => '',
'allow_nested' => false,
);
}
}
// check if nested item is allowed
if($item['iteration'])
{
if($item['is_html'] && !$this->allowed_html[$tag]['nested'])
{
return $error;
}
if(!$item['is_html'] && !$this->allowed_bbcode[$tag]['nested'])
{
return $error;
}
}

/**
* Simple tags: B, U, I, EM, STRONG, SPAN
*/
if($tag === 'b' || $tag === 'i' || $tag === 'u' || $tag === 'em' || $tag === 'strong' || $tag === 'span')
{
$extras = $this->allow_styling ? array('style', 'class') : array();
$html = '<' . $tag . $this->add_extras($item['params'], $extras) . '>';
return array(
'valid' => true,
'start' => $html,
'end' => '</' . $tag . '>'
);
}

/**
* IMG
*/
if($tag === 'img')
{
if($this->is_sig)
{
return $error;
}
// main parameters
$params = array(
'src' => false,
'alt' => false,
);
// additional allowed parameters
$extras = $this->allow_styling ? array('width', 'height', 'border', 'style', 'class', 'title') : array('width', 'height', 'border', 'title');
// [img=blah]blah2[/img]
if(isset($item['params']['param']))
{
$params['src'] = $item['params']['param'];
$params['alt'] = $content;
}
// [img src=blah alt=blah width=123][/img]
elseif(isset($item['params']['src']))
{
$params['src'] = $item['params']['src'];
$params['alt'] = isset($item['params']['alt']) ? $item['params']['alt'] : $content;
for($i=0; $i<count($extras); $i++)
{
if(!empty($item['params'][$extras[$i]]))
{
if($extras[$i] === 'style')
{
$style = $this->valid_style($item['params']['style']);
if($style !== false)
{
$params['style'] = $style;
}
}
else
{
$params[$extras[$i]] = $item['params'][$extras[$i]];
}
}
}
}
// [img]blah[/img], [img width=blah]blah[/img]
elseif(!empty($content))
{
$params['src'] = $content;
$params['alt'] = isset($item['params']['alt']) ? $item['params']['alt'] : (isset($params['title']) ? $params['title'] : '');
for($i=0; $i<count($extras); $i++)
{
if(!empty($item['params'][$extras[$i]]))
{
if($extras[$i] === 'style')
{
$style = $this->valid_style($item['params']['style']);
if($style !== false)
{
$params['style'] = $style;
}
}
else
{
$params[$extras[$i]] = $item['params'][$extras[$i]];
}
}
}
}
// generate html
$html = '<img';
foreach($params as $var => $value)
{
$html .= ' ' . $var . '="' . $this->process_text($value) . '"';
}
if(!isset($params['title']))
{
$html .= ' title="' . $this->process_text($params['alt']) . '"';
}
$html .= ' />';
// add url
if(empty($item['inurl']))
{
$html = '<a href="' . $params['src'] . '" target="_blank" title="Click to open image in new window">' . $html . '</a>';
}
return array(
'valid' => true,
'html' => $html,
'allow_nested' => false,
);
}

/**
* LIST
*/
if($tag === 'list' || $tag === 'ul' || $tag === 'ol')
{
if($this->is_sig)
{
return $error;
}
$extras = $this->allow_styling ? array('style', 'class') : array();
// check if nested tags are all [*]
$nested_count = 0;
for($i=0; $i<count($item['items']); $i++)
{
$tag2 = $item['items'][$i]['tag'];
if($tag2 === '*' || $tag2 === 'li')
{
$nested_count ++;
}
}
if(!$nested_count)
{
// no <li> items. return error
return $error;
}
// replace "list" with html tag
if($tag === 'list')
{
if(isset($item['params']['param']) || isset($item['params']['type']))
{
$tag = 'ol';
}
else
{
$tag = 'ul';
}
}
// valid tag. process subitems to make sure there are no extra items and remove all code between elements
$last_item = false;
for($i=0; $i<count($item['items']); $i++)
{
$item2 = &$item['items'][$i];
$tag2 = $item2['tag'];
if($tag2 === '*' || $tag2 === 'li')
{
// mark as valid
$item2['list_valid'] = true;
if($last_item === false)
{
// change start position to end of [list]
$pos2 = $item2['start'] + $item2['start_len'];
$item2['start'] = $pos;
$item2['start_len'] = $pos2 - $pos;
$item2['first_entry'] = true;
}
$last_item = &$item['items'][$i];
}
}
// generate html
$html = '<' . $tag;
if(isset($item['params']['param']))
{
$html .= ' type="' . htmlspecialchars($item['params']['param']) . '"';
}
elseif(isset($item['params']['type']))
{
$html .= ' type="' . htmlspecialchars($item['params']['type']) . '"';
}
$html .= $this->add_extras($item['params'], $extras) . '>';
return array(
'valid' => true,
'start' => $html,
'end' => '</li></' . $tag . '>'
);
}

/**
* [*], LI
*/
if($tag === '*' || $tag === 'li')
{
if($this->is_sig)
{
return $error;
}
$extras = $this->allow_styling ? array('style', 'class') : array();
// if not marked as valid return error
if(empty($item['list_valid']))
{
return $error;
}
$html = '<li';
if(empty($item['first_entry']))
{
// add closing tag for previous list entry
$html = '</li>' . $html;
}
$html .= $this->add_extras($item['params'], $extras) . '>';
return array(
'valid' => true,
'start' => $html,
'end' => '',
);
}

/**
* COLOR
*/
if($tag === 'color')
{
if($this->is_sig)
{
return $error;
}
$extras = $this->allow_styling ? array('class') : array();
$color = '';
if(isset($item['params']['param']))
{
$color = $item['params']['param'];
}
elseif(isset($item['params']['color']))
{
$color = $item['params']['color'];
}
else
{
return $error;
}
$color = $this->valid_color($color);
if($color === false)
{
return $error;
}
$html = '<span style="' . ($this->allow_styling && isset($item['params']['style']) ? htmlspecialchars($this->valid_style($item['params']['style'], '')) : '') . 'color: ' . $color . ';"' . $this->add_extras($item['params'], $extras) . '>';
return array(
'valid' => true,
'start' => $html,
'end' => '</span>',
);
}

/**
* SIZE
*/
if($tag === 'size')
{
$extras = $this->allow_styling ? array('class') : array();
$size = 0;
if(isset($item['params']['param']))
{
$size = intval($item['params']['param']);
}
elseif(isset($item['params']['size']))
{
$size = intval($item['params']['size']);
}
else
{
return $error;
}
if($size > 0 && $size < 5)
{
// vBulletin-style sizes
switch($size)
{
case 1: $size = 9; break;
case 2: $size = 12; break;
case 3: $size = 15; break;
case 4: $size = 18; break;
}
}
if($size < 9 || $size > 18)
{
return $error;
}
$html = '<span style="' . ($this->allow_styling && isset($item['params']['style']) ? htmlspecialchars($this->valid_style($item['params']['style'], '')) : '') . 'font-size: ' . $size . 'px;"' . $this->add_extras($item['params'], $extras) . '>';
return array(
'valid' => true,
'start' => $html,
'end' => '</span>',
);
}

/**
* URL, A
*/
if($tag === 'url' || $tag === 'a')
{
$extras = $this->allow_styling ? array('style', 'class', 'name', 'title') : array('name', 'title');
$allow_nested = true;
$strip_text = false;
$show_content = true;
$url = '';
// get url
if(!empty($item['params']['param']))
{
$url = $item['params']['param'];
}
elseif(!empty($item['params']['href']))
{
$url = $item['params']['href'];
}
elseif(!$item['is_html'])
{
$url = $content;
$allow_nested = false;
$strip_text = true;
}
else
{
return $error;
}
if($url === $content && strlen($content) > 64)
{
$content = substr($content, 0, 35) . '...' . substr($content, strlen($content) - 15);
$show_content = false;
}
// check if its email
if(substr(strtolower($url), 0, 7) === 'mailto:')
{
$item['tag'] = 'email';
return $this->process_tag($item);
}
// check for invalid urls
$url = $this->valid_url($url, '');
if(empty($url))
{
return $error;
}
// check nested items
if(!$allow_nested)
{
for($i=0; $i<count($item['items']); $i++)
{
$item['items'][$i]['valid'] = false;
}
}
else
{
for($i=0; $i<count($item['next']); $i++)
{
$tag2 = $item['next'][$i]['tag'];
$is_html = $item['next'][$i]['item']['is_html'];
$item['next'][$i]['item']['inurl'] = true;
if($is_html && !$this->allowed_html[$tag2]['inurl'])
{
$item['next'][$i]['item']['valid'] = false;
}
if(!$is_html && !$this->allowed_bbcode[$tag2]['inurl'])
{
$item['next'][$i]['item']['valid'] = false;
}
}
}
// check for incomplete url
if(substr(strtolower($url), 0, 4) === 'www.')
{
$url = 'http://' . $url;
}
// remove extra characters at the end
$last_char = substr($url, strlen($url) - 1);
$last_char_i = ord($last_char);
if(($last_char_i > 32 && $last_char_i < 47) || ($last_char_i > 57 && $last_char_i < 65))
{
$url = substr($url, 0, strlen($url) - 1);
}
// check if url is local
$url_local = false;
global $urls_local;
for($i=0; $i<count($urls_local); $i++)
{
if(strlen($url) > strlen($urls_local[$i]) && strpos($url, $urls_local[$i]) === 0)
{
$url_local = true;
$url = substr($url, strlen($urls_local[$i]));
}
}
if(!$url_local)
{
if(strpos($url, ':') === false)
{
$url_local = true;
}
}
// generate html
$html = '<a' . ($this->allow_styling && isset($item['params']['class']) ? '' : ' class="post-url"') . ' href="' . htmlspecialchars($url) . '"' . ($url_local ? '' : ' target="_blank"') . $this->add_extras($item['params'], $extras) . '>';
if($show_content)
{
return array(
'valid' => true,
'start' => $html,
'end' => '</a>',
);
}
else
{
return array(
'valid' => true,
'html' => $html . $content . '</a>',
'allow_nested' => false,
);
}
}

/**
* EMAIL
*/
if($tag === 'email')
{
$extras = $this->allow_styling ? array('style', 'class', 'name', 'title') : array('name', 'title');
$allow_nested = true;
$strip_text = false;
$url = '';
// get url
if(!empty($item['params']['param']))
{
$url = $item['params']['param'];
}
elseif(!empty($item['params']['href']))
{
$url = $item['params']['href'];
}
elseif(!empty($item['params']['addr']))
{
$url = $item['params']['addr'];
}
else
{
$url = $content;
$pos = strpos($url, '?');
if($pos)
{
$content = substr($url, 0, $pos);
}
if(substr(strtolower($url), 0, 7) === 'mailto:')
{
$content = substr($content, 7);
}
$allow_nested = false;
$strip_text = true;
}
if(empty($url))
{
return $error;
}
// disable nested items
for($i=0; $i<count($item['items']); $i++)
{
$item['items'][$i]['valid'] = false;
}
// generate html
if(substr(strtolower($url), 0, 7) === 'mailto:')
{
$url = substr($url, 7);
}
$email = '<a' . ($this->allow_styling && isset($item['params']['class']) ? '' : ' class="post-email"') . ' href="mailto:' . htmlspecialchars($url) . '"' . $this->add_extras($item['params'], $extras) . '>' . $content . '</a>';
$pos = strpos($url, '?');
if($pos)
{
$str = substr($url, 0, $pos);
}
else
{
$str = $url;
}
$noscript = '<noscript>' . htmlspecialchars(str_replace(array('@', '.'), array(' [at] ', ' [dot] '), $str)) . '</noscript>';
// make javascript from it
$html = BBCODE_NOSMILIES_START . '<script language="JavaScript" type="text/javascript">' . "\n" . '<!--' . "\n";
for($i=0; $i<strlen($email); $i+=5)
{
$str = substr($email, $i, 5);
$html .= 'document.write(\'' . addslashes($str) . '\');' . "\n";
}
$html .= "\n" . '//-->' . "\n" . '</script>' . $noscript . BBCODE_NOSMILIES_END;
return array(
'valid' => true,
'html' => $html,
'allow_nested' => false,
);
}

/**
* QUOTE
*/
if($tag === 'quote' || $tag === 'blockquote')
{
if($this->is_sig)
{
return $error;
}
if($item['iteration'] > 1)
{
return $error;
}
// check user
$user = '';
if(isset($item['params']['param']))
{
$user = htmlspecialchars($item['params']['param']);
}
elseif(isset($item['params']['user']))
{
$user = htmlspecialchars($item['params']['user']);
if(isset($item['params']['userid']) && intval($item['params']['userid']))
{
$user = '<a href="profile.php?mode=viewprofile&[highlight][/highlight]amp;u=' . intval($item['params']['userid']) . '">' . $user . '</a>';
}
}
// generate html
$html = '<blockquote class="quote"';
if(isset($item['params']['post']) && intval($item['params']['post']))
{
$html .= ' cite="viewtopic.php?p=' . intval($item['params']['post']) . '#' . intval($item['params']['post']) . '"';
}
$html .= '>';
if($user)
{
$html .= '<div class="quote-user">' . $user . ' wrote:</div>';
}
else
{
$html .= '<div class="quote-nouser">Quote:</div>';
}
$html .= '<div class="quote-message">';
return array(
'valid' => true,
'start' => $html,
'end' => '</div></blockquote>'
);
}

/**
* CODE
*/
if($tag === 'code')
{
if($this->is_sig)
{
return $error;
}
// replace spaces and tabs with &[highlight][/highlight]nbsp;
if(!defined('EXTRACT_CODE'))
{
$search = array(
' ',
"\t"
);
$replace = array(
' &[highlight][/highlight]nbsp;',
' &[highlight][/highlight]nbsp; &[highlight][/highlight]nbsp;'
);
$text = str_replace($search, $replace, $this->process_text($content, false, true));
}
else
{
$text = $this->process_text($content, false, true);
$search = array('[[highlight][/highlight]highlight]', '[/[highlight][/highlight]highlight]');
$replace = array('', '');
$text = str_replace($search, $replace, $text);
}
// check filename
if(isset($item['params']['filename']))
{
$item['params']['file'] = $item['params']['filename'];
}
if(defined('EXTRACT_CODE') && $this->code_counter == EXTRACT_CODE)
{
$GLOBALS['code_text'] = $text;
if(!empty($item['params']['file']))
{
$GLOBALS['code_filename'] = $item['params']['file'];
}
}
if(substr($text, 0, 1) === "\n")
{
$text = substr($text, 1);
}
elseif(substr($text, 0, 2) === "\r\n")
{
$text = substr($text, 2);
}
// convert to list
$search = array("\n", '[[highlight][/highlight]highlight]', '[/[highlight][/highlight]highlight]');
$replace = array('&[highlight][/highlight]nbsp;</span></li><li class="code-row"><span class="code-row-text">', '<span class="code-row-highlight">', '</span>');
$html = '<li class="code-row code-row-first"><span class="code-row-text">' . str_replace($search, $replace, $text) . '&[highlight][/highlight]nbsp;</span></li>';
$str = '<li class="code-row"><span class="code-row-text">&[highlight][/highlight]nbsp;</span></li>';
if(substr($html, strlen($html) - strlen($str)) === $str)
{
$html = substr($html, 0, strlen($html) - strlen($str));
}
$start = isset($item['params']['start']) ? intval($item['params']['start']) : 1;
$can_download = !empty($GLOBALS['code_post_id']) ? $GLOBALS['code_post_id'] : 0;
if($can_download)
{
$download_text = ' [<a href="download.php?post=' . $can_download;
if($this->code_counter)
{
$download_text .= '&item=' . $this->code_counter;
}
$download_text .= '">download</a>]';
}
else
{
$download_text = '';
}
$code_id = substr(md5($content . mt_rand()), 0, 8);
$str = BBCODE_NOSMILIES_START . '<div class="code">';
$str .= '<div class="code-header" id="codehdr2_' . $code_id . '" style="position: relative;">Code:' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="javascript:void(0)" onclick="ShowHide(\'code_' . $code_id . '\', \'code2_' . $code_id . '\', \'\'); ShowHide(\'codehdr_' . $code_id . '\', \'codehdr2_' . $code_id . '\', \'\')">hide</a>]</div>';
$str .= '<div class="code-header" id="codehdr_' . $code_id . '" style="position: relative; display: none;">Code:' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="javascript:void(0)" onclick="ShowHide(\'code_' . $code_id . '\', \'code2_' . $code_id . '\', \'\'); ShowHide(\'codehdr_' . $code_id . '\', \'codehdr2_' . $code_id . '\', \'\')">show</a>]</div>';
$html = $str . '<div class="code-content" id="code_' . $code_id . '" style="position: relative;"><ol class="code-list" start="' . $start . '">' . $html . '</ol></div></div>' . BBCODE_NOSMILIES_END;
// check highlight
// format: highlight="1,2,3-10"
if(isset($item['params']['highlight']))
{
$search = '<li class="code-row';
$replace = '<li class="code-row code-row-highlight';
$search_len = strlen($search);
$replace_len = strlen($replace);
// get highlight string
$items = array();
$str = $item['params']['highlight'];
$list = explode(',', $str);
for($i=0; $i<count($list); $i++)
{
$str = trim($list[$i]);
if(strpos($str, '-'))
{
$row = explode('-', $str);
if(count($row) == 2)
{
$num1 = intval($row[0]);
if($num1 == 0)
{
$num1 = 1;
}
$num2 = intval($row[1]);
if($num1 > 0 && $num2 > $num1 && ($num2 - $num1) < 256)
{
for($j=$num1; $j<=$num2; $j++)
{
$items['row' . $j] = true;
}
}
}
}
else
{
$num = intval($str);
if($num)
{
$items['row' . $num] = true;
}
}
}
if(count($items))
{
// process all lines
$num = $start - 1;
$pos = strpos($html, $search);
$total = count($items);
$found = 0;
while($pos !== false)
{
$num ++;
if(isset($items['row' . $num]))
{
$found ++;
$html = substr($html, 0, $pos) . $replace . substr($html, $pos + $search_len);
$pos += $replace_len;
}
else
{
$pos += $search_len;
}
$pos = $found < $total ? strpos($html, $search, $pos) : false;
}
}
}
// $html = BBCODE_NOSMILIES_START . '<div class="code"><div class="code-header">Code:</div><div class="code-content">' . $text . '</div></div>' . BBCODE_NOSMILIES_END;
$this->code_counter ++;
return array(
'valid' => true,
'html' => $html,
'allow_nested' => false
);
}

/**
* Invalid tag
*/
return $error;
}

/**
* Check if bbcode tag is valid
*/
function valid_tag($tag, $is_html)
{
if($is_html)
{
return (isset($this->allowed_html[$tag]) && preg_match('/^[a-z]+$/', $tag)) ? true : false;
}
else
{
return (isset($this->allowed_bbcode[$tag]) && (preg_match('/^[a-z]+$/', $tag) || $tag === '*')) ? true : false;
}
}

/**
* Check if parameter name is valid
*/
function valid_param($param)
{
return preg_match('/^[a-z]+$/', $param);
}

/**
* Check if color is valid
*/
function valid_color($color)
{
$color = strtolower($color);
if(preg_match('/^[a-z]+$/', $color))
{
// text color
return $color;
}
if(substr($color, 0, 1) === '#')
{
// normal color
if(preg_match('/^[0-9a-f]+$/', substr($color, 1)))
{
if(strlen($color) == 4 || strlen($color) == 7)
{
return $color;
}
}
return false;
}
// rgb color
if(substr($color, 0, 4) === 'rgb(' && preg_match('/^rgb\([0-9]+,[0-9]+,[0-9]+\)$/', $color))
{
$colors = explode(',', substr($color, 4, strlen($color) - 5));
for($i=0; $i<3; $i++)
{
if($colors[$i] > 255)
{
return false;
}
}
return sprintf('#%02X%02X%02X', $colors[0], $colors[1], $colors[2]);
}
// color with missing #
if(preg_match('/^[0-9a-f]+$/', $color))
{
if(strlen($color) == 3 || strlen($color) == 6)
{
return '#' . $color;
}
}
return false;
}

/**
* Parse style
*/
function valid_style($style, $error = false)
{
$style = str_replace(array('\\', '"', '@'), array('','',''), $style);
$str = strtolower($style);
if(strpos($str, 'expression') !== false || strpos($str, 'javascript:') !== false || strpos($str, 'vbscript:') !== false || strpos($str, 'about:') !== false)
{
// attempt to use javascript
return $error;
}
if(strpos($str, '//') !== false)
{
// attempt to use external file
return $error;
}
if(strpos($str, '!important') !== false)
{
// attempt to completely mess up forum layout?
return $error;
}
return $style;
}

/**
* Validate url
*/
function valid_url($url, $error = '')
{
$str = strtolower($url);
if(substr($str, 0, 11) === 'javascript:')
{
// attempt to use javascript
return $error;
}
if(substr($str, 0, 9) === 'vbscript:')
{
// attempt to use vbscript
return $error;
}
if(substr($str, 0, 6) === 'about:')
{
// attempt to use about: url
return $error;
}
return $url;
}

/**
* Add extras
*/
function add_extras($params, $extras)
{
$html = '';
for($i=0; $i<count($extras); $i++)
{
if(isset($params[$extras[$i]]))
{
if($extras[$i] === 'style')
{
$style = $this->valid_style($params['style']);
if($style !== false)
{
$html .= ' style="' . htmlspecialchars($style) . '"';
}
}
else
{
$html .= ' ' . $extras[$i] . '="' . htmlspecialchars($params[$extras[$i]]) . '"';
}
}
}
return $html;
}
/**
* Splits string to tag and parameters
*/
function extract_params($tag, $is_html)
{
$this->tag = $tag;
$this->params = array();
$tag = str_replace("\t", ' ', $tag);
// get parameters
$pos_eq = strpos($tag, '=');
$pos_space = strpos($tag, ' ');
if($pos_space !== false && $pos_eq !== false && $pos_space < $pos_eq)
{
// mutiple parameters
$param_start = 0;
$param_str = substr($tag, $pos_space + 1);
$param_len = strlen($param_str);
$this->tag = strtolower(substr($tag, 0, $pos_space));
if(!$this->valid_tag($this->tag, $is_html))
{
return false;
}
while($param_start < $param_len)
{
// find entry for '='
$pos = strpos($param_str, '=', $param_start);
if($pos === false)
{
return false;
}
else
{
// get parameter name
$str = substr($param_str, $param_start, $pos - $param_start);
if(!$this->valid_param($str))
{
return false;
}
// get value
$pos++;
$quoted = false;
if(substr($param_str, $pos, 1) === '"')
{
$pos2 = strpos($param_str, '"', $pos + 1);
if($pos2 === false)
{
// invalid quote. search for space instead
$pos2 = strpos($param_str, ' ', $pos + 1);
}
else
{
$pos++;
$quoted = true;
}
}
else
{
$pos2 = strpos($param_str, ' ', $pos);
}
// end not found. counting until end of expression
if($pos2 === false)
{
$pos2 = $param_len;
}
$this->params[$str] = substr($param_str, $pos, $pos2 - $pos);
$param_start = $pos2 + 1;
if($quoted)
{
$param_start ++;
}
}
}
}
elseif($pos_eq !== false)
{
// single parameter
$str = substr($tag, $pos_eq + 1);
$this->tag = strtolower(substr($tag, 0, $pos_eq));
if(!$this->valid_tag($this->tag, $is_html))
{
return false;
}
if(strlen($str) > 1 && substr($str, 0, 1) === '"' && substr($str, strlen($str) - 1) === '"')
{
$str = substr($str, 1, strlen($str) - 2);
}
if(trim($str) !== $str)
{
return false;
}
$this->params['param'] = $str;
}
else
{
// no parameters
$this->tag = strtolower($tag);
if(!$this->valid_tag($this->tag, $is_html))
{
return false;
}
}
return true;
}

/**
* Recusive function that converts text to bbcode tree
*/
function push($start, $level, $prev_tags)
{
//echo '<b>push</b>(', $start, ', ', $level, ', (', implode(',', $prev_tags), '))<br />';
$items = array();
$pos_start_bbcode = $this->allow_bbcode ? strpos($this->text, '[', $start) : false;
$pos_start_html = $this->;allow_html ? strpos($this->text, '<', $start) : false;
while($pos_start_bbcode !== false || $pos_start_html !== false)
{
$pos_start = $pos_start_bbcode === false ? $pos_start_html : ($pos_start_html === false ? $pos_start_bbcode : min($pos_start_bbcode, $pos_start_html));
$is_html = $pos_start_html === $pos_start ? true : false;
$prev_start = $start;
// found tag. get data.
$pos_end = strpos($this->text, $is_html ? '>' : ']', $pos_start);
if($pos_end === false)
{
$tag_valid = false;
}
else
{
$code = substr($this->text, $pos_start, $pos_end - $pos_start + 1);
// check if tag is valid and get type of tag
$tag_valid = true;
$tag_closing = false;
$tag_self_closing = false;
if(strlen($code) < 3)
{
$tag_valid = false;
}
elseif(!$is_html && strpos($code, '[', 1) !== false)
{
$tag_valid = false;
}
elseif($is_html && strpos($code, '<', 1) !== false)
{
$tag_valid = false;
}
elseif(!$is_html && strpos($code, "\n") !== false)
{
$tag_valid = false;
}
elseif(substr($code, 0, 2) === ($is_html ? '</' : '[/'))
{
$tag_closing = true;
$tag = substr($code, 2, strlen($code) - 3);
}
elseif(substr($code, strlen($code) - 3) === ($is_html ? ' />' : ' /]'))
{
$tag_self_closing = true;
$tag = substr($code, 1, strlen($code) - 4);
}
else
{
$tag = substr($code, 1, strlen($code) - 2);
}
// do not process tag if it requires too much recursion
if($level > 10 && (!$tag_closing && !$tag_self_closing))
{
$tag_valid = false;
}
// special tags
if($code === '[*]')
{
$tag_self_closing = true;
}
}
if($tag_valid)
{
$start = $pos_end;
$params = array();
if(!$tag_closing)
{
if(!$this->extract_params($tag, $is_html))
{
$tag_valid = false;
}
else
{
$tag = $this->tag;
$params = $this->params;
}
}
else
{
if(strpos($tag, ' autourl=' . AUTOURL))
{
$tag = str_replace(' autourl=' . AUTOURL, '', $tag);
}
$tag = strtolower($tag);
if(!$this->valid_tag($tag, $is_html))
{
$tag_valid = false;
}
}
}
if($tag_valid)
{
if($tag_closing)
{
// check if this is correct closing tag
if(in_array($tag, $prev_tags))
{
return array(
'items' => $items,
'tag' => $tag,
'pos' => $pos_end,
'start' => $pos_start,
'len' => strlen($code)
);
}
}
elseif($tag_self_closing)
{
// found self-closing tag
$items[] = array(
'tag' => $tag,
'code' => $code,
'params' => $params,
'start' => $pos_start,
'start_len' => strlen($code),
'end' => $pos_end + 1,
'end_len' => 0,
'level' => $level + 1,
'iteration' => 0,
'self_closing' => 1,
'prev' => array(),
'next' => array(),
'is_html' => $is_html,
'items' => array()
);
}
else
{
// found correct tag. call recursive search
$result = $this->push($pos_end, $level + 1, array_merge($prev_tags, array($tag)));
if($result['tag'] === $tag)
{
// found correctly finished tag
$items[] = array(
'tag' => $tag,
'code' => $code,
'params' => $params,
'start' => $pos_start,
'start_len' => strlen($code),
'end' => $result['start'],
'end_len' => $result['len'],
'level' => $level + 1,
'iteration' => 0,
'self_closing' => 2,
'prev' => array(),
'next' => array(),
'is_html' => $is_html,
'items' => $result['items']
);
$start = $result['pos'];
}
else
{
$items = array_merge($items, $result['items']);
return array(
'items' => $items,
'tag' => $result['tag'],
'pos' => $result['pos'],
'start' => $result['start'],
'len' => $result['len']
);
}
}
}
else
{
$start = $pos_start + 1;
}
$pos_start_bbcode = $this->allow_bbcode ? strpos($this->text, '[', $start) : false;
$pos_start_html = $this->allow_html ? strpos($this->text, '<', $start) : false;
}
return array(
'items' => $items,
'tag' => false,
);
}

/**
* Debug fuction. Prints tree of bbcode
*/
function debug($items)
{
for($i=0; $i<count($items); $i++)
{
$item = $items[$i];
if($item['tag'])
{
for($j=0; $j<$item['level']; $j++)
{
echo '-';
}
echo ' ', $item['tag'], ' (';
$first = true;
foreach($item['params'] as $var => $value)
{
if(!$first) echo ', ';
$first = false;
echo $var, '="', htmlspecialchars($value), '"';
}
echo ")<br />\n";
$this->debug($item['items']);
}
}
}

/**
* Post-processing. Adds previous/next items to every item.
*/
function add_pointers(&$items, $prev_tags)
{
$tags = array();
for($i=0; $i<count($items); $i++)
{
$item = &$items[$i];
$tags[] = array(
'tag' => $item['tag'],
'item' => &$items[$i]
);
$iterations = 0;
for($j=0; $j<count($prev_tags); $j++)
{
if($prev_tags[$j]['tag'] === $item['tag'])
{
$iterations++;
}
}
$item['iteration'] = $iterations;
$item['prev'] = $prev_tags;
// todo: check if subitems are allowed
// parse sub-items
if(count($item['items']))
{
$arr = array(
'tag' => $item['tag'],
'item' => &$items[$i]
);
$item['next'] = $this->add_pointers($item['items'], array_merge($prev_tags, array($arr)));
$tags = array_merge($tags, $item['next']);
}
}
return $tags;
}

/**
* Process text
*/
function process_text($text, $br = true, $chars = true)
{
$search = array(
'[url autourl=' . AUTOURL . ']',
'[/url autourl=' . AUTOURL .']',
'[email autourl=' . AUTOURL . ']',
'[/email autourl=' . AUTOURL .']'
);
$replace = array('','','','');
$text = str_replace($search, $replace, $text);
if($chars)
{
$text = htmlspecialchars($text);
$text = str_replace('&[highlight][/highlight]amp;#', '&[highlight][/highlight]#', $text);
}
else
{
$text = str_replace(
array('&[highlight][/highlight]amp;', '>', '<', '"', '&[highlight][/highlight]amp;#'),
array('&[highlight][/highlight]amp;amp;', '&[highlight][/highlight]gt;', '&[highlight][/highlight]lt;', '&[highlight][/highlight]quot;', '&[highlight][/highlight]#'),
$text);
}
if($br)
{
$text = str_replace("\n", "<br />\n", $text);
}
return $text;
}

/**
* Process tree
*/
function process($start, $end, &$items)
{
$html = '';
for($i=0; $i<count($items); $i++)
{
$item = &$items[$i];
// check code before item
if($item['start'] > $start)
{
$html .= $this->process_text(substr($this->text, $start, $item['start'] - $start));
}
// process tag
$result = $this->process_tag($item);
if($result['valid'] && !isset($result['html']))
{
$html .= $result['start'];
if(!isset($result['allow_nested']) || $result['allow_nested'])
{
// process code inside tag
$html .= $this->process($item['start'] + $item['start_len'], $item['end'], $item['items']);
}
$html .= $result['end'];
}
elseif($result['valid'])
{
$html .= $result['html'];
}
else
{
// invalid tag. show html code for it and process nested tags
$item['valid'] = false;
if($item['start_len'])
{
$html .= $this->process_text(substr($this->text, $item['start'], $item['start_len']));
}
$html .= $this->process($item['start'] + $item['start_len'], $item['end'], $item['items']);
if($item['end_len'])
{
$html .= $this->process_text(substr($this->text, $item['end'], $item['end_len']));
}
}
$start = $item['end'] + $item['end_len'];
}
// process code after item
if($start < $end)
{
$html .= $this->process_text(substr($this->text, $start, $end - $start));
}
return $html;
}

/**
* Prepare smilies list
*/
function prepare_smilies()
{
if(!$this->allow_smilies)
{
return;
}
$this->replaced_smilies = array();
for($i=0; $i<count($this->allowed_smilies); $i++)
{
if(strpos($this->text, $this->allowed_smilies[$i]['code']) !== false)
{
$this->replaced_smilies[] = $this->allowed_smilies[$i];
}
}
}

/**
* Process smilies
*/
function process_smilies()
{
$valid_chars_prev = array('', ' ', "\n", "\r", "\t", '>');
$valid_chars_next = array('', ' ', "\n", "\r", "\t", '<');
if(!$this->allow_smilies && !count($this->replaced_smilies))
{
return;
}
for($i=0; $i<count($this->replaced_smilies); $i++)
{
$code = $this->replaced_smilies[$i]['code'];
$text = $this->replaced_smilies[$i]['replace'];
$code_len = strlen($code);
$text_len = strlen($text);
$pos = strpos($this->html, $code);
while($pos !== false)
{
$valid = false;
// check previous character
$prev_char = $pos > 0 ? substr($this->html, $pos - 1, 1) : '';
if(in_array($prev_char, $valid_chars_prev))
{
// check next character
$next_char = substr($this->html, $pos + $code_len, 1);
if(in_array($next_char, $valid_chars_next))
{
// make sure we aren't inside html code
$pos1 = strpos($this->html, '<', $pos + $code_len);
$pos2 = strpos($this->html, '>', $pos + $code_len);
if($pos2 === false || ($pos1 && $pos1 < $pos2))
{
// make sure we aren't inside nosmilies zone
$pos1 = strpos($this->html, BBCODE_NOSMILIES_START, $pos + $code_len);
$pos2 = strpos($this->html, BBCODE_NOSMILIES_END, $pos + $code_len);
if($pos2 === false || ($pos1 && $pos1 < $pos2))
{
$valid = true;
}
}
}
}
if($valid)
{
$this->html = substr($this->html, 0, $pos) . $text . substr($this->html, $pos + $code_len);
$pos += $text_len;
}
else
{
$pos ++;
}
$pos = strpos($this->html, $code, $pos);
}
}
}

/**
* Make urls clickable
*/
function process_urls()
{
// characters allowed in email
$chars = array();
for($i=224; $i<256; $i++)
{
if($i != 247)
{
$chars .= chr($i);
}
}
// search and replace arrays
$search = array(
"/([\s>])((https?|ftp):\/\/|www\.)([^ \r\n\(\)\^\$!`\"'\|\[\]\{\}<>]+)/si",
"/([\s>])([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9\-{$chars}]+(\.[a-zA-Z0-9\-{$chars}]+)*(\.[a-zA-Z]{2,}))/si",
);
$replace = array(
"\\1[url autourl=" . AUTOURL . "]\\2\\4[/url autourl=" . AUTOURL . "]",
"\\1[email autourl=" . AUTOURL . "]\\2[/email autourl=" . AUTOURL . "]",
);
$this->text = preg_replace($search, $replace, ' ' . $this->text . ' ');
$this->text = substr($this->text, 1, strlen($this->text) - 2);
}

/**
* Converts text to html code
*/
function parse($text, $id = false)
{
if(defined('IN_PHPBB'))
{
$search = array(
$id ? ':' . $id : '',
'code:1]',
'list:o]',
);
$replace = array(
'',
'code]',
'list]',
);
$text = str_replace($search, $replace, $text);
if($id)
{
$text = undo_htmlspecialchars($text);
}
}
// reset variables
$this->text = $text;
$this->data = array();
$this->html = '';
$this->prepare_smilies();
$this->process_urls();
$this->code_counter = 0;
// if bbcode and html are disabled then return unprocessed text
if(!$this->allow_bbcode && !$this->allow_html)
{
$this->html = $this->text;
$this->process_smilies();
return $this->html;
}
// convert to tree structure
$result = $this->push(0, 0, array());
$this->data = $result['items'];
/*
ob_start();
$this->debug($this->data);
$str = ob_get_contents();
ob_end_clean();
$this->html = 'Debug:<br />' . $str;
return $this->html;
*/
// add prev/next pointers and count iterations
$this->add_pointers($this->data, array());
// convert to html
$this->html = $this->process(0, strlen($this->text), $this->data);
$this->process_smilies();

return $this->html;
}

}

$bbcode = new BBCode();


// Need to initialize the random numbers only ONCE
mt_srand( (double) microtime() * 1000000);

function make_bbcode_uid()
{
// Unique ID for this message..

$uid = md5(mt_rand());
$uid = substr($uid, 0, BBCODE_UID_LEN);

return $uid;
}

$sql = "SELECT * FROM phpbb_smilies";
if(($result = $db->sql_query($sql)) !== false)
{
$smilies = $db->sql_fetchrowset($result);
$bbcode->allowed_smilies = array();
for($i=0; $i<count($smilies); $i++)
{
$arr = array(
'code' => $smilies[$i]['code'],
'replace' => '<img src="images/smiles/' . $smilies[$i]['smile_url'] . '" alt="' . htmlspecialchars($smilies[$i]['emotion']) . '" />'
);
$bbcode->allowed_smilies[] = $arr;
}
}

function undo_htmlspecialchars($input, $full_undo = false)
{
if($full_undo)
{
$input = str_replace('&[highlight][/highlight]nbsp;', '', $input);
}
$input = preg_replace("/&[highlight][/highlight]gt;/i", ">", $input);
$input = preg_replace("/&[highlight][/highlight]lt;/i", "<", $input);
$input = preg_replace("/&[highlight][/highlight]quot;/i", "\"", $input);
$input = preg_replace("/&[highlight][/highlight]amp;/i", "&", $input);

if($full_undo)
{
if(preg_match_all('/&\#([0-9]+);/', $input, $matches) && count($matches))
{
$list = array();
for($i=0; $i<count($matches[1]); $i++)
{
$list[$matches[1][$i]] = true;
}
$search = array();
$replace = array();
foreach($list as $var => $value)
{
$search[] = '&[highlight][/highlight]#' . $var . ';';
$replace[] = chr($var);
}
$input = str_replace($search, $replace, $input);
}
}

return $input;
}


?>[/code]
Do NOT pm me, I don't visit this forum anymore, don't own it, don't provide any support and don't moderate.
User avatar
PostBot
Moderator
Moderator
 
Posts: 10659
Joined: Sat Aug 02, 2003 3:52 pm
Location: Mars

Postby PostBot on Tue May 31, 2005 7:38 am

and here is viewtopic.php:
[code file="viewtopic.php"]<?php
/***************************************************************************
* viewtopic.php
* -------------------
* begin : Saturday, Feb 13, 2001
* copyright : (C) 2001 The phpBB Group
* email : support@phpbb.com
*
* $Id: viewtopic.php,v 1.186.2.35 2004/03/13 15:08:23 acydburn Exp $
*
*
***************************************************************************/

/***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/

define('IN_PHPBB', true);
define('IN_TOPIC', true);
$phpbb_root_path = './';
include($phpbb_root_path . 'extension.inc');
include($phpbb_root_path . 'common.'.$phpEx);
include($phpbb_root_path . 'includes/bbcode.'.$phpEx);

//
// Start initial var setup
//
$topic_id = $post_id = 0;
if ( isset($HTTP_GET_VARS[POST_TOPIC_URL]) )
{
$topic_id = intval($HTTP_GET_VARS[POST_TOPIC_URL]);
}
else if ( isset($HTTP_GET_VARS['topic']) )
{
$topic_id = intval($HTTP_GET_VARS['topic']);
}

if ( isset($HTTP_GET_VARS[POST_POST_URL]))
{
$post_id = intval($HTTP_GET_VARS[POST_POST_URL]);
}


$start = ( isset($HTTP_GET_VARS['start']) ) ? intval($HTTP_GET_VARS['start']) : 0;

if ( !isset($topic_id) && !isset($post_id) )
{
message_die(GENERAL_MESSAGE, 'Topic_post_not_exist');
}

//
// Find topic id if user requested a newer
// or older topic
//
if ( isset($HTTP_GET_VARS['view']) && empty($HTTP_GET_VARS[POST_POST_URL]) )
{
if ( $HTTP_GET_VARS['view'] == 'newest' )
{
if ( isset($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_sid']) || isset($HTTP_GET_VARS['sid']) )
{
$session_id = isset($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_sid']) ? $HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_sid'] : $HTTP_GET_VARS['sid'];
if (!preg_match('/^[A-Za-z0-9]*$/', $session_id))
{
$session_id = '';
}

if ( $session_id )
{
$sql = "SELECT p.post_id
FROM " . POSTS_TABLE . " p, " . SESSIONS_TABLE . " s, " . USERS_TABLE . " u
WHERE s.session_id = '$session_id'
AND u.user_id = s.session_user_id
AND p.topic_id = $topic_id
AND p.post_time >= u.user_lastvisit
ORDER BY p.post_time ASC
LIMIT 1";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Could not obtain newer/older topic information', '', __LINE__, __FILE__, $sql);
}

if ( !($row = $db->sql_fetchrow($result)) )
{
message_die(GENERAL_MESSAGE, 'No_new_posts_last_visit');
}

$post_id = $row['post_id'];

if (isset($HTTP_GET_VARS['sid']))
{
redirect("viewtopic.$phpEx?sid=$session_id&" . POST_POST_URL . "=$post_id#$post_id");
}
else
{
redirect("viewtopic.$phpEx?" . POST_POST_URL . "=$post_id#$post_id");
}
}
}

redirect(append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id", true));
}
else if ( $HTTP_GET_VARS['view'] == 'next' || $HTTP_GET_VARS['view'] == 'previous' )
{
$sql_condition = ( $HTTP_GET_VARS['view'] == 'next' ) ? '>' : '<';
$sql_ordering = ( $HTTP_GET_VARS['view'] == 'next' ) ? 'ASC' : 'DESC';

$sql = "SELECT t.topic_id
FROM " . TOPICS_TABLE . " t, " . TOPICS_TABLE . " t2
WHERE
t2.topic_id = $topic_id
AND t.forum_id = t2.forum_id
AND t.topic_last_post_id $sql_condition t2.topic_last_post_id
ORDER BY t.topic_last_post_id $sql_ordering
LIMIT 1";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain newer/older topic information", '', __LINE__, __FILE__, $sql);
}

if ( $row = $db->sql_fetchrow($result) )
{
$topic_id = intval($row['topic_id']);
}
else
{
$message = ( $HTTP_GET_VARS['view'] == 'next' ) ? 'No_newer_topics' : 'No_older_topics';
message_die(GENERAL_MESSAGE, $message);
}
}
}

//
// This rather complex gaggle of code handles querying for topics but
// also allows for direct linking to a post (and the calculation of which
// page the post is on and the correct display of viewtopic)
//
$join_sql_table = ( empty($post_id) ) ? '' : ", " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2 ";
$join_sql = ( empty($post_id) ) ? "t.topic_id = $topic_id" : "p.post_id = $post_id AND t.topic_id = p.topic_id AND p2.topic_id = p.topic_id AND p2.post_id <= $post_id";
$count_sql = ( empty($post_id) ) ? '' : ", COUNT(p2.post_id) AS prev_posts";

$order_sql = ( empty($post_id) ) ? '' : "GROUP BY p.post_id, t.topic_id, t.topic_title, t.topic_status, t.topic_replies, t.topic_time, t.topic_type, t.topic_vote, t.topic_last_post_id, f.forum_name, f.forum_status, f.forum_id, f.auth_view, f.auth_read, f.auth_post, f.auth_reply, f.auth_edit, f.auth_delete, f.auth_sticky, f.auth_announce, f.auth_pollcreate, f.auth_vote, f.auth_attachments ORDER BY p.post_id ASC";

$sql = "SELECT t.topic_id, t.topic_title, t.topic_status, t.topic_replies, t.topic_time, t.topic_type, t.topic_vote, t.topic_last_post_id, f.forum_name, f.forum_status, f.forum_id, f.auth_view, f.auth_read, f.auth_post, f.auth_reply, f.auth_edit, f.auth_delete, f.auth_sticky, f.auth_announce, f.auth_pollcreate, f.auth_vote, f.auth_attachments" . $count_sql . "
FROM " . TOPICS_TABLE . " t, " . FORUMS_TABLE . " f" . $join_sql_table . "
WHERE $join_sql
AND f.forum_id = t.forum_id
$order_sql";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain topic information", '', __LINE__, __FILE__, $sql);
}

if ( !($forum_topic_data = $db->sql_fetchrow($result)) )
{
message_die(GENERAL_MESSAGE, 'Topic_post_not_exist');
}

$forum_id = intval($forum_topic_data['forum_id']);

//
// Start session management
//
$userdata = session_pagestart($user_ip, $forum_id);
init_userprefs($userdata);
//
// End session management
//

//
// Start auth check
//
$is_auth = array();
$is_auth = auth(AUTH_ALL, $forum_id, $userdata, $forum_topic_data);

if( !$is_auth['auth_view'] || !$is_auth['auth_read'] )
{
if ( !$userdata['session_logged_in'] )
{
$redirect = ( isset($post_id) ) ? POST_POST_URL . "=$post_id" : POST_TOPIC_URL . "=$topic_id";
$redirect .= ( isset($start) ) ? "&start=$start" : '';
redirect(append_sid("login.$phpEx?redirect=viewtopic.$phpEx&$redirect", true));
}

$message = ( !$is_auth['auth_view'] ) ? $lang['Topic_post_not_exist'] : sprintf($lang['Sorry_auth_read'], $is_auth['auth_read_type']);

message_die(GENERAL_MESSAGE, $message);
}
//
// End auth check
//

$forum_name = $forum_topic_data['forum_name'];
$topic_title = $forum_topic_data['topic_title'];
$topic_id = intval($forum_topic_data['topic_id']);
$topic_time = $forum_topic_data['topic_time'];

if ( !empty($post_id) )
{
$start = floor(($forum_topic_data['prev_posts'] - 1) / intval($board_config['posts_per_page'])) * intval($board_config['posts_per_page']);
}

//
// Is user watching this thread?
//
if( $userdata['session_logged_in'] )
{
$can_watch_topic = TRUE;

$sql = "SELECT notify_status
FROM " . TOPICS_WATCH_TABLE . "
WHERE topic_id = $topic_id
AND user_id = " . $userdata['user_id'];
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain topic watch information", '', __LINE__, __FILE__, $sql);
}

if ( $row = $db->sql_fetchrow($result) )
{
if ( isset($HTTP_GET_VARS['unwatch']) )
{
if ( $HTTP_GET_VARS['unwatch'] == 'topic' )
{
$is_watching_topic = 0;

$sql_priority = (SQL_LAYER == "mysql") ? "LOW_PRIORITY" : '';
$sql = "DELETE $sql_priority FROM " . TOPICS_WATCH_TABLE . "
WHERE topic_id = $topic_id
AND user_id = " . $userdata['user_id'];
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not delete topic watch information", '', __LINE__, __FILE__, $sql);
}
}

$template->assign_vars(array(
'META' => '<meta http-equiv="refresh" content="3;url=' . append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;start=$start") . '">')
);

$message = $lang['No_longer_watching'] . '<br /><br />' . sprintf($lang['Click_return_topic'], '<a href="' . append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;start=$start") . '">', '</a>');
message_die(GENERAL_MESSAGE, $message);
}
else
{
$is_watching_topic = TRUE;

if ( $row['notify_status'] )
{
$sql_priority = (SQL_LAYER == "mysql") ? "LOW_PRIORITY" : '';
$sql = "UPDATE $sql_priority " . TOPICS_WATCH_TABLE . "
SET notify_status = 0
WHERE topic_id = $topic_id
AND user_id = " . $userdata['user_id'];
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not update topic watch information", '', __LINE__, __FILE__, $sql);
}
}
}
}
else
{
if ( isset($HTTP_GET_VARS['watch']) )
{
if ( $HTTP_GET_VARS['watch'] == 'topic' )
{
$is_watching_topic = TRUE;

$sql_priority = (SQL_LAYER == "mysql") ? "LOW_PRIORITY" : '';
$sql = "INSERT $sql_priority INTO " . TOPICS_WATCH_TABLE . " (user_id, topic_id, notify_status)
VALUES (" . $userdata['user_id'] . ", $topic_id, 0)";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not insert topic watch information", '', __LINE__, __FILE__, $sql);
}
}

$template->assign_vars(array(
'META' => '<meta http-equiv="refresh" content="3;url=' . append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;start=$start") . '">')
);

$message = $lang['You_are_watching'] . '<br /><br />' . sprintf($lang['Click_return_topic'], '<a href="' . append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;start=$start") . '">', '</a>');
message_die(GENERAL_MESSAGE, $message);
}
else
{
$is_watching_topic = 0;
}
}
}
else
{
if ( isset($HTTP_GET_VARS['unwatch']) )
{
if ( $HTTP_GET_VARS['unwatch'] == 'topic' )
{
redirect(append_sid("login.$phpEx?redirect=viewtopic.$phpEx&" . POST_TOPIC_URL . "=$topic_id&unwatch=topic", true));
}
}
else
{
$can_watch_topic = 0;
$is_watching_topic = 0;
}
}

//
// Generate a 'Show posts in previous x days' select box. If the postdays var is POSTed
// then get it's value, find the number of topics with dates newer than it (to properly
// handle pagination) and alter the main query
//
$previous_days = array(0, 1, 7, 14, 30, 90, 180, 364);
$previous_days_text = array($lang['All_Posts'], $lang['1_Day'], $lang['7_Days'], $lang['2_Weeks'], $lang['1_Month'], $lang['3_Months'], $lang['6_Months'], $lang['1_Year']);

if( !empty($HTTP_POST_VARS['postdays']) || !empty($HTTP_GET_VARS['postdays']) )
{
$post_days = ( !empty($HTTP_POST_VARS['postdays']) ) ? intval($HTTP_POST_VARS['postdays']) : intval($HTTP_GET_VARS['postdays']);
$min_post_time = time() - (intval($post_days) * 86400);

$sql = "SELECT COUNT(p.post_id) AS num_posts
FROM " . TOPICS_TABLE . " t, " . POSTS_TABLE . " p
WHERE t.topic_id = $topic_id
AND p.topic_id = t.topic_id
AND p.post_time >= $min_post_time";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain limited topics count information", '', __LINE__, __FILE__, $sql);
}

$total_replies = ( $row = $db->sql_fetchrow($result) ) ? intval($row['num_posts']) : 0;

$limit_posts_time = "AND p.post_time >= $min_post_time ";

if ( !empty($HTTP_POST_VARS['postdays']))
{
$start = 0;
}
}
else
{
$total_replies = intval($forum_topic_data['topic_replies']) + 1;

$limit_posts_time = '';
$post_days = 0;
}

$select_post_days = '<select name="postdays">';
for($i = 0; $i < count($previous_days); $i++)
{
$selected = ($post_days == $previous_days[$i]) ? ' selected="selected"' : '';
$select_post_days .= '<option value="' . $previous_days[$i] . '"' . $selected . '>' . $previous_days_text[$i] . '</option>';
}
$select_post_days .= '</select>';

//
// Decide how to order the post display
//
if ( !empty($HTTP_POST_VARS['postorder']) || !empty($HTTP_GET_VARS['postorder']) )
{
$post_order = (!empty($HTTP_POST_VARS['postorder'])) ? htmlspecialchars($HTTP_POST_VARS['postorder']) : htmlspecialchars($HTTP_GET_VARS['postorder']);
$post_time_order = ($post_order == "asc") ? "ASC" : "DESC";
}
else
{
$post_order = 'asc';
$post_time_order = 'ASC';
}

$select_post_order = '<select name="postorder">';
if ( $post_time_order == 'ASC' )
{
$select_post_order .= '<option value="asc" selected="selected">' . $lang['Oldest_First'] . '</option><option value="desc">' . $lang['Newest_First'] . '</option>';
}
else
{
$select_post_order .= '<option value="asc">' . $lang['Oldest_First'] . '</option><option value="desc" selected="selected">' . $lang['Newest_First'] . '</option>';
}
$select_post_order .= '</select>';

$user_ids = array();
$user_ids2 = array();
if($userdata['session_logged_in'])
{
$user_ids[$userdata['user_id']] = $userdata['username'];
}

//
// Go ahead and pull all data for this topic
//
$sql = "SELECT u.username, u.user_id, u.user_posts, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_regdate, u.user_msnm, u.user_viewemail, u.user_rank, u.user_sig, u.user_sig_bbcode_uid, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allowsmile, p.*, pt.post_text, pt.post_text_compiled, pt.post_subject, pt.bbcode_uid, pt.edit_notes
FROM " . POSTS_TABLE . " p, " . USERS_TABLE . " u, " . POSTS_TEXT_TABLE . " pt
WHERE p.topic_id = $topic_id
$limit_posts_time
AND pt.post_id = p.post_id
AND u.user_id = p.poster_id
ORDER BY p.post_time $post_time_order
LIMIT $start, ".$board_config['posts_per_page'];
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain post/user information.", '', __LINE__, __FILE__, $sql);
}

$postrow = array();
if ($row = $db->sql_fetchrow($result))
{
do
{
if($row['user_id'] > 0)
{
$user_ids[$row['user_id']] = $row['username'];
}
if(defined('LOCAL_DEBUG'))
{
$row['post_text_compiled'] = '';
}
$postrow[] = $row;
}
while ($row = $db->sql_fetchrow($result));
$db->sql_freeresult($result);

$total_posts = count($postrow);
}
else
{
include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
sync('topic', $topic_id);

message_die(GENERAL_MESSAGE, $lang['No_posts_topic']);
}

$resync = FALSE;
if ($forum_topic_data['topic_replies'] + 1 < $start + count($postrow))
{
$resync = TRUE;
}
elseif ($start + $board_config['posts_per_page'] > $forum_topic_data['topic_replies'])
{
$row_id = intval($forum_topic_data['topic_replies']) % intval($board_config['posts_per_page']);
if ($postrow[$row_id]['post_id'] != $forum_topic_data['topic_last_post_id'] || $start + count($postrow) < $forum_topic_data['topic_replies'])
{
$resync = TRUE;
}
}
elseif (count($postrow) < $board_config['posts_per_page'])
{
$resync = TRUE;
}

if ($resync)
{
include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
sync('topic', $topic_id);

$result = $db->sql_query('SELECT COUNT(post_id) AS total FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . $topic_id);
$row = $db->sql_fetchrow($result);
$total_replies = $row['total'];
}

$sql = "SELECT *
FROM " . RANKS_TABLE . "
ORDER BY rank_special, rank_min";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain ranks information.", '', __LINE__, __FILE__, $sql);
}

$ranksrow = array();
while ( $row = $db->sql_fetchrow($result) )
{
$ranksrow[] = $row;
}
$db->sql_freeresult($result);

//
// Define censored word matches
//
$orig_word = array();
$replacement_word = array();
obtain_word_list($orig_word, $replacement_word);

//
// Censor topic title
//
if ( count($orig_word) )
{
$topic_title = preg_replace($orig_word, $replacement_word, $topic_title);
}

//
// Was a highlight request part of the URI?
//
$highlight_match = $highlight = '';
/* if (isset($HTTP_GET_VARS['highlight']))
{
// Split words and phrases
$words = explode(' ', trim(htmlspecialchars($HTTP_GET_VARS['highlight'])));

for($i = 0; $i < sizeof($words); $i++)
{
if (trim($words[$i]) != '')
{
$highlight_match .= (($highlight_match != '') ? '|' : '') . str_replace('*', '\w*', phpbb_preg_quote($words[$i], '#'));
}
}
unset($words);

$highlight = urlencode($HTTP_GET_VARS['highlight']);
$highlight_match = phpbb_rtrim($highlight_match, "\\");
}*/

//
// Post, reply and other URL generation for
// templating vars
//
$new_topic_url = $googlebot ? $googleurl : append_sid("posting.$phpEx?mode=newtopic&amp;" . POST_FORUM_URL . "=$forum_id");
$reply_topic_url = $googlebot ? $googleurl : append_sid("posting.$phpEx?mode=reply&amp;" . POST_TOPIC_URL . "=$topic_id");
$view_forum_url = append_sid("viewforum.$phpEx?" . POST_FORUM_URL . "=$forum_id");
$view_prev_topic_url = $googlebot ? $googleurl : append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;view=previous");
$view_next_topic_url = $googlebot ? $googleurl : append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;view=next");

//
// Mozilla navigation bar
//
$nav_links['prev'] = array(
'url' => $view_prev_topic_url,
'title' => $lang['View_previous_topic']
);
$nav_links['next'] = array(
'url' => $view_next_topic_url,
'title' => $lang['View_next_topic']
);
$nav_links['up'] = array(
'url' => $view_forum_url,
'title' => $forum_name
);

$reply_img = ( $forum_topic_data['forum_status'] == FORUM_LOCKED || $forum_topic_data['topic_status'] == TOPIC_LOCKED ) ? $images['reply_locked'] : $images['reply_new'];
$reply_alt = ( $forum_topic_data['forum_status'] == FORUM_LOCKED || $forum_topic_data['topic_status'] == TOPIC_LOCKED ) ? $lang['Topic_locked'] : $lang['Reply_to_topic'];
$post_img = ( $forum_topic_data['forum_status'] == FORUM_LOCKED ) ? $images['post_locked'] : $images['post_new'];
$post_alt = ( $forum_topic_data['forum_status'] == FORUM_LOCKED ) ? $lang['Forum_locked'] : $lang['Post_new_topic'];

//
// Set a cookie for this topic
//
if ( $userdata['session_logged_in'] )
{
$tracking_topics = ( isset($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_t']) ) ? unserialize_array($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_t']) : array();
$tracking_forums = ( isset($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_f']) ) ? unserialize_array($HTTP_COOKIE_VARS[$board_config['cookie_name'] . '_f']) : array();

if ( !empty($tracking_topics[$topic_id]) && !empty($tracking_forums[$forum_id]) )
{
$topic_last_read = ( $tracking_topics[$topic_id] > $tracking_forums[$forum_id] ) ? $tracking_topics[$topic_id] : $tracking_forums[$forum_id];
}
else if ( !empty($tracking_topics[$topic_id]) || !empty($tracking_forums[$forum_id]) )
{
$topic_last_read = ( !empty($tracking_topics[$topic_id]) ) ? $tracking_topics[$topic_id] : $tracking_forums[$forum_id];
}
else
{
$topic_last_read = $userdata['user_lastvisit'];
}

if ( count($tracking_topics) >= 150 && empty($tracking_topics[$topic_id]) )
{
asort($tracking_topics);
unset($tracking_topics[key($tracking_topics)]);
}

$tracking_topics[$topic_id] = time();

setcookie($board_config['cookie_name'] . '_t', serialize_array($tracking_topics), 0, $board_config['cookie_path'], $board_config['cookie_domain'], $board_config['cookie_secure']);
}

//
// Load templates
//
$template->set_filenames(array(
'body' => 'viewtopic_body.tpl')
);
make_jumpbox('viewforum.'.$phpEx, $forum_id);

//
// Output page header
//
$page_title = $forum_name .' :: ' . $topic_title;
$template->assign_block_vars('google_ad', array());
include($phpbb_root_path . 'includes/page_header.'.$phpEx);

//
// User authorisation levels output
//
$s_auth_can = ( ( $is_auth['auth_post'] ) ? $lang['Rules_post_can'] : $lang['Rules_post_cannot'] ) . '<br />';
$s_auth_can .= ( ( $is_auth['auth_reply'] ) ? $lang['Rules_reply_can'] : $lang['Rules_reply_cannot'] ) . '<br />';
$s_auth_can .= ( ( $is_auth['auth_edit'] ) ? $lang['Rules_edit_can'] : $lang['Rules_edit_cannot'] ) . '<br />';
$s_auth_can .= ( ( $is_auth['auth_delete'] ) ? $lang['Rules_delete_can'] : $lang['Rules_delete_cannot'] ) . '<br />';
$s_auth_can .= ( ( $is_auth['auth_vote'] ) ? $lang['Rules_vote_can'] : $lang['Rules_vote_cannot'] ) . '<br />';

$topic_mod = '';

if ( $is_auth['auth_mod'] )
{
$s_auth_can .= sprintf($lang['Rules_moderate'], "<a href=\"modcp.$phpEx?" . POST_FORUM_URL . "=$forum_id&amp;sid=" . $userdata['session_id'] . '">', '</a>');

$topic_mod .= empty($images['topic_mod_delete']) ? "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=delete&amp;sid=" . $userdata['session_id'] . '">delete</a>&nbsp;' : "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=delete&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['topic_mod_delete'] . '" alt="' . $lang['Delete_topic'] . '" title="' . $lang['Delete_topic'] . '" border="0" /></a>&nbsp;';

$topic_mod .= empty($images['topic_mod_move']) ? "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=move&amp;sid=" . $userdata['session_id'] . '">move</a>&nbsp;' : "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=move&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['topic_mod_move'] . '" alt="' . $lang['Move_topic'] . '" title="' . $lang['Move_topic'] . '" border="0" /></a>&nbsp;';

$topic_mod .= ( $forum_topic_data['topic_status'] == TOPIC_UNLOCKED ) ? (empty($images['topic_mod_lock']) ? "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=lock&amp;sid=" . $userdata['session_id'] . '">lock</a>&nbsp;' : "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=lock&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['topic_mod_lock'] . '" alt="' . $lang['Lock_topic'] . '" title="' . $lang['Lock_topic'] . '" border="0" /></a>&nbsp;') : (empty($images['topic_mod_unlock']) ? "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=unlock&amp;sid=" . $userdata['session_id'] . '">unlock</a>&nbsp;' : "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=unlock&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['topic_mod_unlock'] . '" alt="' . $lang['Unlock_topic'] . '" title="' . $lang['Unlock_topic'] . '" border="0" /></a>&nbsp;');

$topic_mod .= empty($images['topic_mod_split']) ? "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=split&amp;sid=" . $userdata['session_id'] . '">split</a>&nbsp;' : "<a href=\"modcp.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;mode=split&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['topic_mod_split'] . '" alt="' . $lang['Split_topic'] . '" title="' . $lang['Split_topic'] . '" border="0" /></a>&nbsp;';
}

//
// Topic watch information
//
$s_watching_topic = '';
if ( $can_watch_topic )
{
if ( $is_watching_topic )
{
$s_watching_topic = "<a href=\"viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;unwatch=topic&amp;start=$start&amp;sid=" . $userdata['session_id'] . '">' . $lang['Stop_watching_topic'] . '</a>';
$s_watching_topic_img = ( isset($images['topic_un_watch']) ) ? "<a href=\"viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;unwatch=topic&amp;start=$start&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['topic_un_watch'] . '" alt="' . $lang['Stop_watching_topic'] . '" title="' . $lang['Stop_watching_topic'] . '" border="0"></a>' : '';
}
else
{
$s_watching_topic = "<a href=\"viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;watch=topic&amp;start=$start&amp;sid=" . $userdata['session_id'] . '">' . $lang['Start_watching_topic'] . '</a>';
$s_watching_topic_img = ( isset($images['Topic_watch']) ) ? "<a href=\"viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;watch=topic&amp;start=$start&amp;sid=" . $userdata['session_id'] . '"><img src="' . $images['Topic_watch'] . '" alt="' . $lang['Start_watching_topic'] . '" title="' . $lang['Start_watching_topic'] . '" border="0"></a>' : '';
}
}

//
// If we've got a hightlight set pass it on to pagination,
// I get annoyed when I lose my highlight after the first page.
//
if($googlebot)
{
$pagination = generate_pagination("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id", $total_replies, $board_config['posts_per_page'], $start);
}
else
{
$pagination = ( $highlight != '' ) ? generate_pagination("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;postdays=$post_days&amp;postorder=$post_order&amp;highlight=$highlight", $total_replies, $board_config['posts_per_page'], $start) : generate_pagination("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;postdays=$post_days&amp;postorder=$post_order", $total_replies, $board_config['posts_per_page'], $start);
}

//
// Send vars to template
//
$template->assign_vars(array(
'FORUM_ID' => $forum_id,
'FORUM_NAME' => $forum_name,
'TOPIC_ID' => $topic_id,
'TOPIC_TITLE' => $topic_title,
'TOPIC_URL_GOOGLE' => 'viewtopic.php?t=' . $topic_id,
'PAGINATION' => $pagination,
'PAGE_NUMBER' => sprintf($lang['Page_of'], ( floor( $start / intval($board_config['posts_per_page']) ) + 1 ), ceil( $total_replies / intval($board_config['posts_per_page']) )),

'POST_IMG' => $post_img,
'REPLY_IMG' => $reply_img,

'L_AUTHOR' => $lang['Author'],
'L_MESSAGE' => $lang['Message'],
'L_POSTED' => $lang['Posted'],
'L_POST_SUBJECT' => $lang['Post_subject'],
'L_VIEW_NEXT_TOPIC' => $lang['View_next_topic'],
'L_VIEW_PREVIOUS_TOPIC' => $lang['View_previous_topic'],
'L_POST_NEW_TOPIC' => $post_alt,
'L_POST_REPLY_TOPIC' => $reply_alt,
'L_BACK_TO_TOP' => $lang['Back_to_top'],
'L_DISPLAY_POSTS' => $lang['Display_posts'],
'L_LOCK_TOPIC' => $lang['Lock_topic'],
'L_UNLOCK_TOPIC' => $lang['Unlock_topic'],
'L_MOVE_TOPIC' => $lang['Move_topic'],
'L_SPLIT_TOPIC' => $lang['Split_topic'],
'L_DELETE_TOPIC' => $lang['Delete_topic'],
'L_GOTO_PAGE' => $lang['Goto_page'],

'S_TOPIC_LINK' => POST_TOPIC_URL,
'S_SELECT_POST_DAYS' => $select_post_days,
'S_SELECT_POST_ORDER' => $select_post_order,
'S_POST_DAYS_ACTION' => $googlebot ? $googleurl : append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . '=' . $topic_id . "&amp;start=$start"),
'S_AUTH_LIST' => $s_auth_can,
'S_TOPIC_ADMIN' => $topic_mod,
'S_WATCH_TOPIC' => $s_watching_topic,
'S_WATCH_TOPIC_IMG' => $s_watching_topic_img,

'U_VIEW_TOPIC' => $googlebot ? append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id") : append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;start=$start&amp;postdays=$post_days&amp;postorder=$post_order&amp;highlight=$highlight"),
'U_VIEW_FORUM' => $view_forum_url,
'U_VIEW_OLDER_TOPIC' => $view_prev_topic_url,
'U_VIEW_NEWER_TOPIC' => $view_next_topic_url,
'U_POST_NEW_TOPIC' => $new_topic_url,
'U_POST_REPLY_TOPIC' => $reply_topic_url)
);

//
// Does this topic contain a poll?
//
if ( !empty($forum_topic_data['topic_vote']) )
{
$s_hidden_fields = '';

$sql = "SELECT vd.vote_id, vd.vote_text, vd.vote_start, vd.vote_length, vr.vote_option_id, vr.vote_option_text, vr.vote_result
FROM " . VOTE_DESC_TABLE . " vd, " . VOTE_RESULTS_TABLE . " vr
WHERE vd.topic_id = $topic_id
AND vr.vote_id = vd.vote_id
ORDER BY vr.vote_option_id ASC";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain vote data for this topic", '', __LINE__, __FILE__, $sql);
}

if ( $vote_info = $db->sql_fetchrowset($result) )
{
$db->sql_freeresult($result);
$vote_options = count($vote_info);

$vote_id = $vote_info[0]['vote_id'];
$vote_title = $vote_info[0]['vote_text'];

$sql = "SELECT vote_id
FROM " . VOTE_USERS_TABLE . "
WHERE vote_id = $vote_id
AND vote_user_id = " . intval($userdata['user_id']);
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, "Could not obtain user vote data for this topic", '', __LINE__, __FILE__, $sql);
}

$user_voted = ( $row = $db->sql_fetchrow($result) ) ? TRUE : 0;
$db->sql_freeresult($result);

if ( isset($HTTP_GET_VARS['vote']) || isset($HTTP_POST_VARS['vote']) )
{
$view_result = ( ( ( isset($HTTP_GET_VARS['vote']) ) ? $HTTP_GET_VARS['vote'] : $HTTP_POST_VARS['vote'] ) == 'viewresult' ) ? TRUE : 0;
}
else
{
$view_result = 0;
}

$poll_expired = ( $vote_info[0]['vote_length'] ) ? ( ( $vote_info[0]['vote_start'] + $vote_info[0]['vote_length'] < time() ) ? TRUE : 0 ) : 0;

if ( $user_voted || $view_result || $poll_expired || !$is_auth['auth_vote'] || $forum_topic_data['topic_status'] == TOPIC_LOCKED )
{
$template->set_filenames(array(
'pollbox' => 'viewtopic_poll_result.tpl')
);

$vote_results_sum = 0;

for($i = 0; $i < $vote_options; $i++)
{
$vote_results_sum += $vote_info[$i]['vote_result'];
}

$vote_graphic = 0;
$vote_graphic_max = count($images['voting_graphic']);

for($i = 0; $i < $vote_options; $i++)
{
$vote_percent = ( $vote_results_sum > 0 ) ? $vote_info[$i]['vote_result'] / $vote_results_sum : 0;
$vote_graphic_length = round($vote_percent * $board_config['vote_graphic_length']);

$vote_graphic_img = $images['voting_graphic'][$vote_graphic];
$vote_graphic = ($vote_graphic < $vote_graphic_max - 1) ? $vote_graphic + 1 : 0;

if ( count($orig_word) )
{
$vote_info[$i]['vote_option_text'] = preg_replace($orig_word, $replacement_word, $vote_info[$i]['vote_option_text']);
}

$template->assign_block_vars("poll_option", array(
'POLL_OPTION_CAPTION' => $vote_info[$i]['vote_option_text'],
'POLL_OPTION_RESULT' => $vote_info[$i]['vote_result'],
'POLL_OPTION_PERCENT' => sprintf("%.1d%%", ($vote_percent * 100)),

'POLL_OPTION_IMG' => $vote_graphic_img,
'POLL_OPTION_IMG_WIDTH' => $vote_graphic_length)
);
}

$template->assign_vars(array(
'L_TOTAL_VOTES' => $lang['Total_votes'],
'TOTAL_VOTES' => $vote_results_sum)
);

}
else
{
$template->set_filenames(array(
'pollbox' => 'viewtopic_poll_ballot.tpl')
);

for($i = 0; $i < $vote_options; $i++)
{
if ( count($orig_word) )
{
$vote_info[$i]['vote_option_text'] = preg_replace($orig_word, $replacement_word, $vote_info[$i]['vote_option_text']);
}

$template->assign_block_vars("poll_option", array(
'POLL_OPTION_ID' => $vote_info[$i]['vote_option_id'],
'POLL_OPTION_CAPTION' => $vote_info[$i]['vote_option_text'])
);
}

$template->assign_vars(array(
'L_SUBMIT_VOTE' => $lang['Submit_vote'],
'L_VIEW_RESULTS' => $lang['View_results'],

'U_VIEW_RESULTS' => $googlebot ? append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id") : append_sid("viewtopic.$phpEx?" . POST_TOPIC_URL . "=$topic_id&amp;postdays=$post_days&amp;postorder=$post_order&amp;vote=viewresult"))
);

$s_hidden_fields = '<input type="hidden" name="topic_id" value="' . $topic_id . '" /><input type="hidden" name="mode" value="vote" />';
}

if ( count($orig_word) )
{
$vote_title = preg_replace($orig_word, $replacement_word, $vote_title);
}

$s_hidden_fields .= '<input type="hidden" name="sid" value="' . $userdata['session_id'] . '" />';

$template->assign_vars(array(
'POLL_QUESTION' => $vote_title,

'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_POLL_ACTION' => $googlebot ? $googleurl : append_sid("posting.$phpEx?mode=vote&amp;" . POST_TOPIC_URL . "=$topic_id"))
);

$template->assign_var_from_handle('POLL_DISPLAY', 'pollbox');
}
}

//
// Update the topic view counter
//
if(!$googlebot)
{
$sql = "UPDATE " . TOPICS_TABLE . "
SET topic_views = topic_views + 1
WHERE topic_id = $topic_id";
if ( !$db->sql_query($sql) )
{
message_die(GENERAL_ERROR, "Could not update topic views.", '', __LINE__, __FILE__, $sql);
}
}

//
// Okay, let's do the loop, yeah come on baby let's do the loop
// and it goes like this ...
//
$sig_cache = array();
$delnote = isset($HTTP_GET_VARS['delnote']) ? explode('.', $HTTP_GET_VARS['delnote']) : array();
for($i = 0; $i < $total_posts; $i++)
{
$poster_id = $postrow[$i]['user_id'];
$poster = ( $poster_id == ANONYMOUS ) ? $lang['Guest'] : $postrow[$i]['username'];

$post_date = create_date2($board_config['default_dateformat'], $postrow[$i]['post_time'], $board_config['board_timezone']);

$poster_posts = ( $postrow[$i]['user_id'] != ANONYMOUS ) ? $lang['Posts'] . ': ' . $postrow[$i]['user_posts'] : '';

$poster_from = ( $postrow[$i]['user_from'] && $postrow[$i]['user_id'] != ANONYMOUS ) ? $lang['Location'] . ': ' . $postrow[$i]['user_from'] : '';

$poster_joined = ( $postrow[$i]['user_id'] != ANONYMOUS ) ? $lang['Joined'] . ': ' . create_date($lang['DATE_FORMAT'], $postrow[$i]['user_regdate'], $board_config['board_timezone']) : '';

$poster_avatar = '';
if ( $postrow[$i]['user_avatar_type'] && $poster_id != ANONYMOUS && $postrow[$i]['user_allowavatar'] )
{
switch( $postrow[$i]['user_avatar_type'] )
{
case USER_AVATAR_UPLOAD:
$poster_avatar = ( $board_config['allow_avatar_upload'] ) ? '<img src="' . $board_config['avatar_path'] . '/' . $postrow[$i]['user_avatar'] . '" alt="" border="0" />' : '';
break;
case USER_AVATAR_REMOTE:
$poster_avatar = ( $board_config['allow_avatar_remote'] ) ? '<img src="' . $postrow[$i]['user_avatar'] . '" alt="" border="0" />' : '';
break;
case USER_AVATAR_GALLERY:
$poster_avatar = ( $board_config['allow_avatar_local'] ) ? '<img src="' . $board_config['avatar_gallery_path'] . '/' . $postrow[$i]['user_avatar'] . '" alt="" border="0" />' : '';
break;
}
}

//
// Define the little post icon
//
if ( $userdata['session_logged_in'] && $postrow[$i]['post_time'] > $userdata['user_lastvisit'] && $postrow[$i]['post_time'] > $topic_last_read )
{
$mini_post_img = $images['icon_minipost_new'];
$mini_post_alt = $lang['New_post'];
}
else
{
$mini_post_img = $images['icon_minipost'];
$mini_post_alt = $lang['Post'];
}

$mini_post_url = $googlebot ? $googleurl : append_sid("viewtopic.$phpEx?" . POST_POST_URL . '=' . $postrow[$i]['post_id']) . '#' . $postrow[$i]['post_id'];

//
// Generate ranks, set them to empty string initially.
//
$poster_rank = '';
$rank_image = '';
if ( $postrow[$i]['user_id'] == ANONYMOUS )
{
}
else if ( $postrow[$i]['user_rank'] )
{
for($j = 0; $j < count($ranksrow); $j++)
{
if ( $postrow[$i]['user_rank'] == $ranksrow[$j]['rank_id'] && $ranksrow[$j]['rank_special'] )
{
$poster_rank = $ranksrow[$j]['rank_title'];
$rank_image = ( $ranksrow[$j]['rank_image'] ) ? '<img src="' . $ranksrow[$j]['rank_image'] . '" alt="' . $poster_rank . '" title="' . $poster_rank . '" border="0" /><br />' : '';
}
}
}
else
{
for($j = 0; $j < count($ranksrow); $j++)
{
if ( $postrow[$i]['user_posts'] >= $ranksrow[$j]['rank_min'] && !$ranksrow[$j]['rank_special'] )
{
$poster_rank = $ranksrow[$j]['rank_title'];
$rank_image = ( $ranksrow[$j]['rank_image'] ) ? '<img src="' . $ranksrow[$j]['rank_image'] . '" alt="' . $poster_rank . '" title="' . $poster_rank . '" border="0" /><br />' : '';
}
}
}

//
// Handle anon users posting with usernames
//
if ( $poster_id == ANONYMOUS && $postrow[$i]['post_username'] != '' )
{
$poster = $postrow[$i]['post_username'];
$poster_rank = $lang['Guest'];
}

$temp_url = '';

if ( $poster_id != ANONYMOUS )
{
$temp_url = $googlebot ? $googleurl : append_sid("profile.$phpEx?mode=viewprofile&amp;" . POST_USERS_URL . "=$poster_id");
$profile_img = '<a href="' . $temp_url . '"><img src="' . $images['icon_profile'] . '" alt="' . $lang['Read_profile'] . '" title="' . $lang['Read_profile'] . '" border="0" /></a>';
$profile = '<a href="' . $temp_url . '">' . $lang['Read_profile'] . '</a>';

$temp_url = $googlebot ? $googleurl : append_sid("privmsg.$phpEx?mode=post&amp;" . POST_USERS_URL . "=$poster_id");
$pm_img = '<a href="' . $temp_url . '"><img src="' . $images['icon_pm'] . '" alt="' . $lang['Send_private_message'] . '" title="' . $lang['Send_private_message'] . '" border="0" /></a>';
$pm = '<a href="' . $temp_url . '">' . $lang['Send_private_message'] . '</a>';

if (( !empty($postrow[$i]['user_viewemail']) || $is_auth['auth_mod'] ) && !$googlebot)
{
$email_uri = ( $board_config['board_email_form'] ) ? append_sid("profile.$phpEx?mode=email&amp;" . POST_USERS_URL .'=' . $poster_id) : 'mailto:' . $postrow[$i]['user_email'];

$email_img = '<a href="' . $email_uri . '"><img src="' . $images['icon_email'] . '" alt="' . $lang['Send_email'] . '" title="' . $lang['Send_email'] . '" border="0" /></a>';
$email = '<a href="' . $email_uri . '">' . $lang['Send_email'] . '</a>';
}
else
{
$email_img = '';
$email = '';
}

$www_img = ( $postrow[$i]['user_website'] ) ? '<a href="' . $postrow[$i]['user_website'] . '" target="_userwww"><img src="' . $images['icon_www'] . '" alt="' . $lang['Visit_website'] . '" title="' . $lang['Visit_website'] . '" border="0" /></a>' : '';
$www = ( $postrow[$i]['user_website'] ) ? '<a href="' . $postrow[$i]['user_website'] . '" target="_userwww">' . $lang['Visit_website'] . '</a>' : '';

if ( !empty($postrow[$i]['user_icq']) && !$googlebot )
{
$icq_status_img = '<a href="http://wwp.icq.com/' . $postrow[$i]['user_icq'] . '#pager"><img src="http://web.icq.com/whitepages/online?icq=' . $postrow[$i]['user_icq'] . '&img=5" width="18" height="18" border="0" /></a>';
$icq_img = '<a href="http://wwp.icq.com/scripts/search.dll?to=' . $postrow[$i]['user_icq'] . '"><img src="' . $images['icon_icq'] . '" alt="' . $lang['ICQ'] . '" title="' . $lang['ICQ'] . '" border="0" /></a>';
$icq = '<a href="http://wwp.icq.com/scripts/search.dll?to=' . $postrow[$i]['user_icq'] . '">' . $lang['ICQ'] . '</a>';
}
else
{
$icq_status_img = '';
$icq_img = '';
$icq = '';
}

$aim_img = ( $postrow[$i]['user_aim'] && !$googlebot ) ? '<a href="aim:goim?screenname=' . $postrow[$i]['user_aim'] . '&amp;message=Hello+Are+you+there?"><img src="' . $images['icon_aim'] . '" alt="' . $lang['AIM'] . '" title="' . $lang['AIM'] . '" border="0" /></a>' : '';
$aim = ( $postrow[$i]['user_aim'] && !$googlebot ) ? '<a href="aim:goim?screenname=' . $postrow[$i]['user_aim'] . '&amp;message=Hello+Are+you+there?">' . $lang['AIM'] . '</a>' : '';

$temp_url = $googlebot ? $googleurl : append_sid("profile.$phpEx?mode=viewprofile&amp;" . POST_USERS_URL . "=$poster_id");
$msn_img = ( $postrow[$i]['user_msnm'] && !$googlebot ) ? '<a href="' . $temp_url . '"><img src="' . $images['icon_msnm'] . '" alt="' . $lang['MSNM'] . '" title="' . $lang['MSNM'] . '" border="0" /></a>' : '';
$msn = ( $postrow[$i]['user_msnm'] && !$googlebot ) ? '<a href="' . $temp_url . '">' . $lang['MSNM'] . '</a>' : '';

$yim_img = ( $postrow[$i]['user_yim'] ) ? '<a href="http://edit.yahoo.com/config/send_webmesg?.target=' . $postrow[$i]['user_yim'] . '&amp;.src=pg"><img src="' . $images['icon_yim'] . '" alt="' . $lang['YIM'] . '" title="' . $lang['YIM'] . '" border="0" /></a>' : '';
$yim = ( $postrow[$i]['user_yim'] ) ? '<a href="http://edit.yahoo.com/config/send_webmesg?.target=' . $postrow[$i]['user_yim'] . '&amp;.src=pg">' . $lang['YIM'] . '</a>' : '';
}
else
{
$profile_img = '';
$profile = '';
$pm_img = '';
$pm = '';
$email_img = '';
$email = '';
$www_img = '';
$www = '';
$icq_status_img = '';
$icq_img = '';
$icq = '';
$aim_img = '';
$aim = '';
$msn_img = '';
$msn = '';
$yim_img = '';
$yim = '';
}

$temp_url = append_sid("posting.$phpEx?mode=quote&amp;" . POST_POST_URL . "=" . $postrow[$i]['post_id']);
$quote_img = $googlebot ? '' : '<a href="' . $temp_url . '"><img src="' . $images['icon_quote'] . '" alt="' . $lang['Reply_with_quote'] . '" title="' . $lang['Reply_with_quote'] . '" border="0" /></a>';
$quote = $googlebot ? '' : '<a href="' . $temp_url . '">' . $lang['Reply_with_quote'] . '</a>';

$temp_url = append_sid("search.$phpEx?search_author=" . urlencode($postrow[$i]['username']) . "&amp;showresults=posts");
$search_img = $googlebot ? '' : '<a href="' . $temp_url . '"><img src="' . $images['icon_search'] . '" alt="' . $lang['Search_user_posts'] . '" title="' . $lang['Search_user_posts'] . '" border="0" /></a>';
$search = $googlebot ? '' : '<a href="' . $temp_url . '">' . $lang['Search_user_posts'] . '</a>';

if ( ( $userdata['user_id'] == $poster_id && $is_auth['auth_edit'] ) || $is_auth['auth_mod'] )
{
$temp_url = append_sid("posting.$phpEx?mode=editpost&amp;" . POST_POST_URL . "=" . $postrow[$i]['post_id']);
$edit_img = '<a href="' . $temp_url . '"><img src="' . $images['icon_edit'] . '" alt="' . $lang['Edit_delete_post'] . '" title="' . $lang['Edit_delete_post'] . '" border="0" /></a>';
$edit = '<a href="' . $temp_url . '">' . $lang['Edit_delete_post'] . '</a>';
}
else
{
$edit_img = '';
$edit = '';
}

if ( $is_auth['auth_mod'] )
{
$temp_url = "modcp.$phpEx?mode=ip&amp;" . POST_POST_URL . "=" . $postrow[$i]['post_id'] . "&amp;" . POST_TOPIC_URL . "=" . $topic_id . "&amp;sid=" . $userdata['session_id'];
$ip_img = '<a href="' . $temp_url . '"><img src="' . $images['icon_ip'] . '" alt="' . $lang['View_IP'] . '" title="' . $lang['View_IP'] . '" border="0" /></a>';
$ip = '<a href="' . $temp_url . '">' . $lang['View_IP'] . '</a>';

$temp_url = "posting.$phpEx?mode=delete&amp;" . POST_POST_URL . "=" . $postrow[$i]['post_id'] . "&amp;sid=" . $userdata['session_id'];
$delpost_img = '<a href="' . $temp_url . '"><img src="' . $images['icon_delpost'] . '" alt="' . $lang['Delete_post'] . '" title="' . $lang['Delete_post'] . '" border="0" /></a>';
$delpost = '<a href="' . $temp_url . '">' . $lang['Delete_post'] . '</a>';
}
else
{
$ip_img = '';
$ip = '';

if ( $userdata['user_id'] == $poster_id && $is_auth['auth_delete'] && $forum_topic_data['topic_last_post_id'] == $postrow[$i]['post_id'] )
{
$temp_url = "posting.$phpEx?mode=delete&amp;" . POST_POST_URL . "=" . $postrow[$i]['post_id'] . "&amp;sid=" . $userdata['session_id'];
$delpost_img = '<a href="' . $temp_url . '"><img src="' . $images['icon_delpost'] . '" alt="' . $lang['Delete_post'] . '" title="' . $lang['Delete_post'] . '" border="0" /></a>';
$delpost = '<a href="' . $temp_url . '">' . $lang['Delete_post'] . '</a>';
}
else
{
$delpost_img = '';
$delpost = '';
}
}

$post_subject = ( $postrow[$i]['post_subject'] != '' ) ? $postrow[$i]['post_subject'] : '';

$message = $postrow[$i]['post_text'];
$message_compiled = empty($postrow[$i]['post_text_compiled']) ? false : $postrow[$i]['post_text_compiled'];
$bbcode_uid = $postrow[$i]['bbcode_uid'];

$user_sig = ( $postrow[$i]['enable_sig'] && trim($postrow[$i]['user_sig']) != '' && $board_config['allow_sig'] ) ? $postrow[$i]['user_sig'] : '';
$user_sig_bbcode_uid = $postrow[$i]['user_sig_bbcode_uid'];

//
// Parse message and/or sig for BBCode if reqd
//
$bbcode->allow_bbcode = $board_config['allow_bbcode'];
$bbcode->allow_smilies = $board_config['allow_smilies'];
if($user_sig && empty($sig_cache[$postrow[$i]['user_id']]))
{
$bbcode->is_sig = true;
$user_sig = $bbcode->parse($user_sig, $user_sig_bbcode_uid);
$sig_cache[$postrow[$i]['user_id']] = $user_sig;
$bbcode->is_sig = false;
}
elseif($user_sig)
{
$user_sig = $sig_cache[$postrow[$i]['user_id']];
}
if($message_compiled === false)
{
$bbcode->allow_smilies = $board_config['allow_smilies'] && $postrow[$i]['user_allowsmile'] ? true : false;
$GLOBALS['code_post_id'] = $postrow[$i]['post_id'];
$message = $bbcode->parse($message, $bbcode_uid);
$GLOBALS['code_post_id'] = 0;
// update database
$sql = "UPDATE " . POSTS_TEXT_TABLE . " SET post_text_compiled='" . addslashes($message) . "' WHERE post_id='" . $postrow[$i]['post_id'] . "'";
$db->sql_query($sql);
}
else
{
$message = $message_compiled;
}

//
// Highlight active words (primarily for search)
//
if ($highlight_match)
{
// This was shamelessly 'borrowed' from volker at multiartstudio dot de
// via php.net's annotated manual
$message = str_replace('\"', '"', substr(@preg_replace('#(\>(((?>([^><]+|(?R)))*)\<))#se', "@preg_replace('#\b(" . $highlight_match . ")\b#i', '<span style=\"color:#" . $theme['fontcolor3'] . "\"><b>\\\\1</b></span>', '\\0')", '>' . $message . '<'), 1, -1));
}

//
// Replace naughty words
//
if (count($orig_word))
{
$post_subject = preg_replace($orig_word, $replacement_word, $post_subject);

if ($user_sig != '')
{
$user_sig = str_replace('\"', '"', substr(preg_replace('#(\>(((?>([^><]+|(?R)))*)\<))#se', "preg_replace(\$orig_word, \$replacement_word, '\\0')", '>' . $user_sig . '<'), 1, -1));
}

$message = str_replace('\"', '"', substr(preg_replace('#(\>(((?>([^><]+|(?R)))*)\<))#se', "preg_replace(\$orig_word, \$replacement_word, '\\0')", '>' . $message . '<'), 1, -1));
}

//
// Replace newlines (we use this rather than nl2br because
// till recently it wasn't XHTML compliant)
//
if ( trim($user_sig) !== '' )
{
$user_sig = '<br />_________________<br />' . $user_sig;
}
else
{
$user_sig = '';
}

//
// Editing information
//
if ( $postrow[$i]['post_edit_count'] )
{
$l_edit_time_total = ( $postrow[$i]['post_edit_count'] == 1 ) ? $lang['Edited_time_total'] : $lang['Edited_times_total'];

$l_edited_by = '<br /><br />' . sprintf($l_edit_time_total, $poster, create_date($board_config['default_dateformat'], $postrow[$i]['post_edit_time'], $board_config['board_timezone']), $postrow[$i]['post_edit_count']);
}
else
{
$l_edited_by = '';
}

if($googlebot)
{
$postrow[$i]['edit_notes'] = '';
}
$notes_list = strlen($postrow[$i]['edit_notes']) ? unserialize($postrow[$i]['edit_notes']) : array();
if($is_auth['auth_mod'] && count($delnote) == 2 && $delnote[0] == $postrow[$i]['post_id'])
{
$new_list = array();
$num = intval($delnote[1]);
for($n=0; $n<count($notes_list); $n++)
{
if($n !== $num)
{
$new_list[] = $notes_list[$n];
}
}
$notes_list = $new_list;
$postrow[$i]['edit_notes'] = count($notes_list) ? serialize($notes_list) : '';
$sql = "UPDATE " . POSTS_TEXT_TABLE . " SET edit_notes='" . addslashes($postrow[$i]['edit_notes']) . "' WHERE post_id='{$postrow[$i]['post_id']}'";
$db->sql_query($sql);
}

//
// Again this will be handled by the templating
// code at some point
//
$row_color = ( !($i % 2) ) ? $theme['td_color1'] : $theme['td_color2'];
$row_class = ( !($i % 2) ) ? $theme['td_class1'] : $theme['td_class2'];

$template->assign_block_vars('postrow', array(
'ROW_COLOR' => '#' . $row_color,
'ROW_CLASS' => $row_class,
'POSTER_NAME' => $poster,
'POSTER_RANK' => '', //$poster_rank,
'RANK_IMAGE' => $rank_image,
'POSTER_JOINED' => $poster_joined,
'POSTER_POSTS' => $poster_posts,
'POSTER_FROM' => $poster_from,
'POSTER_AVATAR' => $poster_avatar,
'POST_DATE' => $post_date,
'POST_SUBJECT' => $post_subject,
'MESSAGE' => $message,
'SIGNATURE' => $user_sig,
'EDITED_MESSAGE' => $l_edited_by,

'MINI_POST_IMG' => $mini_post_img,
'PROFILE_IMG' => $profile_img,
'PROFILE' => $profile,
'SEARCH_IMG' => $search_img,
'SEARCH' => $search,
'PM_IMG' => $pm_img,
'PM' => $pm,
'EMAIL_IMG' => $email_img,
'EMAIL' => $email,
'WWW_IMG' => $www_img,
'WWW' => $www,
'ICQ_STATUS_IMG' => $icq_status_img,
'ICQ_IMG' => $icq_img,
'ICQ' => $icq,
'AIM_IMG' => $aim_img,
'AIM' => $aim,
'MSN_IMG' => $msn_img,
'MSN' => $msn,
'YIM_IMG' => $yim_img,
'YIM' => $yim,
'EDIT_IMG' => $edit_img,
'EDIT' => $edit,
'QUOTE_IMG' => $quote_img,
'QUOTE' => $quote,
'IP_IMG' => $ip_img,
'IP' => $ip,
'DELETE_IMG' => $delpost_img,
'DELETE' => $delpost,

'L_MINI_POST_ALT' => $mini_post_alt,
'NOTES_COUNT' => count($notes_list),
'NOTES_DATA' => $postrow[$i]['edit_notes'],

'U_MINI_POST' => $mini_post_url,
'U_POST_ID' => $postrow[$i]['post_id'])
);
for($n=0; $n<count($notes_list); $n++)
{
if(!isset($user_ids[$notes_list[$n]['poster']]))
{
$user_ids[$notes_list[$n]['poster']] = 'n/a';
$user_ids2[] = $notes_list[$n]['poster'];
}
}
}

if(count($user_ids2))
{
$sql = "SELECT user_id, username FROM " . USERS_TABLE . " WHERE user_id IN (" . implode(', ', $user_ids2) . ")";
$result = $db->sql_query($sql);
while( $row = $db->sql_fetchrow($result) )
{
$user_ids[$row['user_id']] = $row['username'];
}
$db->sql_freeresult($result);
}

// add notes
unset($item);
for($i=0; $i<count($template->_tpldata['postrow.']); $i++)
{
if(!empty($template->_tpldata['postrow.'][$i]['NOTES_DATA']))
{
$item = &$template->_tpldata['postrow.'][$i];
$item['notes.'] = array();
$list = unserialize($item['NOTES_DATA']);
for($j=0; $j<count($list); $j++)
{
$item['notes.'][] = array(
'POSTER_NAME' => $user_ids[$list[$j]['poster']],
'POSTER_PROFILE' => append_sid("profile.$phpEx?mode=viewprofile&amp;" . POST_USERS_URL . "=" . $list[$j]['poster']),
'TEXT' => htmlspecialchars($list[$j]['text']),
'TIME' => create_date($board_config['default_dateformat'], $list[$j]['time'], $board_config['board_timezone']),
'U_DELETE' => $is_auth['auth_mod'] ? ($template->vars['U_VIEW_TOPIC'] . '&amp;delnote=' . $item['U_POST_ID'] . '.' . $j) : '',
);
}
unset($item);
}
}

$template->pparse('body');

include($phpbb_root_path . 'includes/page_tail.'.$phpEx);

?>
[/code]
Do NOT pm me, I don't visit this forum anymore, don't own it, don't provide any support and don't moderate.
User avatar
PostBot
Moderator
Moderator
 
Posts: 10659
Joined: Sat Aug 02, 2003 3:52 pm
Location: Mars

Postby PostBot on Tue May 31, 2005 7:39 am

Do whatever you want with it :)

Note: these files are not fully compatible with phpBB so don't try to simply put it on your forum. It won't work. You'll need to do lots of other adjustments before using these files. But it can be used to create mods that have similar functionality.
Do NOT pm me, I don't visit this forum anymore, don't own it, don't provide any support and don't moderate.
User avatar
PostBot
Moderator
Moderator
 
Posts: 10659
Joined: Sat Aug 02, 2003 3:52 pm
Location: Mars

Postby DooBDee on Tue May 31, 2005 8:28 am

thanks CA - really helpful.

All i would like on my forums are:

line numbers
Download
Hide.

I dont suppose there is a quick wauy of doing this? Baz-x has a lit of bugs in it and soetimes does not work at all . :(
DooBDee
Website Ninja
DooBDee.net
User avatar
DooBDee
Moderator
Moderator
 
Posts: 3530
Joined: Tue Mar 01, 2005 6:28 pm
Location: DooBDee.net

Postby Bicet on Tue May 31, 2005 9:09 am

Half of my post are Thnx Cyber ;)
So I would like to thank you again.
User avatar
Bicet
Coder
Coder
 
Posts: 247
Joined: Mon Nov 15, 2004 7:50 pm

Postby Thatbitextra on Tue May 31, 2005 9:12 am

Yeah, thanks CyberAlien :)
I hope one day I will be able to understand it, and until then I will try to learn from it :)
My MODs: [NEW] Choose Who to Accept PMs From (Prevents you from receiving unwanted PMs!) | Warn of Old Topic Before Posting Reply
Style: subBlack (Now updated to phpBB 2.0.22 and 5 new color schemes!)

Please note, I do NOT offer support via PM. It's a forum, so post your question, then everyone can help.
User avatar
Thatbitextra
Moderator
Moderator
 
Posts: 1821
Joined: Thu Mar 24, 2005 1:11 pm
Location: A place where something is or could be located; a site.

Postby UseLess on Tue May 31, 2005 11:29 am

Greetings,

Well I wasn't very happy this morning, you'd understand if you consider the following: Daughter + bedroom + paint.. and there's not a lot of paint where it should be... ;) but now I am sort of... I'll be happier when I've had a chance to look over the files...

But thanks a million CA...
Movie Quote:
It's not the years honey, it's the mileage...

I do not provide any install services for phpBB, Mods or Styles.
Please do not pm me for support/scripting help - you won't get any reply. If you have a question then make a post in the appropriate forum.
User avatar
UseLess
Registered User
Registered User
 
Posts: 6220
Joined: Mon Sep 27, 2004 2:14 am
Location: North East, UK

Postby MrBass on Tue May 31, 2005 12:06 pm

[quote user="DoobDee" post="37354"]thanks CA - really helpful.

All i would like on my forums are:

line numbers
Download
Hide.

I dont suppose there is a quick wauy of doing this? Baz-x has a lit of bugs in it and soetimes does not work at all . :([/quote]

I'm the same a DoobDee, plus I like the filename option too. Unfortunately I know diddly squat about PHP so I'm stuck until someone releases a mod for us mere mortals.
MrBass
The heart has reasons that reason cannot know. --Pascal

Pete's Place | Pete's Forum
Latest MOD: File Upload Manager Installation guide coming soon...
User avatar
MrBass
Moderator
Moderator
 
Posts: 711
Joined: Thu Feb 17, 2005 2:06 pm
Location: Pete's Place

Postby PostBot on Tue May 31, 2005 12:20 pm

I just noticed that some html special characters didn't convert properly, so I've updated code for bbcode.php. To make sure you get full code use download function to download it instead of copy/paste.
Do NOT pm me, I don't visit this forum anymore, don't own it, don't provide any support and don't moderate.
User avatar
PostBot
Moderator
Moderator
 
Posts: 10659
Joined: Sat Aug 02, 2003 3:52 pm
Location: Mars

Postby PostBot on Wed Jun 01, 2005 8:58 am

Few notes about bbcode parser:

1. It doesn't handle html, so even if html is enabled on forum it won't work. Original parser handles it, but phpBB does preparsing of text and after it its almost impossible to convert text back to what user entered in textarea so I didn't bother converting html parser to phpbb.

2. It doesn't handle properly characters like &#8226;. So when posting that character inside text better to use &[b][/b]#8226;. When posting such characters inside [code] block use &[highlight][/highlight]#8226;. This is also caused by incompatibility with phpBB 2.0 bbcode parser.

So if anyone would make this into a mod he should fix those bugs.
Do NOT pm me, I don't visit this forum anymore, don't own it, don't provide any support and don't moderate.
User avatar
PostBot
Moderator
Moderator
 
Posts: 10659
Joined: Sat Aug 02, 2003 3:52 pm
Location: Mars

Postby DooBDee on Wed Jun 01, 2005 10:23 am

Yes, i would like this VERY VERY much!
DooBDee
Website Ninja
DooBDee.net
User avatar
DooBDee
Moderator
Moderator
 
Posts: 3530
Joined: Tue Mar 01, 2005 6:28 pm
Location: DooBDee.net

Postby Magnotta on Fri Jun 17, 2005 3:08 am

Thanks for posting this CA. Ever since I joined here I wanted to have a code bbcode like the one here where the lines are numbered. While I know that someones made a mod for it, it wasn;t really what I was looking for, as I wanted something simpler with just the lined numbers. Now, thanks to you posting this, I've figured out a nice simple way to get it done(so far only on a testboard, as it needs more polishing before I'll actually use it, but still happy to get it started). So thanks :)
User avatar
Magnotta
Registered User
Registered User
 
Posts: 315
Joined: Wed Jan 19, 2005 11:11 pm

Postby DooBDee on Fri Jun 17, 2005 9:10 am

[quote user="Magnotta" post="39947"]Thanks for posting this CA. Ever since I joined here I wanted to have a code bbcode like the one here where the lines are numbered. While I know that someones made a mod for it, it wasn;t really what I was looking for, as I wanted something simpler with just the lined numbers. Now, thanks to you posting this, I've figured out a nice simple way to get it done(so far only on a testboard, as it needs more polishing before I'll actually use it, but still happy to get it started). So thanks :)[/quote]

Ca's version does not only do lined numbers.
DooBDee
Website Ninja
DooBDee.net
User avatar
DooBDee
Moderator
Moderator
 
Posts: 3530
Joined: Tue Mar 01, 2005 6:28 pm
Location: DooBDee.net

Postby PostBot on Fri Jun 17, 2005 9:16 am

Yes, there are more functions than code formatting. There is also bbcode styling, limitation of nested bbcode (for example you can limit nested quotes to 3 as it is done on this forum), you can limit number of certain bbcodes per post, easily add new bbcodes, easily add new parametes to any bbcode tag, limit max/min size bbcode (and also handling of vbulletin type size bbcode), rgb colors, etc...

And the best part is that it doesn't use lots of complex regexps, so bbcode parsing is much faster.
Do NOT pm me, I don't visit this forum anymore, don't own it, don't provide any support and don't moderate.
User avatar
PostBot
Moderator
Moderator
 
Posts: 10659
Joined: Sat Aug 02, 2003 3:52 pm
Location: Mars

Postby DooBDee on Fri Jun 17, 2005 9:22 am

[quote user="CyberAlien" post="39959"]Yes, there are more functions than code formatting. There is also bbcode styling, limitation of nested bbcode (for example you can limit nested quotes to 3 as it is done on this forum), you can limit number of certain bbcodes per post, easily add new bbcodes, easily add new parametes to any bbcode tag, limit max/min size bbcode (and also handling of vbulletin type size bbcode), rgb colors, etc...

And the best part is that it doesn't use lots of complex regexps, so bbcode parsing is much faster.[/quote]

Agreed.

I am personally just waiting for a mod for this ;)
DooBDee
Website Ninja
DooBDee.net
User avatar
DooBDee
Moderator
Moderator
 
Posts: 3530
Joined: Tue Mar 01, 2005 6:28 pm
Location: DooBDee.net

Next

Return to Regular Discussion

Who is online

Users browsing this forum: No registered users and 0 guests