Topic: Help with slow query

Hi.
I'm running an altered version of punBB for a combination of portal, bittorrent tracker (no warez smile) and forum, all using punBB's theme engine.
Everything is working fine and speedy for topics where the number of posts is low but I have at least 2 topics where the post count is so high I get query times of over 7 seconds.
Any ideas on how to solve it?

The debug of viewtopic.php with the biggest thread (over 21675 posts):

Time (s) Query 
0.00323 SELECT u.*, g.*, o.logged, o.idle FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.user_id=u.id WHERE u.id=2 
0.00153 UPDATE LOW_PRIORITY punbb_online SET logged=1167761785 WHERE user_id=2 
0.00135 UPDATE punbb_online SET current_page='/forum/viewtopic.php', current_ip='192.168.1.51', current_page_id='691' WHERE user_id='2' 
0.00168 SELECT * FROM punbb_online WHERE logged<1167761485 
0.00238 SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=2) LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=691 AND t.moved_to IS NULL 
0.00135 insert into punbb_statviews_all(user_id, topic_id) VALUES (2, 691) 
0.00209 SELECT (SELECT COUNT(*) FROM bt_peers WHERE userid=2 AND seeder="yes") AS seeders, (SELECT COUNT(*) FROM bt_peers WHERE userid=2 AND seeder="no") AS leechers 
0.00094 SELECT COUNT(id) FROM punbb_reports WHERE zapped IS NULL 
0.00097 SELECT COUNT(id) FROM punbb_messages WHERE showed=0 AND owner=2 
5.56557 SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id=691 ORDER BY p.id LIMIT 0,25 
0.47620 select af.* from punbb_attach_2_files as af left join punbb_posts as p on af.post_id=p.id where p.topic_id=691 
0.00201 SELECT search_for, replace_with FROM punbb_censoring 
0.00191 UPDATE LOW_PRIORITY punbb_topics SET num_views=num_views+1 WHERE id=691 
Total query time: 6.06121 s

The debug of viewtopic.php with a small thread (11 posts) :

Time (s) Query 
0.00326 SELECT u.*, g.*, o.logged, o.idle FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.user_id=u.id WHERE u.id=2 
0.00151 UPDATE LOW_PRIORITY punbb_online SET logged=1167761953 WHERE user_id=2 
0.00146 UPDATE punbb_online SET current_page='/forum/viewtopic.php', current_ip='192.168.1.51', current_page_id='2301' WHERE user_id='2' 
0.00172 SELECT * FROM punbb_online WHERE logged<1167761653 
0.00247 SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=2) LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=2301 AND t.moved_to IS NULL 
0.00150 insert into punbb_statviews_all(user_id, topic_id) VALUES (2, 2301) 
0.00138 SELECT (SELECT COUNT(*) FROM bt_peers WHERE userid=2 AND seeder="yes") AS seeders, (SELECT COUNT(*) FROM bt_peers WHERE userid=2 AND seeder="no") AS leechers 
0.00103 SELECT COUNT(id) FROM punbb_reports WHERE zapped IS NULL 
0.00106 SELECT COUNT(id) FROM punbb_messages WHERE showed=0 AND owner=2 
0.01488 SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id=2301 ORDER BY p.id LIMIT 0,25 
0.00232 select af.* from punbb_attach_2_files as af left join punbb_posts as p on af.post_id=p.id where p.topic_id=2301 
0.00143 SELECT search_for, replace_with FROM punbb_censoring 
0.00181 UPDATE LOW_PRIORITY punbb_topics SET num_views=num_views+1 WHERE id=2301 
Total query time: 0.03583 s

An explain with 11 posts:

id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
1 SIMPLE p ref punbb_posts_topic_id_idx,punbb_posts_multi_idx punbb_posts_topic_id_idx 4 const 32 Using temporary; Using filesort 
1 SIMPLE u eq_ref PRIMARY,group_id PRIMARY 4 ptanime.p.poster_id 1   
1 SIMPLE g eq_ref PRIMARY PRIMARY 4 ptanime.u.group_id 1   
1 SIMPLE o ALL unique_online_idx NULL NULL NULL 22

An explain with +21k posts:

id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
1 SIMPLE u ALL PRIMARY,group_id NULL NULL NULL 1489 Using temporary; Using filesort 
1 SIMPLE g eq_ref PRIMARY PRIMARY 4 ptanime.u.group_id 1   
1 SIMPLE p ref punbb_posts_topic_id_idx,punbb_posts_multi_idx punbb_posts_multi_idx 8 ptanime.u.id,const 5   
1 SIMPLE o ALL unique_online_idx NULL NULL NULL 26

Any ideas on how to solve this?

Re: Help with slow query

I can try breaking that up into two queries for you: if a topic in phpBB is to be believed, that should speed you pu a bit smile
I would need a copy of viewtopic.php for you though

Re: Help with slow query

You mean a copy of viewtopic.php?
Sure, not a problem:

<?php
/***********************************************************************

  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)

  This file is part of PunBB.

  PunBB 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.

  PunBB is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  MA  02111-1307  USA

************************************************************************/

// Enable SPELLCHECKER on this page
// Disable it by adding // from the following line (on this page only)
define('PBB_SPELLCHECKER', 1);

define('PUN_ROOT', './');
require PUN_ROOT.'include/common.php';
require PUN_ROOT.'include/attach/attach_incl.php'; //Attachment Mod row, loads variables, functions and lang file


if ($pun_user['g_read_board'] == '0')
    message($lang_common['No view']);


$action = isset($_GET['action']) ? $_GET['action'] : null;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;
if ($id < 1 && $pid < 1)
    message($lang_common['Bad request']);

// Load the viewtopic.php language file
require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';


// If a post ID is specified we determine topic ID and page number so we can redirect to the correct message
if ($pid)
{
    $result = $db->query('SELECT topic_id FROM '.$db->prefix.'posts WHERE id='.$pid) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $id = $db->result($result);

    // Determine on what page the post is located (depending on $pun_user['disp_posts'])
    $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$id.' ORDER BY posted') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $num_posts = $db->num_rows($result);

    for ($i = 0; $i < $num_posts; ++$i)
    {
        $cur_id = $db->result($result, $i);
        if ($cur_id == $pid)
            break;
    }
    ++$i;    // we started at 0

    $_GET['p'] = ceil($i / $pun_user['disp_posts']);
}

// If action=new, we redirect to the first new post (if any)
else if ($action == 'new' && !$pun_user['is_guest'])
{
    $result = $db->query('SELECT MIN(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' AND posted>'.$pun_user['last_visit']) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $first_new_post_id = $db->result($result);

    if ($first_new_post_id)
        header('Location: viewtopic.php?pid='.$first_new_post_id.'#p'.$first_new_post_id);
    else    // If there is no new post, we go to the last post
        header('Location: viewtopic.php?id='.$id.'&action=last');

    exit;
}

// If action=last, we redirect to the last post
else if ($action == 'last')
{
    $result = $db->query('SELECT MAX(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $last_post_id = $db->result($result);

    if ($last_post_id)
    {
        header('Location: viewtopic.php?pid='.$last_post_id.'#p'.$last_post_id);
        exit;
    }
}


// Fetch some info about the topic
if (!$pun_user['is_guest'])
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
else
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

// MOD USERSTATS
$statresult = $db->query('insert into '.$db->prefix.'statviews_all(user_id, topic_id) VALUES (' . $pun_user['id'] . ', '.$id.')') or error('Unable to update view statistics', __FILE__, __LINE__, $db->error());
// MOD USERSTATS

if (!$db->num_rows($result))
    message($lang_common['Bad request']);

$cur_topic = $db->fetch_assoc($result);

// Sort out who the moderators are and if we are currently a moderator (or an admin)
$mods_array = ($cur_topic['moderators'] != '') ? unserialize($cur_topic['moderators']) : array();
$is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_id'] == PUN_MOD && array_key_exists($pun_user['username'], $mods_array))) ? true : false;

// Can we or can we not post replies?
if ($cur_topic['closed'] == '0')
{
    if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1' || $is_admmod)
        $post_link = '<a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
    else
        $post_link = ' ';
}
else
{
    $post_link = $lang_topic['Topic closed'];

    if ($is_admmod)
        $post_link .= ' / <a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
}


// Determine the post offset (based on $_GET['p'])
$num_pages = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);

if(!isset($_GET['p']) || $_GET['p'] <= 1) $p = 1;
else if($_GET['p'] > $num_pages) $p = $num_pages;
else $p = $_GET['p'];
$start_from = $pun_user['disp_posts'] * ($p - 1);

// Generate paging links
$paging_links = $lang_common['Pages'].': '.paginate($num_pages, $p, 'viewtopic.php?id='.$id);


if ($pun_config['o_censoring'] == '1')
    $cur_topic['subject'] = censor_words($cur_topic['subject']);

$quickpost_buttons = false;
if ($pun_config['o_quickpost_buttons'] == '1')
    $quickpost_buttons = true;

$quickpost = false;
if ($pun_config['o_quickpost'] == '1' &&
    !$pun_user['is_guest'] &&
    ($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) &&
    ($cur_topic['closed'] == '0' || $is_admmod))
{
    $required_fields = array('req_message' => $lang_common['Message']);
    $quickpost = true;
}

if (!$pun_user['is_guest'] && $pun_config['o_subscriptions'] == '1')
{
    if ($cur_topic['is_subscribed'])
        // I apologize for the variable naming here. It's a mix of subscription and action I guess :-)
        $subscraction = '<p class="subscribelink clearb">'.$lang_topic['Is subscribed'].' - <a href="misc.php?unsubscribe='.$id.'">'.$lang_topic['Unsubscribe'].'</a></p>'."\n";
    else
        $subscraction = '<p class="subscribelink clearb"><a href="misc.php?subscribe='.$id.'">'.$lang_topic['Subscribe'].'</a></p>'."\n";
}
else
    $subscraction = '<div class="clearer"></div>'."\n";

if ($cur_topic['question'])
    $cur_topic_question = $cur_topic['question'].' - ';
else
    $cur_topic_question = '';

$page_title = pun_htmlspecialchars($pun_config['o_board_title'].' / '.$cur_topic_question . $cur_topic['subject']);
define('PUN_ALLOW_INDEX', 1);
require PUN_ROOT.'header.php';

?>
<div class="linkst">
    <div class="inbox">
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <p class="postlink conr"><?php echo $post_link ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <div class="clearer"></div>
    </div>
</div>

<?php


require PUN_ROOT.'include/parser.php';

// Mod poll begin
if ($cur_topic['question'])
{
    require PUN_ROOT . 'lang/' . $pun_user['language'] . '/polls.php'; 
    // get the poll data
    $result = $db->query('SELECT ptype,options,voters,votes FROM ' . $db->prefix . 'polls WHERE pollid=' . $id . '') or error('Unable to fetch poll info', __FILE__, __LINE__, $db->error());

    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $cur_poll = $db->fetch_assoc($result);

    $options = unserialize($cur_poll['options']);
    if (!empty($cur_poll['voters']))
        $voters = unserialize($cur_poll['voters']);
    else
        $voters = array();

    $ptype = $cur_poll['ptype']; 
    // yay memory!
    // $cur_poll = null;
    $firstcheck = false;
    ?>
<div class="blockform">
    <h2><span><?php echo $lang_polls['Poll'] ?></span></h2>
    <div class="box">
        <?php
    if ((!$pun_user['is_guest']) && (!in_array($pun_user['id'], $voters)) && ($cur_topic['closed'] == '0') && (($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) || $is_admmod)) 
    {
        $showsubmit = true;
        ?>
        <form id="post" method="post" action="vote.php">
            <div class="inform">
                <div class="rbox">
                <fieldset>
                    <legend><?php echo pun_htmlspecialchars($cur_topic['question']) ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="poll_id" value="<?php echo $id; ?>" />
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
    
                        <?php
                        if ($ptype == 1) 
                        {
                            while (list($key, $value) = each($options)) 
                            {
                            ?>
                                <label><input name="vote" <?php if (!$firstcheck) { echo 'checked="checked"'; $firstcheck = true; }; ?> type="radio" value="<?php echo $key ?>" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 2) 
                        {
                            while (list($key, $value) = each($options)) 
                            {         
                            ?>
                                <label><input name="options[<?php echo $key ?>]" type="checkbox" value="1" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 3) 
                        {
                            
                            while (list($key, $value) = each($options)) 
                            {
                                echo pun_htmlspecialchars($value); ?>
                                <label><input name="options[<?php echo $key ?>]" checked="checked" type="radio" value="yes" /> <?php echo $cur_topic['yes']; ?></label>
                                <label><input name="options[<?php echo $key ?>]" type="radio" value="no" /> <?php echo $cur_topic['no']; ?></label>
                                <br />
                            <?php
                            } 
                        } 
                        else
                        {
                            message($lang_common['Bad request']);
                        }
            ?></div></fieldset><?php
    } 
    else 
    {
        $showsubmit = false;
        ?>
        <div class="inform">
        <div class="rbox">
            
            <p class="poll_info"><strong><?php echo pun_htmlspecialchars($cur_topic['question']) ?></strong></p>            
            <?php
            if (!empty($cur_poll['votes']))
                    $votes = unserialize($cur_poll['votes']);
            else
                  $votes = array();
        
            if ($ptype == 1 || $ptype == 2) 
            {
                $total = 0;
                $percent = 0;
                $percent_int = 0;
                while (list($key, $val) = each($options)) 
                {
                    if (isset($votes[$key]))
                        $total += $votes[$key];
                }
                reset($options);
            }
            
              while (list($key, $value) = each($options)) {    

                if ($ptype == 1 || $ptype == 2)
                { 
                    if (isset($votes[$key]))
                    {
                        $percent =  $votes[$key] * 100 / $total;
                        $percent_int = floor($percent);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        <div class="poll_result">
                            <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key])) echo $percent_int/2; else echo '0'; ?>%;" alt="" />
                            <span><?php if (isset($votes[$key])) echo $percent_int . '% - ' . $votes[$key]; else echo '0% - 0'; ?></span>
                        </div>
                <?php
                }
                else if ($ptype == 3) 
                { 
                    $total = 0;
                    $yes_percent = 0;
                    $no_percent = 0;
                    $vote_yes = 0;
                    $vote_no = 0;
                    if (isset($votes[$key]['yes']))
                    {
                        $vote_yes = $votes[$key]['yes'];
                    }

                    if (isset($votes[$key]['no'])) {
                        $vote_no += $votes[$key]['no'];
                    }

                    $total = $vote_yes + $vote_no;
                    if (isset($votes[$key]))
                    {
                        $yes_percent =   floor($vote_yes * 100 / $total);
                        $no_percent = floor($vote_no * 100 / $total);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        
                        <div class="poll_result_yesno">
                            <strong><?php echo $cur_topic['yes']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['yes'])) { echo $yes_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['yes'])) { echo $yes_percent . "% - " . $votes[$key]['yes']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                        <div class="poll_result_yesno">                        
                            <strong><?php echo $cur_topic['no']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['no'])) { echo $no_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['no'])) { echo $no_percent . "% - " . $votes[$key]['no']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                    <?php 
                }
                else
                message($lang_common['Bad request']);
            }     
            ?>
                <p class="poll_info">Total : <?php echo $total; ?></p>
            <?php
        } 
        ?>
            </div>
                
            </div>

            <?php if ($showsubmit == true) 
            { 
                echo '<p><input type="submit" name="submit" tabindex="2" value="' . $lang_common['Submit'] . '" accesskey="s" /> <input type="submit" name="null" tabindex="2" value="' . $lang_polls['Null vote']. '" accesskey="n" /></p>
                </form>';
            } 
            ?>
    </div>
</div>
<?php
}
// Mod poll end

$bg_switch = true;    // Used for switching background color in posts
$post_count = 0;    // Keep track of post numbers

// Retrieve the posts (and their respective poster/online status)
//$result = $db->query('SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.idle=0) WHERE p.topic_id='.$id.' ORDER BY p.id LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error()); //Attachment Mod, changed the true to false...
// ---------- TB ----------
$result = $db->query('
SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
 FROM '.$db->prefix.'posts AS p
 INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
 INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
 LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
 WHERE p.topic_id='.$id.'
 ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'
 LIMIT '.$start_from.','.$pun_user['disp_posts'], false)
    or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
// ---------- TB ----------

$att_res = $db->query('select af.* from '.$db->prefix.'attach_2_files as af left join '.$db->prefix.'posts as p on af.post_id=p.id where p.topic_id='.$id);
$att_arr = array();
$attach_allow_download = false;

while ($att_arr[] = $db->fetch_assoc($att_res)) {}
if($pun_user['g_id']==PUN_ADMIN)
    $attach_allow_download = true;
else
{         //fetch the rules of the forum, and check so that the user is allowed to download.
    $result_attach_two = $db->query('SELECT ar.rules FROM '.$db->prefix.'attach_2_rules AS ar WHERE ar.group_id=\''.$pun_user['group_id'].'\' AND ar.forum_id='.$cur_topic['forum_id'].' LIMIT 1')or error('Unable to fetch rules for the attachments', __FILE__, __LINE__, $db->error());
    if($db->num_rows($result_attach_two)==1)
    {
        list($attach_rules)=$db->fetch_row($result_attach_two);
        $attach_allow_download = attach_rules($attach_rules,ATTACH_DOWNLOAD);
    }
}

while ($cur_post = $db->fetch_assoc($result))
{
    $post_count++;
    $user_avatar = '';
    $user_info = array();
    $user_contacts = array();
    $post_actions = array();
    $is_online = '';
    $signature = '';
    $user_image_award = '';

    // If the poster is a registered user.
    if ($cur_post['poster_id'] > 1)
    {
        // ---------- TB ----------
//        require_once '../tracker/include/bittorrent.php';
        //---- Torrent Stuff
        $uploaded = $cur_post["bt_uploaded"];
        $downloaded = $cur_post["bt_downloaded"];
        
         //----Ratio
        if ($downloaded > 0)
        {
            $ratio = $uploaded / $downloaded;
//            $color = get_ratio_color($ratio);
            $ratio = number_format($ratio, 3);
            if ($color)
              $ratio = "<font style='color:$color;'>$ratio</font>";
        }
        else
            if ($cur_post["uploaded"] > 0)
                 $ratio = "Inf.";
            else
                $ratio = "---";
        // ---------- TB ----------

        // Image Award Mod Block Start
        if(strlen($cur_post['imgaward']) > 0){    // if we have something there, figure out what to output...
            //figure out the size of the award (Name of award should be in the form:  Test_Award_100x20.png ... where png is format, 100x20 is dimensions and Test_Award is name of award (seen in admin interface)
            $awardmod_filename=$cur_post['imgaward'];
            $awardmod_temp=substr($awardmod_filename,strrpos($awardmod_filename,'_')+1); //we still have the file extentsion
            $awardmod_temp=substr($awardmod_temp,0,strpos($awardmod_temp,'.'));
            $awardmod_dimensions = explode('x',$awardmod_temp);    // there ... now the array will hold 100 and 20 in [0] and [1] respecively ... :)
            $awardmod_name=str_replace('_',' ',substr($awardmod_filename,0,strrpos($awardmod_filename,'_')));
            if($pun_config['o_avatars'] == '1' && $pun_user['show_avatars'] != '0')
                $user_image_award = "\t\t\t\t\t".'<dd><img src="img/awards/'.$awardmod_filename.'" width="'.$awardmod_dimensions[0].'" height="'.$awardmod_dimensions[1].'" alt="Award: '.$awardmod_name.'" /></dd>';
            else
                $user_image_award = "\t\t\t\t\t".'<dd>Award: "'.$awardmod_name.'"</dd>';
        }
        // Image Award Mod Block End

        $username = '<a href="profile.php?id='.$cur_post['poster_id'].'">'.pun_htmlspecialchars($cur_post['username']).'</a>';
        $user_title = get_title($cur_post);

        if ($pun_config['o_censoring'] == '1')
            $user_title = censor_words($user_title);

        // Format the online indicator
        $is_online = ($cur_post['is_online'] == $cur_post['poster_id']) ? '<strong>'.$lang_topic['Online'].'</strong>' : $lang_topic['Offline'];

/*        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png" '.$img_size[3].' alt="" />';
        }
        else
            $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/default.gif" alt="" />';
*/

        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            $user_avatar = pun_htmlspecialchars($cur_post['avatar']);
            if(!stristr($user_avatar,"http://"))
                $user_avatar = '<img src="'.$pun_config['o_base_url'].'/'.$user_avatar.'" class="pavatar" alt="'.pun_htmlspecialchars($cur_post['username']).'" />';
            else
                $user_avatar = '<img src="'.$user_avatar.'" alt="" />';
        }
        else
            $user_avatar = '';

        // We only show sex, location, register date, post count and the contact links if "Show user info" is enabled
        if ($pun_config['o_show_user_info'] == '1')
        {
            if ($cur_post['sex'] != '')
                $user_info[] = '<dd>'.$lang_common['Sex'].': '.($cur_post['sex'] == 'male' ? $lang_common['Male'] : $lang_common['Female']);

            if ($cur_post['location'] != '')
            {
                if ($pun_config['o_censoring'] == '1')
                    $cur_post['location'] = censor_words($cur_post['location']);

                $user_info[] = '<dd>'.$lang_topic['From'].': '.pun_htmlspecialchars($cur_post['location']);
            }

            $user_info[] = '<dd>'.$lang_common['Registered'].': '.date($pun_config['o_date_format'], $cur_post['registered']);

            if ($pun_config['o_show_post_count'] == '1' || $pun_user['g_id'] < PUN_GUEST)
                $user_info[] = '<dd>'.$lang_common['Posts'].': '.$cur_post['num_posts'];

            // Now let's deal with the contact links (E-mail and URL)
            if (($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) || $pun_user['g_id'] < PUN_GUEST)
                $user_contacts[] = '<a href="mailto:'.$cur_post['email'].'">'.$lang_common['E-mail'].'</a>';
            else if ($cur_post['email_setting'] == '1' && !$pun_user['is_guest'])
                $user_contacts[] = '<a href="misc.php?email='.$cur_post['poster_id'].'">'.$lang_common['E-mail'].'</a>';

            require(PUN_ROOT.'include/pms/viewtopic_PM-link.php');

            if ($cur_post['url'] != '')
                $user_contacts[] = '<a href="'.pun_htmlspecialchars($cur_post['url']).'">'.$lang_topic['Website'].'</a>';
        }

        if ($pun_user['g_id'] < PUN_GUEST)
        {
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

            if ($cur_post['admin_note'] != '')
                $user_info[] = '<dd>'.$lang_topic['Note'].': <strong>'.pun_htmlspecialchars($cur_post['admin_note']).'</strong>';
        }
    }
    // If the poster is a guest (or a user that has been deleted)
    else
    {
        $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/guest.gif" alt="" />';
        $username = pun_htmlspecialchars($cur_post['username']);
        $user_title = get_title($cur_post);

        if ($pun_user['g_id'] < PUN_GUEST)
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

        if ($pun_config['o_show_user_info'] == '1' && $cur_post['poster_email'] != '' && !$pun_user['is_guest'])
            $user_contacts[] = '<a href="mailto:'.$cur_post['poster_email'].'">'.$lang_common['E-mail'].'</a>';
    }

    // Generation post action array (quote, edit, delete etc.)
    if (!$is_admmod)
    {
        if (!$pun_user['is_guest'])
            $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>';

        if ($cur_topic['closed'] == '0')
        {
            if ($cur_post['poster_id'] == $pun_user['id'])
            {
                if ((($start_from + $post_count) == 1 && $pun_user['g_delete_topics'] == '1') || (($start_from + $post_count) > 1 && $pun_user['g_delete_posts'] == '1'))
                    $post_actions[] = '<li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>';
                if ($pun_user['g_edit_posts'] == '1')
                    $post_actions[] = '<li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>';
            }

            if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1')
                $post_actions[] = '<li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';
        }
    }
    else
        $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>'.$lang_topic['Link separator'].'</li><li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>'.$lang_topic['Link separator'].'</li><li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>'.$lang_topic['Link separator'].'</li><li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';


    // Switch the background color for every message.
    $bg_switch = ($bg_switch) ? $bg_switch = false : $bg_switch = true;
    $vtbg = ($bg_switch) ? ' roweven' : ' rowodd';


    // Perform the main parsing of the message (BBCode, smilies, censor words etc)
    $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);

    // Do signature parsing/caching
    if ($cur_post['signature'] != '' && $pun_user['show_sig'] != '0')
    {
        if (isset($signature_cache[$cur_post['poster_id']]))
            $signature = $signature_cache[$cur_post['poster_id']];
        else
        {
            $signature = parse_signature($cur_post['signature']);
            $signature_cache[$cur_post['poster_id']] = $signature;
        }
    }

    // Attachment Mod Block Start
    $attach_output = '';
    $attach_num = 0;

    // Check if this post has any attachments
for ($i=0; $i < sizeof($att_arr)-1;$i++)
{
    if($att_arr[$i]['post_id'] == $cur_post['id']){
        $attach_num++;
        if($attach_allow_download){//check if the user is allowed to download it.
            $attach_output = $lang_attach['Attachments:'].' ';
            $attachment_extension .= attach_get_extension($att_arr[$i]['filename']);
            $attach_output .= '<br />'."\n\t\t\t\t\t\t".attach_icon($att_arr[$i]['extension']).' <a href="./attachment.php?item='.$att_arr[$i]['id'].'">'.$att_arr[$i]['filename'].'</a>, '.$lang_attach['Size:'].' '.number_format($att_arr[$i]['size']).' '.$lang_attach['bytes'].', '.$lang_attach['Downloads:'].' '.number_format($att_arr[$i]['downloads']);
        }
    }
}    // Attachment Mod Block End

?>
<div id="p<?php echo $cur_post['id'] ?>" class="blockpost<?php echo $vtbg ?><?php if (($post_count + $start_from) == 1) echo ' firstpost'; ?>">
    <h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?> </span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>
    <div class="box">
        <div class="inbox">
            <div class="postleft">
                <dl>
                    <dt><strong><?php echo $username ?></strong></dt>
                    <dd class="usertitle"><strong><?php echo $user_title ?></strong></dd>
                    <?php if (!empty($user_avatar)) echo '<dd class="postavatar">'.$user_avatar.'</dd>'; ?>
                    <?php if (!empty($ratio)) echo '<dd class="ratio">'.$lang_common['Ratio'].': '.$ratio.'</dd>'; ?>
<?php if (strlen($user_image_award)>0) echo $user_image_award; ?>
<?php if (count($user_info)) echo "\t\t\t\t\t".implode('</dd>'."\n\t\t\t\t\t", $user_info).'</dd>'."\n"; ?>
<?php if (count($user_contacts)) echo "\t\t\t\t\t".'<dd class="usercontacts">'.implode('  ', $user_contacts).'</dd>'."\n"; ?>
            <div class="postfootleft"><?php if ($cur_post['poster_id'] > 1) echo '<p>'.$is_online.'</p>'; ?></div>
                </dl>
            </div>
            <div class="postright">
                <h3><?php if (($post_count + $start_from) > 1) echo ' Re: '; ?><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></h3>
                <div class="postmsg">
                    <?php echo $cur_post['message']."\n" ?>
<?php if ($cur_post['edited'] != '') echo "\t\t\t\t\t".'<p class="postedit"><em>'.$lang_topic['Last edit'].' '.pun_htmlspecialchars($cur_post['edited_by']).' ('.format_time($cur_post['edited']).')</em></p>'."\n"; ?>
<?php if ($attach_allow_download && $attach_output != '') echo "\t\t\t\t\t".'<div class="postsignature"><hr />'.$attach_output.'</div>'."\n"; ## Attachment Mod row ?>
<?php if ($signature != '') echo "\t\t\t\t".'<div class="postsignature"><hr />'.$signature.'</div>'."\n"; ?>
                </div>
            </div>
            <div class="clearer"></div>
            <div class="postfootright"><?php echo (count($post_actions)) ? '<ul>'.implode($lang_topic['Link separator'].'</li>', $post_actions).'</li></ul></div>'."\n" : '<div> </div></div>'."\n" ?>
        </div>
    </div>
</div>

<?php

}

?>
<div class="postlinksb">
    <div class="inbox">
        <p class="postlink conr"><?php echo $post_link ?></p>
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <?php echo $subscraction ?>
    </div>
</div>

<?php

// Display quick post if enabled
if ($quickpost)
{

?>
<div class="blockform">
    <h2><span><?php echo $lang_topic['Quick post'] ?></span></h2>
    <div class="box">
            <form id="post" method="post" name="qpost" action="post.php?tid=<?php echo $id ?>" onsubmit="this.submit.disabled=true;if(process_form(this)){return true;}else{this.submit.disabled=false;return false;}">
            <div class="inform">
                <fieldset>
                    <legend><?php echo $lang_common['Write message legend'] ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
                        <?php if ($quickpost_buttons) require PUN_ROOT.'mod_easy_bbcode.php'; ?>
                        <?php require PUN_ROOT.'mod_modern_bbcode.php'; ?>
                        <label><textarea name="req_message" rows="7" cols="75" tabindex="1"></textarea></label>
                        <ul class="bblinks">
                            <li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#smilies" onclick="window.open(this.href); return false;"><?php echo $lang_common['Smilies'] ?></a>: <?php echo ($pun_config['o_smilies'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                        </ul>
                    </div>
                </fieldset>
            </div>
            <p><input type="submit" name="submit" tabindex="2" value="<?php echo $lang_common['Submit'] ?>" accesskey="s" /></p>
        </form>
    </div>
</div>
<?php

}

// Increment "num_views" for topic
$low_prio = ($db_type == 'mysql') ? 'LOW_PRIORITY ' : '';
$db->query('UPDATE '.$low_prio.$db->prefix.'topics SET num_views=num_views+1 WHERE id='.$id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());

$forum_id = $cur_topic['forum_id'];
$footer_style = 'viewtopic';
require PUN_ROOT.'footer.php';

Re: Help with slow query

OK, tell me how this works (or if it doesn't work, what error you get)

<?php
/***********************************************************************

  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)

  This file is part of PunBB.

  PunBB 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.

  PunBB is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  MA  02111-1307  USA

************************************************************************/

// Enable SPELLCHECKER on this page
// Disable it by adding // from the following line (on this page only)
define('PBB_SPELLCHECKER', 1);

define('PUN_ROOT', './');
require PUN_ROOT.'include/common.php';
require PUN_ROOT.'include/attach/attach_incl.php'; //Attachment Mod row, loads variables, functions and lang file


if ($pun_user['g_read_board'] == '0')
    message($lang_common['No view']);


$action = isset($_GET['action']) ? $_GET['action'] : null;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;
if ($id < 1 && $pid < 1)
    message($lang_common['Bad request']);

// Load the viewtopic.php language file
require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';


// If a post ID is specified we determine topic ID and page number so we can redirect to the correct message
if ($pid)
{
    $result = $db->query('SELECT topic_id FROM '.$db->prefix.'posts WHERE id='.$pid) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $id = $db->result($result);

    // Determine on what page the post is located (depending on $pun_user['disp_posts'])
    $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$id.' ORDER BY posted') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $num_posts = $db->num_rows($result);

    for ($i = 0; $i < $num_posts; ++$i)
    {
        $cur_id = $db->result($result, $i);
        if ($cur_id == $pid)
            break;
    }
    ++$i;    // we started at 0

    $_GET['p'] = ceil($i / $pun_user['disp_posts']);
}

// If action=new, we redirect to the first new post (if any)
else if ($action == 'new' && !$pun_user['is_guest'])
{
    $result = $db->query('SELECT MIN(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' AND posted>'.$pun_user['last_visit']) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $first_new_post_id = $db->result($result);

    if ($first_new_post_id)
        header('Location: viewtopic.php?pid='.$first_new_post_id.'#p'.$first_new_post_id);
    else    // If there is no new post, we go to the last post
        header('Location: viewtopic.php?id='.$id.'&action=last');

    exit;
}

// If action=last, we redirect to the last post
else if ($action == 'last')
{
    $result = $db->query('SELECT MAX(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $last_post_id = $db->result($result);

    if ($last_post_id)
    {
        header('Location: viewtopic.php?pid='.$last_post_id.'#p'.$last_post_id);
        exit;
    }
}


// Fetch some info about the topic
if (!$pun_user['is_guest'])
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
else
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

// MOD USERSTATS
$statresult = $db->query('insert into '.$db->prefix.'statviews_all(user_id, topic_id) VALUES (' . $pun_user['id'] . ', '.$id.')') or error('Unable to update view statistics', __FILE__, __LINE__, $db->error());
// MOD USERSTATS

if (!$db->num_rows($result))
    message($lang_common['Bad request']);

$cur_topic = $db->fetch_assoc($result);

// Sort out who the moderators are and if we are currently a moderator (or an admin)
$mods_array = ($cur_topic['moderators'] != '') ? unserialize($cur_topic['moderators']) : array();
$is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_id'] == PUN_MOD && array_key_exists($pun_user['username'], $mods_array))) ? true : false;

// Can we or can we not post replies?
if ($cur_topic['closed'] == '0')
{
    if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1' || $is_admmod)
        $post_link = '<a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
    else
        $post_link = ' ';
}
else
{
    $post_link = $lang_topic['Topic closed'];

    if ($is_admmod)
        $post_link .= ' / <a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
}


// Determine the post offset (based on $_GET['p'])
$num_pages = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);

if(!isset($_GET['p']) || $_GET['p'] <= 1) $p = 1;
else if($_GET['p'] > $num_pages) $p = $num_pages;
else $p = $_GET['p'];
$start_from = $pun_user['disp_posts'] * ($p - 1);

// Generate paging links
$paging_links = $lang_common['Pages'].': '.paginate($num_pages, $p, 'viewtopic.php?id='.$id);


if ($pun_config['o_censoring'] == '1')
    $cur_topic['subject'] = censor_words($cur_topic['subject']);

$quickpost_buttons = false;
if ($pun_config['o_quickpost_buttons'] == '1')
    $quickpost_buttons = true;

$quickpost = false;
if ($pun_config['o_quickpost'] == '1' &&
    !$pun_user['is_guest'] &&
    ($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) &&
    ($cur_topic['closed'] == '0' || $is_admmod))
{
    $required_fields = array('req_message' => $lang_common['Message']);
    $quickpost = true;
}

if (!$pun_user['is_guest'] && $pun_config['o_subscriptions'] == '1')
{
    if ($cur_topic['is_subscribed'])
        // I apologize for the variable naming here. It's a mix of subscription and action I guess :-)
        $subscraction = '<p class="subscribelink clearb">'.$lang_topic['Is subscribed'].' - <a href="misc.php?unsubscribe='.$id.'">'.$lang_topic['Unsubscribe'].'</a></p>'."\n";
    else
        $subscraction = '<p class="subscribelink clearb"><a href="misc.php?subscribe='.$id.'">'.$lang_topic['Subscribe'].'</a></p>'."\n";
}
else
    $subscraction = '<div class="clearer"></div>'."\n";

if ($cur_topic['question'])
    $cur_topic_question = $cur_topic['question'].' - ';
else
    $cur_topic_question = '';

$page_title = pun_htmlspecialchars($pun_config['o_board_title'].' / '.$cur_topic_question . $cur_topic['subject']);
define('PUN_ALLOW_INDEX', 1);
require PUN_ROOT.'header.php';

?>
<div class="linkst">
    <div class="inbox">
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <p class="postlink conr"><?php echo $post_link ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <div class="clearer"></div>
    </div>
</div>

<?php


require PUN_ROOT.'include/parser.php';

// Mod poll begin
if ($cur_topic['question'])
{
    require PUN_ROOT . 'lang/' . $pun_user['language'] . '/polls.php'; 
    // get the poll data
    $result = $db->query('SELECT ptype,options,voters,votes FROM ' . $db->prefix . 'polls WHERE pollid=' . $id . '') or error('Unable to fetch poll info', __FILE__, __LINE__, $db->error());

    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $cur_poll = $db->fetch_assoc($result);

    $options = unserialize($cur_poll['options']);
    if (!empty($cur_poll['voters']))
        $voters = unserialize($cur_poll['voters']);
    else
        $voters = array();

    $ptype = $cur_poll['ptype']; 
    // yay memory!
    // $cur_poll = null;
    $firstcheck = false;
    ?>
<div class="blockform">
    <h2><span><?php echo $lang_polls['Poll'] ?></span></h2>
    <div class="box">
        <?php
    if ((!$pun_user['is_guest']) && (!in_array($pun_user['id'], $voters)) && ($cur_topic['closed'] == '0') && (($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) || $is_admmod)) 
    {
        $showsubmit = true;
        ?>
        <form id="post" method="post" action="vote.php">
            <div class="inform">
                <div class="rbox">
                <fieldset>
                    <legend><?php echo pun_htmlspecialchars($cur_topic['question']) ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="poll_id" value="<?php echo $id; ?>" />
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
    
                        <?php
                        if ($ptype == 1) 
                        {
                            while (list($key, $value) = each($options)) 
                            {
                            ?>
                                <label><input name="vote" <?php if (!$firstcheck) { echo 'checked="checked"'; $firstcheck = true; }; ?> type="radio" value="<?php echo $key ?>" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 2) 
                        {
                            while (list($key, $value) = each($options)) 
                            {         
                            ?>
                                <label><input name="options[<?php echo $key ?>]" type="checkbox" value="1" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 3) 
                        {
                            
                            while (list($key, $value) = each($options)) 
                            {
                                echo pun_htmlspecialchars($value); ?>
                                <label><input name="options[<?php echo $key ?>]" checked="checked" type="radio" value="yes" /> <?php echo $cur_topic['yes']; ?></label>
                                <label><input name="options[<?php echo $key ?>]" type="radio" value="no" /> <?php echo $cur_topic['no']; ?></label>
                                <br />
                            <?php
                            } 
                        } 
                        else
                        {
                            message($lang_common['Bad request']);
                        }
            ?></div></fieldset><?php
    } 
    else 
    {
        $showsubmit = false;
        ?>
        <div class="inform">
        <div class="rbox">
            
            <p class="poll_info"><strong><?php echo pun_htmlspecialchars($cur_topic['question']) ?></strong></p>            
            <?php
            if (!empty($cur_poll['votes']))
                    $votes = unserialize($cur_poll['votes']);
            else
                  $votes = array();
        
            if ($ptype == 1 || $ptype == 2) 
            {
                $total = 0;
                $percent = 0;
                $percent_int = 0;
                while (list($key, $val) = each($options)) 
                {
                    if (isset($votes[$key]))
                        $total += $votes[$key];
                }
                reset($options);
            }
            
              while (list($key, $value) = each($options)) {    

                if ($ptype == 1 || $ptype == 2)
                { 
                    if (isset($votes[$key]))
                    {
                        $percent =  $votes[$key] * 100 / $total;
                        $percent_int = floor($percent);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        <div class="poll_result">
                            <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key])) echo $percent_int/2; else echo '0'; ?>%;" alt="" />
                            <span><?php if (isset($votes[$key])) echo $percent_int . '% - ' . $votes[$key]; else echo '0% - 0'; ?></span>
                        </div>
                <?php
                }
                else if ($ptype == 3) 
                { 
                    $total = 0;
                    $yes_percent = 0;
                    $no_percent = 0;
                    $vote_yes = 0;
                    $vote_no = 0;
                    if (isset($votes[$key]['yes']))
                    {
                        $vote_yes = $votes[$key]['yes'];
                    }

                    if (isset($votes[$key]['no'])) {
                        $vote_no += $votes[$key]['no'];
                    }

                    $total = $vote_yes + $vote_no;
                    if (isset($votes[$key]))
                    {
                        $yes_percent =   floor($vote_yes * 100 / $total);
                        $no_percent = floor($vote_no * 100 / $total);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        
                        <div class="poll_result_yesno">
                            <strong><?php echo $cur_topic['yes']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['yes'])) { echo $yes_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['yes'])) { echo $yes_percent . "% - " . $votes[$key]['yes']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                        <div class="poll_result_yesno">                        
                            <strong><?php echo $cur_topic['no']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['no'])) { echo $no_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['no'])) { echo $no_percent . "% - " . $votes[$key]['no']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                    <?php 
                }
                else
                message($lang_common['Bad request']);
            }     
            ?>
                <p class="poll_info">Total : <?php echo $total; ?></p>
            <?php
        } 
        ?>
            </div>
                
            </div>

            <?php if ($showsubmit == true) 
            { 
                echo '<p><input type="submit" name="submit" tabindex="2" value="' . $lang_common['Submit'] . '" accesskey="s" /> <input type="submit" name="null" tabindex="2" value="' . $lang_polls['Null vote']. '" accesskey="n" /></p>
                </form>';
            } 
            ?>
    </div>
</div>
<?php
}
// Mod poll end

$bg_switch = true;    // Used for switching background color in posts
$post_count = 0;    // Keep track of post numbers

// Retrieve the posts (and their respective poster/online status)
//$result = $db->query('SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.idle=0) WHERE p.topic_id='.$id.' ORDER BY p.id LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error()); //Attachment Mod, changed the true to false...
// ---------- TB ----------
// $result = $db->query('
// SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
//  FROM '.$db->prefix.'posts AS p
//  INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
//  INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
//  LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
//  WHERE p.topic_id='.$id.'
//  ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'
//  LIMIT '.$start_from.','.$pun_user['disp_posts'], false)
//     or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
// ---------- TB ----------

// Start: Mod by Smartys
$p_array = array();
$result = $db->query('SELECT p.id FROM '.$db->prefix.'posts AS p WHERE p.topic_id='.$id.' LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post IDs', __FILE__, __LINE__, $db->error());
while (list($p_id) = $db->fetch_row($result))
{
    $p_array[] = $p_id;
}
$post_ids = implode(",", $p_array); 

$result = $db->query('
SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
FROM '.$db->prefix.'posts AS p
INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
WHERE p.id IN ('.$post_ids.')
ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' '), false)
    or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());

// End: Mod by Smartys

$att_res = $db->query('select af.* from '.$db->prefix.'attach_2_files as af left join '.$db->prefix.'posts as p on af.post_id=p.id where p.topic_id='.$id);
$att_arr = array();
$attach_allow_download = false;

while ($att_arr[] = $db->fetch_assoc($att_res)) {}
if($pun_user['g_id']==PUN_ADMIN)
    $attach_allow_download = true;
else
{         //fetch the rules of the forum, and check so that the user is allowed to download.
    $result_attach_two = $db->query('SELECT ar.rules FROM '.$db->prefix.'attach_2_rules AS ar WHERE ar.group_id=\''.$pun_user['group_id'].'\' AND ar.forum_id='.$cur_topic['forum_id'].' LIMIT 1')or error('Unable to fetch rules for the attachments', __FILE__, __LINE__, $db->error());
    if($db->num_rows($result_attach_two)==1)
    {
        list($attach_rules)=$db->fetch_row($result_attach_two);
        $attach_allow_download = attach_rules($attach_rules,ATTACH_DOWNLOAD);
    }
}

while ($cur_post = $db->fetch_assoc($result))
{
    $post_count++;
    $user_avatar = '';
    $user_info = array();
    $user_contacts = array();
    $post_actions = array();
    $is_online = '';
    $signature = '';
    $user_image_award = '';

    // If the poster is a registered user.
    if ($cur_post['poster_id'] > 1)
    {
        // ---------- TB ----------
//        require_once '../tracker/include/bittorrent.php';
        //---- Torrent Stuff
        $uploaded = $cur_post["bt_uploaded"];
        $downloaded = $cur_post["bt_downloaded"];
        
         //----Ratio
        if ($downloaded > 0)
        {
            $ratio = $uploaded / $downloaded;
//            $color = get_ratio_color($ratio);
            $ratio = number_format($ratio, 3);
            if ($color)
              $ratio = "<font style='color:$color;'>$ratio</font>";
        }
        else
            if ($cur_post["uploaded"] > 0)
                 $ratio = "Inf.";
            else
                $ratio = "---";
        // ---------- TB ----------

        // Image Award Mod Block Start
        if(strlen($cur_post['imgaward']) > 0){    // if we have something there, figure out what to output...
            //figure out the size of the award (Name of award should be in the form:  Test_Award_100x20.png ... where png is format, 100x20 is dimensions and Test_Award is name of award (seen in admin interface)
            $awardmod_filename=$cur_post['imgaward'];
            $awardmod_temp=substr($awardmod_filename,strrpos($awardmod_filename,'_')+1); //we still have the file extentsion
            $awardmod_temp=substr($awardmod_temp,0,strpos($awardmod_temp,'.'));
            $awardmod_dimensions = explode('x',$awardmod_temp);    // there ... now the array will hold 100 and 20 in [0] and [1] respecively ... :)
            $awardmod_name=str_replace('_',' ',substr($awardmod_filename,0,strrpos($awardmod_filename,'_')));
            if($pun_config['o_avatars'] == '1' && $pun_user['show_avatars'] != '0')
                $user_image_award = "\t\t\t\t\t".'<dd><img src="img/awards/'.$awardmod_filename.'" width="'.$awardmod_dimensions[0].'" height="'.$awardmod_dimensions[1].'" alt="Award: '.$awardmod_name.'" /></dd>';
            else
                $user_image_award = "\t\t\t\t\t".'<dd>Award: "'.$awardmod_name.'"</dd>';
        }
        // Image Award Mod Block End

        $username = '<a href="profile.php?id='.$cur_post['poster_id'].'">'.pun_htmlspecialchars($cur_post['username']).'</a>';
        $user_title = get_title($cur_post);

        if ($pun_config['o_censoring'] == '1')
            $user_title = censor_words($user_title);

        // Format the online indicator
        $is_online = ($cur_post['is_online'] == $cur_post['poster_id']) ? '<strong>'.$lang_topic['Online'].'</strong>' : $lang_topic['Offline'];

/*        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png" '.$img_size[3].' alt="" />';
        }
        else
            $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/default.gif" alt="" />';
*/

        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            $user_avatar = pun_htmlspecialchars($cur_post['avatar']);
            if(!stristr($user_avatar,"http://"))
                $user_avatar = '<img src="'.$pun_config['o_base_url'].'/'.$user_avatar.'" class="pavatar" alt="'.pun_htmlspecialchars($cur_post['username']).'" />';
            else
                $user_avatar = '<img src="'.$user_avatar.'" alt="" />';
        }
        else
            $user_avatar = '';

        // We only show sex, location, register date, post count and the contact links if "Show user info" is enabled
        if ($pun_config['o_show_user_info'] == '1')
        {
            if ($cur_post['sex'] != '')
                $user_info[] = '<dd>'.$lang_common['Sex'].': '.($cur_post['sex'] == 'male' ? $lang_common['Male'] : $lang_common['Female']);

            if ($cur_post['location'] != '')
            {
                if ($pun_config['o_censoring'] == '1')
                    $cur_post['location'] = censor_words($cur_post['location']);

                $user_info[] = '<dd>'.$lang_topic['From'].': '.pun_htmlspecialchars($cur_post['location']);
            }

            $user_info[] = '<dd>'.$lang_common['Registered'].': '.date($pun_config['o_date_format'], $cur_post['registered']);

            if ($pun_config['o_show_post_count'] == '1' || $pun_user['g_id'] < PUN_GUEST)
                $user_info[] = '<dd>'.$lang_common['Posts'].': '.$cur_post['num_posts'];

            // Now let's deal with the contact links (E-mail and URL)
            if (($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) || $pun_user['g_id'] < PUN_GUEST)
                $user_contacts[] = '<a href="mailto:'.$cur_post['email'].'">'.$lang_common['E-mail'].'</a>';
            else if ($cur_post['email_setting'] == '1' && !$pun_user['is_guest'])
                $user_contacts[] = '<a href="misc.php?email='.$cur_post['poster_id'].'">'.$lang_common['E-mail'].'</a>';

            require(PUN_ROOT.'include/pms/viewtopic_PM-link.php');

            if ($cur_post['url'] != '')
                $user_contacts[] = '<a href="'.pun_htmlspecialchars($cur_post['url']).'">'.$lang_topic['Website'].'</a>';
        }

        if ($pun_user['g_id'] < PUN_GUEST)
        {
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

            if ($cur_post['admin_note'] != '')
                $user_info[] = '<dd>'.$lang_topic['Note'].': <strong>'.pun_htmlspecialchars($cur_post['admin_note']).'</strong>';
        }
    }
    // If the poster is a guest (or a user that has been deleted)
    else
    {
        $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/guest.gif" alt="" />';
        $username = pun_htmlspecialchars($cur_post['username']);
        $user_title = get_title($cur_post);

        if ($pun_user['g_id'] < PUN_GUEST)
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

        if ($pun_config['o_show_user_info'] == '1' && $cur_post['poster_email'] != '' && !$pun_user['is_guest'])
            $user_contacts[] = '<a href="mailto:'.$cur_post['poster_email'].'">'.$lang_common['E-mail'].'</a>';
    }

    // Generation post action array (quote, edit, delete etc.)
    if (!$is_admmod)
    {
        if (!$pun_user['is_guest'])
            $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>';

        if ($cur_topic['closed'] == '0')
        {
            if ($cur_post['poster_id'] == $pun_user['id'])
            {
                if ((($start_from + $post_count) == 1 && $pun_user['g_delete_topics'] == '1') || (($start_from + $post_count) > 1 && $pun_user['g_delete_posts'] == '1'))
                    $post_actions[] = '<li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>';
                if ($pun_user['g_edit_posts'] == '1')
                    $post_actions[] = '<li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>';
            }

            if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1')
                $post_actions[] = '<li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';
        }
    }
    else
        $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>'.$lang_topic['Link separator'].'</li><li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>'.$lang_topic['Link separator'].'</li><li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>'.$lang_topic['Link separator'].'</li><li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';


    // Switch the background color for every message.
    $bg_switch = ($bg_switch) ? $bg_switch = false : $bg_switch = true;
    $vtbg = ($bg_switch) ? ' roweven' : ' rowodd';


    // Perform the main parsing of the message (BBCode, smilies, censor words etc)
    $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);

    // Do signature parsing/caching
    if ($cur_post['signature'] != '' && $pun_user['show_sig'] != '0')
    {
        if (isset($signature_cache[$cur_post['poster_id']]))
            $signature = $signature_cache[$cur_post['poster_id']];
        else
        {
            $signature = parse_signature($cur_post['signature']);
            $signature_cache[$cur_post['poster_id']] = $signature;
        }
    }

    // Attachment Mod Block Start
    $attach_output = '';
    $attach_num = 0;

    // Check if this post has any attachments
for ($i=0; $i < sizeof($att_arr)-1;$i++)
{
    if($att_arr[$i]['post_id'] == $cur_post['id']){
        $attach_num++;
        if($attach_allow_download){//check if the user is allowed to download it.
            $attach_output = $lang_attach['Attachments:'].' ';
            $attachment_extension .= attach_get_extension($att_arr[$i]['filename']);
            $attach_output .= '<br />'."\n\t\t\t\t\t\t".attach_icon($att_arr[$i]['extension']).' <a href="./attachment.php?item='.$att_arr[$i]['id'].'">'.$att_arr[$i]['filename'].'</a>, '.$lang_attach['Size:'].' '.number_format($att_arr[$i]['size']).' '.$lang_attach['bytes'].', '.$lang_attach['Downloads:'].' '.number_format($att_arr[$i]['downloads']);
        }
    }
}    // Attachment Mod Block End

?>
<div id="p<?php echo $cur_post['id'] ?>" class="blockpost<?php echo $vtbg ?><?php if (($post_count + $start_from) == 1) echo ' firstpost'; ?>">
    <h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?> </span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>
    <div class="box">
        <div class="inbox">
            <div class="postleft">
                <dl>
                    <dt><strong><?php echo $username ?></strong></dt>
                    <dd class="usertitle"><strong><?php echo $user_title ?></strong></dd>
                    <?php if (!empty($user_avatar)) echo '<dd class="postavatar">'.$user_avatar.'</dd>'; ?>
                    <?php if (!empty($ratio)) echo '<dd class="ratio">'.$lang_common['Ratio'].': '.$ratio.'</dd>'; ?>
<?php if (strlen($user_image_award)>0) echo $user_image_award; ?>
<?php if (count($user_info)) echo "\t\t\t\t\t".implode('</dd>'."\n\t\t\t\t\t", $user_info).'</dd>'."\n"; ?>
<?php if (count($user_contacts)) echo "\t\t\t\t\t".'<dd class="usercontacts">'.implode('  ', $user_contacts).'</dd>'."\n"; ?>
            <div class="postfootleft"><?php if ($cur_post['poster_id'] > 1) echo '<p>'.$is_online.'</p>'; ?></div>
                </dl>
            </div>
            <div class="postright">
                <h3><?php if (($post_count + $start_from) > 1) echo ' Re: '; ?><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></h3>
                <div class="postmsg">
                    <?php echo $cur_post['message']."\n" ?>
<?php if ($cur_post['edited'] != '') echo "\t\t\t\t\t".'<p class="postedit"><em>'.$lang_topic['Last edit'].' '.pun_htmlspecialchars($cur_post['edited_by']).' ('.format_time($cur_post['edited']).')</em></p>'."\n"; ?>
<?php if ($attach_allow_download && $attach_output != '') echo "\t\t\t\t\t".'<div class="postsignature"><hr />'.$attach_output.'</div>'."\n"; ## Attachment Mod row ?>
<?php if ($signature != '') echo "\t\t\t\t".'<div class="postsignature"><hr />'.$signature.'</div>'."\n"; ?>
                </div>
            </div>
            <div class="clearer"></div>
            <div class="postfootright"><?php echo (count($post_actions)) ? '<ul>'.implode($lang_topic['Link separator'].'</li>', $post_actions).'</li></ul></div>'."\n" : '<div> </div></div>'."\n" ?>
        </div>
    </div>
</div>

<?php

}

?>
<div class="postlinksb">
    <div class="inbox">
        <p class="postlink conr"><?php echo $post_link ?></p>
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <?php echo $subscraction ?>
    </div>
</div>

<?php

// Display quick post if enabled
if ($quickpost)
{

?>
<div class="blockform">
    <h2><span><?php echo $lang_topic['Quick post'] ?></span></h2>
    <div class="box">
            <form id="post" method="post" name="qpost" action="post.php?tid=<?php echo $id ?>" onsubmit="this.submit.disabled=true;if(process_form(this)){return true;}else{this.submit.disabled=false;return false;}">
            <div class="inform">
                <fieldset>
                    <legend><?php echo $lang_common['Write message legend'] ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
                        <?php if ($quickpost_buttons) require PUN_ROOT.'mod_easy_bbcode.php'; ?>
                        <?php require PUN_ROOT.'mod_modern_bbcode.php'; ?>
                        <label><textarea name="req_message" rows="7" cols="75" tabindex="1"></textarea></label>
                        <ul class="bblinks">
                            <li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#smilies" onclick="window.open(this.href); return false;"><?php echo $lang_common['Smilies'] ?></a>: <?php echo ($pun_config['o_smilies'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                        </ul>
                    </div>
                </fieldset>
            </div>
            <p><input type="submit" name="submit" tabindex="2" value="<?php echo $lang_common['Submit'] ?>" accesskey="s" /></p>
        </form>
    </div>
</div>
<?php

}

// Increment "num_views" for topic
$low_prio = ($db_type == 'mysql') ? 'LOW_PRIORITY ' : '';
$db->query('UPDATE '.$low_prio.$db->prefix.'topics SET num_views=num_views+1 WHERE id='.$id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());

$forum_id = $cur_topic['forum_id'];
$footer_style = 'viewtopic';
require PUN_ROOT.'footer.php';

Re: Help with slow query

That was an impressive change in speed smile
The query that used to take in some cases over 8 seconds is now taking so little time that it's nothing short of amazing.

Time (s)      Query
0.00319     SELECT u.*, g.*, o.logged, o.idle FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.user_id=u.id WHERE u.id=2
0.00135     UPDATE LOW_PRIORITY punbb_online SET logged=1167768040 WHERE user_id=2
0.00108     SELECT topic_id FROM punbb_posts WHERE id='64334'
0.00137     UPDATE punbb_online SET current_page='/forum/viewtopic.php', current_ip='192.168.1.51', current_page_id='691' WHERE user_id='2'
0.00108     SELECT * FROM punbb_online WHERE logged<1167767740
0.00108     SELECT topic_id FROM punbb_posts WHERE id=64334
0.11654     SELECT id FROM punbb_posts WHERE topic_id=691 ORDER BY posted
0.00240     SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=2) LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=691 AND t.moved_to IS NULL
0.00143     insert into punbb_statviews_all(user_id, topic_id) VALUES (2, 691)
0.00210     SELECT (SELECT COUNT(id) FROM bt_peers WHERE userid=2 AND seeder="yes") AS seeders, (SELECT COUNT(id) FROM bt_peers WHERE userid=2 AND seeder="no") AS leechers
0.00097     SELECT COUNT(id) FROM punbb_reports WHERE zapped IS NULL
0.00115     SELECT COUNT(id) FROM punbb_messages WHERE showed=0 AND owner=2
0.00122     SELECT p.id FROM punbb_posts AS p WHERE p.topic_id=691 LIMIT 21675,25
0.01412     SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.id IN (64306,64308,64310,64313,64323,64324,64328,64334) ORDER BY p.id
0.00103     select af.* from punbb_attach_2_files as af left join punbb_posts as p on af.post_id=p.id where p.topic_id=691
0.00145     SELECT search_for, replace_with FROM punbb_censoring
0.00173     UPDATE LOW_PRIORITY punbb_topics SET num_views=num_views+1 WHERE id=691
Total query time: 0.15329 s

My thanks for the help.
Now all I have to find is the PHP code bottleneck that makes the page take 12 seconds to render.

You wouldn't have another rabbit in your top hat for that would you? wink

Re: Help with slow query

Ooops. Spoke too soon, the query isn't returning the correct results. Some posts aren't showing up.
Let me try to find out what's happening and I'll post it here.

Re: Help with slow query

Oh dear, that's not good hmm

Re: Help with slow query

OK, hopefully this should fix it (although it will probably be slower)

<?php
/***********************************************************************

  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)

  This file is part of PunBB.

  PunBB 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.

  PunBB is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  MA  02111-1307  USA

************************************************************************/

// Enable SPELLCHECKER on this page
// Disable it by adding // from the following line (on this page only)
define('PBB_SPELLCHECKER', 1);

define('PUN_ROOT', './');
require PUN_ROOT.'include/common.php';
require PUN_ROOT.'include/attach/attach_incl.php'; //Attachment Mod row, loads variables, functions and lang file


if ($pun_user['g_read_board'] == '0')
    message($lang_common['No view']);


$action = isset($_GET['action']) ? $_GET['action'] : null;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;
if ($id < 1 && $pid < 1)
    message($lang_common['Bad request']);

// Load the viewtopic.php language file
require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';


// If a post ID is specified we determine topic ID and page number so we can redirect to the correct message
if ($pid)
{
    $result = $db->query('SELECT topic_id FROM '.$db->prefix.'posts WHERE id='.$pid) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $id = $db->result($result);

    // Determine on what page the post is located (depending on $pun_user['disp_posts'])
    $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$id.' ORDER BY posted') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $num_posts = $db->num_rows($result);

    for ($i = 0; $i < $num_posts; ++$i)
    {
        $cur_id = $db->result($result, $i);
        if ($cur_id == $pid)
            break;
    }
    ++$i;    // we started at 0

    $_GET['p'] = ceil($i / $pun_user['disp_posts']);
}

// If action=new, we redirect to the first new post (if any)
else if ($action == 'new' && !$pun_user['is_guest'])
{
    $result = $db->query('SELECT MIN(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' AND posted>'.$pun_user['last_visit']) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $first_new_post_id = $db->result($result);

    if ($first_new_post_id)
        header('Location: viewtopic.php?pid='.$first_new_post_id.'#p'.$first_new_post_id);
    else    // If there is no new post, we go to the last post
        header('Location: viewtopic.php?id='.$id.'&action=last');

    exit;
}

// If action=last, we redirect to the last post
else if ($action == 'last')
{
    $result = $db->query('SELECT MAX(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $last_post_id = $db->result($result);

    if ($last_post_id)
    {
        header('Location: viewtopic.php?pid='.$last_post_id.'#p'.$last_post_id);
        exit;
    }
}


// Fetch some info about the topic
if (!$pun_user['is_guest'])
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
else
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

// MOD USERSTATS
$statresult = $db->query('insert into '.$db->prefix.'statviews_all(user_id, topic_id) VALUES (' . $pun_user['id'] . ', '.$id.')') or error('Unable to update view statistics', __FILE__, __LINE__, $db->error());
// MOD USERSTATS

if (!$db->num_rows($result))
    message($lang_common['Bad request']);

$cur_topic = $db->fetch_assoc($result);

// Sort out who the moderators are and if we are currently a moderator (or an admin)
$mods_array = ($cur_topic['moderators'] != '') ? unserialize($cur_topic['moderators']) : array();
$is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_id'] == PUN_MOD && array_key_exists($pun_user['username'], $mods_array))) ? true : false;

// Can we or can we not post replies?
if ($cur_topic['closed'] == '0')
{
    if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1' || $is_admmod)
        $post_link = '<a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
    else
        $post_link = ' ';
}
else
{
    $post_link = $lang_topic['Topic closed'];

    if ($is_admmod)
        $post_link .= ' / <a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
}


// Determine the post offset (based on $_GET['p'])
$num_pages = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);

if(!isset($_GET['p']) || $_GET['p'] <= 1) $p = 1;
else if($_GET['p'] > $num_pages) $p = $num_pages;
else $p = $_GET['p'];
$start_from = $pun_user['disp_posts'] * ($p - 1);

// Generate paging links
$paging_links = $lang_common['Pages'].': '.paginate($num_pages, $p, 'viewtopic.php?id='.$id);


if ($pun_config['o_censoring'] == '1')
    $cur_topic['subject'] = censor_words($cur_topic['subject']);

$quickpost_buttons = false;
if ($pun_config['o_quickpost_buttons'] == '1')
    $quickpost_buttons = true;

$quickpost = false;
if ($pun_config['o_quickpost'] == '1' &&
    !$pun_user['is_guest'] &&
    ($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) &&
    ($cur_topic['closed'] == '0' || $is_admmod))
{
    $required_fields = array('req_message' => $lang_common['Message']);
    $quickpost = true;
}

if (!$pun_user['is_guest'] && $pun_config['o_subscriptions'] == '1')
{
    if ($cur_topic['is_subscribed'])
        // I apologize for the variable naming here. It's a mix of subscription and action I guess :-)
        $subscraction = '<p class="subscribelink clearb">'.$lang_topic['Is subscribed'].' - <a href="misc.php?unsubscribe='.$id.'">'.$lang_topic['Unsubscribe'].'</a></p>'."\n";
    else
        $subscraction = '<p class="subscribelink clearb"><a href="misc.php?subscribe='.$id.'">'.$lang_topic['Subscribe'].'</a></p>'."\n";
}
else
    $subscraction = '<div class="clearer"></div>'."\n";

if ($cur_topic['question'])
    $cur_topic_question = $cur_topic['question'].' - ';
else
    $cur_topic_question = '';

$page_title = pun_htmlspecialchars($pun_config['o_board_title'].' / '.$cur_topic_question . $cur_topic['subject']);
define('PUN_ALLOW_INDEX', 1);
require PUN_ROOT.'header.php';

?>
<div class="linkst">
    <div class="inbox">
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <p class="postlink conr"><?php echo $post_link ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <div class="clearer"></div>
    </div>
</div>

<?php


require PUN_ROOT.'include/parser.php';

// Mod poll begin
if ($cur_topic['question'])
{
    require PUN_ROOT . 'lang/' . $pun_user['language'] . '/polls.php'; 
    // get the poll data
    $result = $db->query('SELECT ptype,options,voters,votes FROM ' . $db->prefix . 'polls WHERE pollid=' . $id . '') or error('Unable to fetch poll info', __FILE__, __LINE__, $db->error());

    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $cur_poll = $db->fetch_assoc($result);

    $options = unserialize($cur_poll['options']);
    if (!empty($cur_poll['voters']))
        $voters = unserialize($cur_poll['voters']);
    else
        $voters = array();

    $ptype = $cur_poll['ptype']; 
    // yay memory!
    // $cur_poll = null;
    $firstcheck = false;
    ?>
<div class="blockform">
    <h2><span><?php echo $lang_polls['Poll'] ?></span></h2>
    <div class="box">
        <?php
    if ((!$pun_user['is_guest']) && (!in_array($pun_user['id'], $voters)) && ($cur_topic['closed'] == '0') && (($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) || $is_admmod)) 
    {
        $showsubmit = true;
        ?>
        <form id="post" method="post" action="vote.php">
            <div class="inform">
                <div class="rbox">
                <fieldset>
                    <legend><?php echo pun_htmlspecialchars($cur_topic['question']) ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="poll_id" value="<?php echo $id; ?>" />
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
    
                        <?php
                        if ($ptype == 1) 
                        {
                            while (list($key, $value) = each($options)) 
                            {
                            ?>
                                <label><input name="vote" <?php if (!$firstcheck) { echo 'checked="checked"'; $firstcheck = true; }; ?> type="radio" value="<?php echo $key ?>" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 2) 
                        {
                            while (list($key, $value) = each($options)) 
                            {         
                            ?>
                                <label><input name="options[<?php echo $key ?>]" type="checkbox" value="1" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 3) 
                        {
                            
                            while (list($key, $value) = each($options)) 
                            {
                                echo pun_htmlspecialchars($value); ?>
                                <label><input name="options[<?php echo $key ?>]" checked="checked" type="radio" value="yes" /> <?php echo $cur_topic['yes']; ?></label>
                                <label><input name="options[<?php echo $key ?>]" type="radio" value="no" /> <?php echo $cur_topic['no']; ?></label>
                                <br />
                            <?php
                            } 
                        } 
                        else
                        {
                            message($lang_common['Bad request']);
                        }
            ?></div></fieldset><?php
    } 
    else 
    {
        $showsubmit = false;
        ?>
        <div class="inform">
        <div class="rbox">
            
            <p class="poll_info"><strong><?php echo pun_htmlspecialchars($cur_topic['question']) ?></strong></p>            
            <?php
            if (!empty($cur_poll['votes']))
                    $votes = unserialize($cur_poll['votes']);
            else
                  $votes = array();
        
            if ($ptype == 1 || $ptype == 2) 
            {
                $total = 0;
                $percent = 0;
                $percent_int = 0;
                while (list($key, $val) = each($options)) 
                {
                    if (isset($votes[$key]))
                        $total += $votes[$key];
                }
                reset($options);
            }
            
              while (list($key, $value) = each($options)) {    

                if ($ptype == 1 || $ptype == 2)
                { 
                    if (isset($votes[$key]))
                    {
                        $percent =  $votes[$key] * 100 / $total;
                        $percent_int = floor($percent);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        <div class="poll_result">
                            <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key])) echo $percent_int/2; else echo '0'; ?>%;" alt="" />
                            <span><?php if (isset($votes[$key])) echo $percent_int . '% - ' . $votes[$key]; else echo '0% - 0'; ?></span>
                        </div>
                <?php
                }
                else if ($ptype == 3) 
                { 
                    $total = 0;
                    $yes_percent = 0;
                    $no_percent = 0;
                    $vote_yes = 0;
                    $vote_no = 0;
                    if (isset($votes[$key]['yes']))
                    {
                        $vote_yes = $votes[$key]['yes'];
                    }

                    if (isset($votes[$key]['no'])) {
                        $vote_no += $votes[$key]['no'];
                    }

                    $total = $vote_yes + $vote_no;
                    if (isset($votes[$key]))
                    {
                        $yes_percent =   floor($vote_yes * 100 / $total);
                        $no_percent = floor($vote_no * 100 / $total);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        
                        <div class="poll_result_yesno">
                            <strong><?php echo $cur_topic['yes']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['yes'])) { echo $yes_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['yes'])) { echo $yes_percent . "% - " . $votes[$key]['yes']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                        <div class="poll_result_yesno">                        
                            <strong><?php echo $cur_topic['no']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['no'])) { echo $no_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['no'])) { echo $no_percent . "% - " . $votes[$key]['no']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                    <?php 
                }
                else
                message($lang_common['Bad request']);
            }     
            ?>
                <p class="poll_info">Total : <?php echo $total; ?></p>
            <?php
        } 
        ?>
            </div>
                
            </div>

            <?php if ($showsubmit == true) 
            { 
                echo '<p><input type="submit" name="submit" tabindex="2" value="' . $lang_common['Submit'] . '" accesskey="s" /> <input type="submit" name="null" tabindex="2" value="' . $lang_polls['Null vote']. '" accesskey="n" /></p>
                </form>';
            } 
            ?>
    </div>
</div>
<?php
}
// Mod poll end

$bg_switch = true;    // Used for switching background color in posts
$post_count = 0;    // Keep track of post numbers

// Retrieve the posts (and their respective poster/online status)
//$result = $db->query('SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.idle=0) WHERE p.topic_id='.$id.' ORDER BY p.id LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error()); //Attachment Mod, changed the true to false...
// ---------- TB ----------
// $result = $db->query('
// SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
//  FROM '.$db->prefix.'posts AS p
//  INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
//  INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
//  LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
//  WHERE p.topic_id='.$id.'
//  ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'
//  LIMIT '.$start_from.','.$pun_user['disp_posts'], false)
//     or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
// ---------- TB ----------

// Start: Mod by Smartys
$p_array = array();
$result = $db->query('SELECT p.id FROM '.$db->prefix.'posts AS p WHERE p.topic_id='.$id.' ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post IDs', __FILE__, __LINE__, $db->error());
while (list($p_id) = $db->fetch_row($result))
{
    $p_array[] = $p_id;
}
$post_ids = implode(",", $p_array); 

$result = $db->query('
SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
FROM '.$db->prefix.'posts AS p
INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
WHERE p.id IN ('.$post_ids.')
ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' '), false)
    or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());

// End: Mod by Smartys

$att_res = $db->query('select af.* from '.$db->prefix.'attach_2_files as af left join '.$db->prefix.'posts as p on af.post_id=p.id where p.topic_id='.$id);
$att_arr = array();
$attach_allow_download = false;

while ($att_arr[] = $db->fetch_assoc($att_res)) {}
if($pun_user['g_id']==PUN_ADMIN)
    $attach_allow_download = true;
else
{         //fetch the rules of the forum, and check so that the user is allowed to download.
    $result_attach_two = $db->query('SELECT ar.rules FROM '.$db->prefix.'attach_2_rules AS ar WHERE ar.group_id=\''.$pun_user['group_id'].'\' AND ar.forum_id='.$cur_topic['forum_id'].' LIMIT 1')or error('Unable to fetch rules for the attachments', __FILE__, __LINE__, $db->error());
    if($db->num_rows($result_attach_two)==1)
    {
        list($attach_rules)=$db->fetch_row($result_attach_two);
        $attach_allow_download = attach_rules($attach_rules,ATTACH_DOWNLOAD);
    }
}

while ($cur_post = $db->fetch_assoc($result))
{
    $post_count++;
    $user_avatar = '';
    $user_info = array();
    $user_contacts = array();
    $post_actions = array();
    $is_online = '';
    $signature = '';
    $user_image_award = '';

    // If the poster is a registered user.
    if ($cur_post['poster_id'] > 1)
    {
        // ---------- TB ----------
//        require_once '../tracker/include/bittorrent.php';
        //---- Torrent Stuff
        $uploaded = $cur_post["bt_uploaded"];
        $downloaded = $cur_post["bt_downloaded"];
        
         //----Ratio
        if ($downloaded > 0)
        {
            $ratio = $uploaded / $downloaded;
//            $color = get_ratio_color($ratio);
            $ratio = number_format($ratio, 3);
            if ($color)
              $ratio = "<font style='color:$color;'>$ratio</font>";
        }
        else
            if ($cur_post["uploaded"] > 0)
                 $ratio = "Inf.";
            else
                $ratio = "---";
        // ---------- TB ----------

        // Image Award Mod Block Start
        if(strlen($cur_post['imgaward']) > 0){    // if we have something there, figure out what to output...
            //figure out the size of the award (Name of award should be in the form:  Test_Award_100x20.png ... where png is format, 100x20 is dimensions and Test_Award is name of award (seen in admin interface)
            $awardmod_filename=$cur_post['imgaward'];
            $awardmod_temp=substr($awardmod_filename,strrpos($awardmod_filename,'_')+1); //we still have the file extentsion
            $awardmod_temp=substr($awardmod_temp,0,strpos($awardmod_temp,'.'));
            $awardmod_dimensions = explode('x',$awardmod_temp);    // there ... now the array will hold 100 and 20 in [0] and [1] respecively ... :)
            $awardmod_name=str_replace('_',' ',substr($awardmod_filename,0,strrpos($awardmod_filename,'_')));
            if($pun_config['o_avatars'] == '1' && $pun_user['show_avatars'] != '0')
                $user_image_award = "\t\t\t\t\t".'<dd><img src="img/awards/'.$awardmod_filename.'" width="'.$awardmod_dimensions[0].'" height="'.$awardmod_dimensions[1].'" alt="Award: '.$awardmod_name.'" /></dd>';
            else
                $user_image_award = "\t\t\t\t\t".'<dd>Award: "'.$awardmod_name.'"</dd>';
        }
        // Image Award Mod Block End

        $username = '<a href="profile.php?id='.$cur_post['poster_id'].'">'.pun_htmlspecialchars($cur_post['username']).'</a>';
        $user_title = get_title($cur_post);

        if ($pun_config['o_censoring'] == '1')
            $user_title = censor_words($user_title);

        // Format the online indicator
        $is_online = ($cur_post['is_online'] == $cur_post['poster_id']) ? '<strong>'.$lang_topic['Online'].'</strong>' : $lang_topic['Offline'];

/*        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png" '.$img_size[3].' alt="" />';
        }
        else
            $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/default.gif" alt="" />';
*/

        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            $user_avatar = pun_htmlspecialchars($cur_post['avatar']);
            if(!stristr($user_avatar,"http://"))
                $user_avatar = '<img src="'.$pun_config['o_base_url'].'/'.$user_avatar.'" class="pavatar" alt="'.pun_htmlspecialchars($cur_post['username']).'" />';
            else
                $user_avatar = '<img src="'.$user_avatar.'" alt="" />';
        }
        else
            $user_avatar = '';

        // We only show sex, location, register date, post count and the contact links if "Show user info" is enabled
        if ($pun_config['o_show_user_info'] == '1')
        {
            if ($cur_post['sex'] != '')
                $user_info[] = '<dd>'.$lang_common['Sex'].': '.($cur_post['sex'] == 'male' ? $lang_common['Male'] : $lang_common['Female']);

            if ($cur_post['location'] != '')
            {
                if ($pun_config['o_censoring'] == '1')
                    $cur_post['location'] = censor_words($cur_post['location']);

                $user_info[] = '<dd>'.$lang_topic['From'].': '.pun_htmlspecialchars($cur_post['location']);
            }

            $user_info[] = '<dd>'.$lang_common['Registered'].': '.date($pun_config['o_date_format'], $cur_post['registered']);

            if ($pun_config['o_show_post_count'] == '1' || $pun_user['g_id'] < PUN_GUEST)
                $user_info[] = '<dd>'.$lang_common['Posts'].': '.$cur_post['num_posts'];

            // Now let's deal with the contact links (E-mail and URL)
            if (($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) || $pun_user['g_id'] < PUN_GUEST)
                $user_contacts[] = '<a href="mailto:'.$cur_post['email'].'">'.$lang_common['E-mail'].'</a>';
            else if ($cur_post['email_setting'] == '1' && !$pun_user['is_guest'])
                $user_contacts[] = '<a href="misc.php?email='.$cur_post['poster_id'].'">'.$lang_common['E-mail'].'</a>';

            require(PUN_ROOT.'include/pms/viewtopic_PM-link.php');

            if ($cur_post['url'] != '')
                $user_contacts[] = '<a href="'.pun_htmlspecialchars($cur_post['url']).'">'.$lang_topic['Website'].'</a>';
        }

        if ($pun_user['g_id'] < PUN_GUEST)
        {
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

            if ($cur_post['admin_note'] != '')
                $user_info[] = '<dd>'.$lang_topic['Note'].': <strong>'.pun_htmlspecialchars($cur_post['admin_note']).'</strong>';
        }
    }
    // If the poster is a guest (or a user that has been deleted)
    else
    {
        $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/guest.gif" alt="" />';
        $username = pun_htmlspecialchars($cur_post['username']);
        $user_title = get_title($cur_post);

        if ($pun_user['g_id'] < PUN_GUEST)
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

        if ($pun_config['o_show_user_info'] == '1' && $cur_post['poster_email'] != '' && !$pun_user['is_guest'])
            $user_contacts[] = '<a href="mailto:'.$cur_post['poster_email'].'">'.$lang_common['E-mail'].'</a>';
    }

    // Generation post action array (quote, edit, delete etc.)
    if (!$is_admmod)
    {
        if (!$pun_user['is_guest'])
            $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>';

        if ($cur_topic['closed'] == '0')
        {
            if ($cur_post['poster_id'] == $pun_user['id'])
            {
                if ((($start_from + $post_count) == 1 && $pun_user['g_delete_topics'] == '1') || (($start_from + $post_count) > 1 && $pun_user['g_delete_posts'] == '1'))
                    $post_actions[] = '<li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>';
                if ($pun_user['g_edit_posts'] == '1')
                    $post_actions[] = '<li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>';
            }

            if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1')
                $post_actions[] = '<li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';
        }
    }
    else
        $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>'.$lang_topic['Link separator'].'</li><li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>'.$lang_topic['Link separator'].'</li><li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>'.$lang_topic['Link separator'].'</li><li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';


    // Switch the background color for every message.
    $bg_switch = ($bg_switch) ? $bg_switch = false : $bg_switch = true;
    $vtbg = ($bg_switch) ? ' roweven' : ' rowodd';


    // Perform the main parsing of the message (BBCode, smilies, censor words etc)
    $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);

    // Do signature parsing/caching
    if ($cur_post['signature'] != '' && $pun_user['show_sig'] != '0')
    {
        if (isset($signature_cache[$cur_post['poster_id']]))
            $signature = $signature_cache[$cur_post['poster_id']];
        else
        {
            $signature = parse_signature($cur_post['signature']);
            $signature_cache[$cur_post['poster_id']] = $signature;
        }
    }

    // Attachment Mod Block Start
    $attach_output = '';
    $attach_num = 0;

    // Check if this post has any attachments
for ($i=0; $i < sizeof($att_arr)-1;$i++)
{
    if($att_arr[$i]['post_id'] == $cur_post['id']){
        $attach_num++;
        if($attach_allow_download){//check if the user is allowed to download it.
            $attach_output = $lang_attach['Attachments:'].' ';
            $attachment_extension .= attach_get_extension($att_arr[$i]['filename']);
            $attach_output .= '<br />'."\n\t\t\t\t\t\t".attach_icon($att_arr[$i]['extension']).' <a href="./attachment.php?item='.$att_arr[$i]['id'].'">'.$att_arr[$i]['filename'].'</a>, '.$lang_attach['Size:'].' '.number_format($att_arr[$i]['size']).' '.$lang_attach['bytes'].', '.$lang_attach['Downloads:'].' '.number_format($att_arr[$i]['downloads']);
        }
    }
}    // Attachment Mod Block End

?>
<div id="p<?php echo $cur_post['id'] ?>" class="blockpost<?php echo $vtbg ?><?php if (($post_count + $start_from) == 1) echo ' firstpost'; ?>">
    <h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?> </span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>
    <div class="box">
        <div class="inbox">
            <div class="postleft">
                <dl>
                    <dt><strong><?php echo $username ?></strong></dt>
                    <dd class="usertitle"><strong><?php echo $user_title ?></strong></dd>
                    <?php if (!empty($user_avatar)) echo '<dd class="postavatar">'.$user_avatar.'</dd>'; ?>
                    <?php if (!empty($ratio)) echo '<dd class="ratio">'.$lang_common['Ratio'].': '.$ratio.'</dd>'; ?>
<?php if (strlen($user_image_award)>0) echo $user_image_award; ?>
<?php if (count($user_info)) echo "\t\t\t\t\t".implode('</dd>'."\n\t\t\t\t\t", $user_info).'</dd>'."\n"; ?>
<?php if (count($user_contacts)) echo "\t\t\t\t\t".'<dd class="usercontacts">'.implode('  ', $user_contacts).'</dd>'."\n"; ?>
            <div class="postfootleft"><?php if ($cur_post['poster_id'] > 1) echo '<p>'.$is_online.'</p>'; ?></div>
                </dl>
            </div>
            <div class="postright">
                <h3><?php if (($post_count + $start_from) > 1) echo ' Re: '; ?><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></h3>
                <div class="postmsg">
                    <?php echo $cur_post['message']."\n" ?>
<?php if ($cur_post['edited'] != '') echo "\t\t\t\t\t".'<p class="postedit"><em>'.$lang_topic['Last edit'].' '.pun_htmlspecialchars($cur_post['edited_by']).' ('.format_time($cur_post['edited']).')</em></p>'."\n"; ?>
<?php if ($attach_allow_download && $attach_output != '') echo "\t\t\t\t\t".'<div class="postsignature"><hr />'.$attach_output.'</div>'."\n"; ## Attachment Mod row ?>
<?php if ($signature != '') echo "\t\t\t\t".'<div class="postsignature"><hr />'.$signature.'</div>'."\n"; ?>
                </div>
            </div>
            <div class="clearer"></div>
            <div class="postfootright"><?php echo (count($post_actions)) ? '<ul>'.implode($lang_topic['Link separator'].'</li>', $post_actions).'</li></ul></div>'."\n" : '<div> </div></div>'."\n" ?>
        </div>
    </div>
</div>

<?php

}

?>
<div class="postlinksb">
    <div class="inbox">
        <p class="postlink conr"><?php echo $post_link ?></p>
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <?php echo $subscraction ?>
    </div>
</div>

<?php

// Display quick post if enabled
if ($quickpost)
{

?>
<div class="blockform">
    <h2><span><?php echo $lang_topic['Quick post'] ?></span></h2>
    <div class="box">
            <form id="post" method="post" name="qpost" action="post.php?tid=<?php echo $id ?>" onsubmit="this.submit.disabled=true;if(process_form(this)){return true;}else{this.submit.disabled=false;return false;}">
            <div class="inform">
                <fieldset>
                    <legend><?php echo $lang_common['Write message legend'] ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
                        <?php if ($quickpost_buttons) require PUN_ROOT.'mod_easy_bbcode.php'; ?>
                        <?php require PUN_ROOT.'mod_modern_bbcode.php'; ?>
                        <label><textarea name="req_message" rows="7" cols="75" tabindex="1"></textarea></label>
                        <ul class="bblinks">
                            <li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#smilies" onclick="window.open(this.href); return false;"><?php echo $lang_common['Smilies'] ?></a>: <?php echo ($pun_config['o_smilies'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                        </ul>
                    </div>
                </fieldset>
            </div>
            <p><input type="submit" name="submit" tabindex="2" value="<?php echo $lang_common['Submit'] ?>" accesskey="s" /></p>
        </form>
    </div>
</div>
<?php

}

// Increment "num_views" for topic
$low_prio = ($db_type == 'mysql') ? 'LOW_PRIORITY ' : '';
$db->query('UPDATE '.$low_prio.$db->prefix.'topics SET num_views=num_views+1 WHERE id='.$id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());

$forum_id = $cur_topic['forum_id'];
$footer_style = 'viewtopic';
require PUN_ROOT.'footer.php';

Re: Help with slow query

The times are still pretty good:

Time (s) Query 
0.00323 SELECT u.*, g.*, o.logged, o.idle FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.user_id=u.id WHERE u.id=2 
0.00145 INSERT INTO punbb_statuser (user_id, user_ip) VALUES(2,"192.168.1.51") 
0.00143 UPDATE LOW_PRIORITY punbb_online SET logged=1167780249, idle=0 WHERE user_id=2 
0.00172 SELECT topic_id FROM punbb_posts WHERE id='64360' 
0.00140 UPDATE punbb_online SET current_page='/forum/viewtopic.php', current_ip='192.168.1.51', current_page_id='691' WHERE user_id='2' 
0.00176 SELECT * FROM punbb_online WHERE logged<1167779949 
0.00107 SELECT topic_id FROM punbb_posts WHERE id=64360 
0.11582 SELECT id FROM punbb_posts WHERE topic_id=691 ORDER BY posted 
0.00240 SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=2) LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=691 AND t.moved_to IS NULL 
0.00144 insert into punbb_statviews_all(user_id, topic_id) VALUES (2, 691) 
0.00212 SELECT (SELECT COUNT(id) FROM bt_peers WHERE userid=2 AND seeder="yes") AS seeders, (SELECT COUNT(id) FROM bt_peers WHERE userid=2 AND seeder="no") AS leechers 
0.00098 SELECT COUNT(id) FROM punbb_reports WHERE zapped IS NULL 
0.00100 SELECT COUNT(id) FROM punbb_messages WHERE showed=0 AND owner=2 
0.00130 SELECT p.id FROM punbb_posts AS p WHERE p.topic_id=691 ORDER BY p.id LIMIT 21675,25 
0.01706 SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.id IN (64306,64308,64310,64313,64323,64324,64328,64334,64353,64354,64356,64358,64360,64362) ORDER BY p.id  
0.00117 select af.* from punbb_attach_2_files as af left join punbb_posts as p on af.post_id=p.id where p.topic_id=691 
0.00151 SELECT search_for, replace_with FROM punbb_censoring 
0.00193 UPDATE LOW_PRIORITY punbb_topics SET num_views=num_views+1 WHERE id=691 
Total query time: 0.15879 s

AND I can see all the posts smile
Now all it remains is find out why the page is taking 12s to generate when the SQL is taking less than 1.

Re: Help with slow query

Glad to see it works fine now smile
I have a feeling I know why the 12 seconds happens: does it take that long if you don't use to a pid= link?

Re: Help with slow query

Aha! Got it in one. That _is_ strange.
If I use id= it takes about 2.7s (still high, I mean, over 2 seconds to generate a page? but I can live with it if I must) however if I use a pid it takes about 12s.

Re: Help with slow query

OK, I might have a fix for that too: tell me if this works/doesn't

<?php
/***********************************************************************

  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)

  This file is part of PunBB.

  PunBB 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.

  PunBB is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  MA  02111-1307  USA

************************************************************************/

// Enable SPELLCHECKER on this page
// Disable it by adding // from the following line (on this page only)
define('PBB_SPELLCHECKER', 1);

define('PUN_ROOT', './');
require PUN_ROOT.'include/common.php';
require PUN_ROOT.'include/attach/attach_incl.php'; //Attachment Mod row, loads variables, functions and lang file


if ($pun_user['g_read_board'] == '0')
    message($lang_common['No view']);


$action = isset($_GET['action']) ? $_GET['action'] : null;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;
if ($id < 1 && $pid < 1)
    message($lang_common['Bad request']);

// Load the viewtopic.php language file
require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';


// If a post ID is specified we determine topic ID and page number so we can redirect to the correct message
if ($pid)
{
    $result = $db->query('SELECT topic_id, posted FROM '.$db->prefix.'posts WHERE id='.$pid) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    list($id, $posted) = $db->fetch_row($result);

    // Determine on what page the post is located (depending on $pun_user['disp_posts'])
    $result = $db->query('SELECT count(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' and posted <= '.$posted) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $post_number = $db->result($result);

    $_GET['p'] = ceil($post_number / $pun_user['disp_posts']);
}

// If action=new, we redirect to the first new post (if any)
else if ($action == 'new' && !$pun_user['is_guest'])
{
    $result = $db->query('SELECT MIN(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' AND posted>'.$pun_user['last_visit']) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $first_new_post_id = $db->result($result);

    if ($first_new_post_id)
        header('Location: viewtopic.php?pid='.$first_new_post_id.'#p'.$first_new_post_id);
    else    // If there is no new post, we go to the last post
        header('Location: viewtopic.php?id='.$id.'&action=last');

    exit;
}

// If action=last, we redirect to the last post
else if ($action == 'last')
{
    $result = $db->query('SELECT MAX(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $last_post_id = $db->result($result);

    if ($last_post_id)
    {
        header('Location: viewtopic.php?pid='.$last_post_id.'#p'.$last_post_id);
        exit;
    }
}


// Fetch some info about the topic
if (!$pun_user['is_guest'])
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
else
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, t.question, t.yes, t.no, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

// MOD USERSTATS
$statresult = $db->query('insert into '.$db->prefix.'statviews_all(user_id, topic_id) VALUES (' . $pun_user['id'] . ', '.$id.')') or error('Unable to update view statistics', __FILE__, __LINE__, $db->error());
// MOD USERSTATS

if (!$db->num_rows($result))
    message($lang_common['Bad request']);

$cur_topic = $db->fetch_assoc($result);

// Sort out who the moderators are and if we are currently a moderator (or an admin)
$mods_array = ($cur_topic['moderators'] != '') ? unserialize($cur_topic['moderators']) : array();
$is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_id'] == PUN_MOD && array_key_exists($pun_user['username'], $mods_array))) ? true : false;

// Can we or can we not post replies?
if ($cur_topic['closed'] == '0')
{
    if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1' || $is_admmod)
        $post_link = '<a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
    else
        $post_link = ' ';
}
else
{
    $post_link = $lang_topic['Topic closed'];

    if ($is_admmod)
        $post_link .= ' / <a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
}


// Determine the post offset (based on $_GET['p'])
$num_pages = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);

if(!isset($_GET['p']) || $_GET['p'] <= 1) $p = 1;
else if($_GET['p'] > $num_pages) $p = $num_pages;
else $p = $_GET['p'];
$start_from = $pun_user['disp_posts'] * ($p - 1);

// Generate paging links
$paging_links = $lang_common['Pages'].': '.paginate($num_pages, $p, 'viewtopic.php?id='.$id);


if ($pun_config['o_censoring'] == '1')
    $cur_topic['subject'] = censor_words($cur_topic['subject']);

$quickpost_buttons = false;
if ($pun_config['o_quickpost_buttons'] == '1')
    $quickpost_buttons = true;

$quickpost = false;
if ($pun_config['o_quickpost'] == '1' &&
    !$pun_user['is_guest'] &&
    ($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) &&
    ($cur_topic['closed'] == '0' || $is_admmod))
{
    $required_fields = array('req_message' => $lang_common['Message']);
    $quickpost = true;
}

if (!$pun_user['is_guest'] && $pun_config['o_subscriptions'] == '1')
{
    if ($cur_topic['is_subscribed'])
        // I apologize for the variable naming here. It's a mix of subscription and action I guess :-)
        $subscraction = '<p class="subscribelink clearb">'.$lang_topic['Is subscribed'].' - <a href="misc.php?unsubscribe='.$id.'">'.$lang_topic['Unsubscribe'].'</a></p>'."\n";
    else
        $subscraction = '<p class="subscribelink clearb"><a href="misc.php?subscribe='.$id.'">'.$lang_topic['Subscribe'].'</a></p>'."\n";
}
else
    $subscraction = '<div class="clearer"></div>'."\n";

if ($cur_topic['question'])
    $cur_topic_question = $cur_topic['question'].' - ';
else
    $cur_topic_question = '';

$page_title = pun_htmlspecialchars($pun_config['o_board_title'].' / '.$cur_topic_question . $cur_topic['subject']);
define('PUN_ALLOW_INDEX', 1);
require PUN_ROOT.'header.php';

?>
<div class="linkst">
    <div class="inbox">
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <p class="postlink conr"><?php echo $post_link ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <div class="clearer"></div>
    </div>
</div>

<?php


require PUN_ROOT.'include/parser.php';

// Mod poll begin
if ($cur_topic['question'])
{
    require PUN_ROOT . 'lang/' . $pun_user['language'] . '/polls.php'; 
    // get the poll data
    $result = $db->query('SELECT ptype,options,voters,votes FROM ' . $db->prefix . 'polls WHERE pollid=' . $id . '') or error('Unable to fetch poll info', __FILE__, __LINE__, $db->error());

    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    $cur_poll = $db->fetch_assoc($result);

    $options = unserialize($cur_poll['options']);
    if (!empty($cur_poll['voters']))
        $voters = unserialize($cur_poll['voters']);
    else
        $voters = array();

    $ptype = $cur_poll['ptype']; 
    // yay memory!
    // $cur_poll = null;
    $firstcheck = false;
    ?>
<div class="blockform">
    <h2><span><?php echo $lang_polls['Poll'] ?></span></h2>
    <div class="box">
        <?php
    if ((!$pun_user['is_guest']) && (!in_array($pun_user['id'], $voters)) && ($cur_topic['closed'] == '0') && (($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) || $is_admmod)) 
    {
        $showsubmit = true;
        ?>
        <form id="post" method="post" action="vote.php">
            <div class="inform">
                <div class="rbox">
                <fieldset>
                    <legend><?php echo pun_htmlspecialchars($cur_topic['question']) ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="poll_id" value="<?php echo $id; ?>" />
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
    
                        <?php
                        if ($ptype == 1) 
                        {
                            while (list($key, $value) = each($options)) 
                            {
                            ?>
                                <label><input name="vote" <?php if (!$firstcheck) { echo 'checked="checked"'; $firstcheck = true; }; ?> type="radio" value="<?php echo $key ?>" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 2) 
                        {
                            while (list($key, $value) = each($options)) 
                            {         
                            ?>
                                <label><input name="options[<?php echo $key ?>]" type="checkbox" value="1" /> <span><?php echo pun_htmlspecialchars($value); ?></span></label>
                            <?php
                            } 
                        } 
                        elseif ($ptype == 3) 
                        {
                            
                            while (list($key, $value) = each($options)) 
                            {
                                echo pun_htmlspecialchars($value); ?>
                                <label><input name="options[<?php echo $key ?>]" checked="checked" type="radio" value="yes" /> <?php echo $cur_topic['yes']; ?></label>
                                <label><input name="options[<?php echo $key ?>]" type="radio" value="no" /> <?php echo $cur_topic['no']; ?></label>
                                <br />
                            <?php
                            } 
                        } 
                        else
                        {
                            message($lang_common['Bad request']);
                        }
            ?></div></fieldset><?php
    } 
    else 
    {
        $showsubmit = false;
        ?>
        <div class="inform">
        <div class="rbox">
            
            <p class="poll_info"><strong><?php echo pun_htmlspecialchars($cur_topic['question']) ?></strong></p>            
            <?php
            if (!empty($cur_poll['votes']))
                    $votes = unserialize($cur_poll['votes']);
            else
                  $votes = array();
        
            if ($ptype == 1 || $ptype == 2) 
            {
                $total = 0;
                $percent = 0;
                $percent_int = 0;
                while (list($key, $val) = each($options)) 
                {
                    if (isset($votes[$key]))
                        $total += $votes[$key];
                }
                reset($options);
            }
            
              while (list($key, $value) = each($options)) {    

                if ($ptype == 1 || $ptype == 2)
                { 
                    if (isset($votes[$key]))
                    {
                        $percent =  $votes[$key] * 100 / $total;
                        $percent_int = floor($percent);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        <div class="poll_result">
                            <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key])) echo $percent_int/2; else echo '0'; ?>%;" alt="" />
                            <span><?php if (isset($votes[$key])) echo $percent_int . '% - ' . $votes[$key]; else echo '0% - 0'; ?></span>
                        </div>
                <?php
                }
                else if ($ptype == 3) 
                { 
                    $total = 0;
                    $yes_percent = 0;
                    $no_percent = 0;
                    $vote_yes = 0;
                    $vote_no = 0;
                    if (isset($votes[$key]['yes']))
                    {
                        $vote_yes = $votes[$key]['yes'];
                    }

                    if (isset($votes[$key]['no'])) {
                        $vote_no += $votes[$key]['no'];
                    }

                    $total = $vote_yes + $vote_no;
                    if (isset($votes[$key]))
                    {
                        $yes_percent =   floor($vote_yes * 100 / $total);
                        $no_percent = floor($vote_no * 100 / $total);
                    }
                    ?>
                        <div class="poll_question"><?php echo pun_htmlspecialchars($value); ?></div>
                        
                        <div class="poll_result_yesno">
                            <strong><?php echo $cur_topic['yes']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['yes'])) { echo $yes_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['yes'])) { echo $yes_percent . "% - " . $votes[$key]['yes']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                        <div class="poll_result_yesno">                        
                            <strong><?php echo $cur_topic['no']; ?></strong>
                                <img src="img/transparent.gif" class="poll_bar" style="width:<?php if (isset($votes[$key]['no'])) { echo $no_percent/2; } else { echo '0';  } ?>%;" alt="" />
                                <span><?php if (isset($votes[$key]['no'])) { echo $no_percent . "% - " . $votes[$key]['no']; } else { echo "0% - " . 0; } ?></span>
                        </div>
                    <?php 
                }
                else
                message($lang_common['Bad request']);
            }     
            ?>
                <p class="poll_info">Total : <?php echo $total; ?></p>
            <?php
        } 
        ?>
            </div>
                
            </div>

            <?php if ($showsubmit == true) 
            { 
                echo '<p><input type="submit" name="submit" tabindex="2" value="' . $lang_common['Submit'] . '" accesskey="s" /> <input type="submit" name="null" tabindex="2" value="' . $lang_polls['Null vote']. '" accesskey="n" /></p>
                </form>';
            } 
            ?>
    </div>
</div>
<?php
}
// Mod poll end

$bg_switch = true;    // Used for switching background color in posts
$post_count = 0;    // Keep track of post numbers

// Retrieve the posts (and their respective poster/online status)
//$result = $db->query('SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.idle=0) WHERE p.topic_id='.$id.' ORDER BY p.id LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error()); //Attachment Mod, changed the true to false...
// ---------- TB ----------
// $result = $db->query('
// SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
//  FROM '.$db->prefix.'posts AS p
//  INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
//  INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
//  LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
//  WHERE p.topic_id='.$id.'
//  ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'
//  LIMIT '.$start_from.','.$pun_user['disp_posts'], false)
//     or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
// ---------- TB ----------

// Start: Mod by Smartys
$p_array = array();
$result = $db->query('SELECT p.id FROM '.$db->prefix.'posts AS p WHERE p.topic_id='.$id.' ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post IDs', __FILE__, __LINE__, $db->error());
while (list($p_id) = $db->fetch_row($result))
{
    $p_array[] = $p_id;
}
$post_ids = implode(",", $p_array); 

$result = $db->query('
SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
FROM '.$db->prefix.'posts AS p
INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
WHERE p.id IN ('.$post_ids.')
ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' '), false)
    or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());

// End: Mod by Smartys

$att_res = $db->query('select af.* from '.$db->prefix.'attach_2_files as af left join '.$db->prefix.'posts as p on af.post_id=p.id where p.topic_id='.$id);
$att_arr = array();
$attach_allow_download = false;

while ($att_arr[] = $db->fetch_assoc($att_res)) {}
if($pun_user['g_id']==PUN_ADMIN)
    $attach_allow_download = true;
else
{         //fetch the rules of the forum, and check so that the user is allowed to download.
    $result_attach_two = $db->query('SELECT ar.rules FROM '.$db->prefix.'attach_2_rules AS ar WHERE ar.group_id=\''.$pun_user['group_id'].'\' AND ar.forum_id='.$cur_topic['forum_id'].' LIMIT 1')or error('Unable to fetch rules for the attachments', __FILE__, __LINE__, $db->error());
    if($db->num_rows($result_attach_two)==1)
    {
        list($attach_rules)=$db->fetch_row($result_attach_two);
        $attach_allow_download = attach_rules($attach_rules,ATTACH_DOWNLOAD);
    }
}

while ($cur_post = $db->fetch_assoc($result))
{
    $post_count++;
    $user_avatar = '';
    $user_info = array();
    $user_contacts = array();
    $post_actions = array();
    $is_online = '';
    $signature = '';
    $user_image_award = '';

    // If the poster is a registered user.
    if ($cur_post['poster_id'] > 1)
    {
        // ---------- TB ----------
//        require_once '../tracker/include/bittorrent.php';
        //---- Torrent Stuff
        $uploaded = $cur_post["bt_uploaded"];
        $downloaded = $cur_post["bt_downloaded"];
        
         //----Ratio
        if ($downloaded > 0)
        {
            $ratio = $uploaded / $downloaded;
//            $color = get_ratio_color($ratio);
            $ratio = number_format($ratio, 3);
            if ($color)
              $ratio = "<font style='color:$color;'>$ratio</font>";
        }
        else
            if ($cur_post["uploaded"] > 0)
                 $ratio = "Inf.";
            else
                $ratio = "---";
        // ---------- TB ----------

        // Image Award Mod Block Start
        if(strlen($cur_post['imgaward']) > 0){    // if we have something there, figure out what to output...
            //figure out the size of the award (Name of award should be in the form:  Test_Award_100x20.png ... where png is format, 100x20 is dimensions and Test_Award is name of award (seen in admin interface)
            $awardmod_filename=$cur_post['imgaward'];
            $awardmod_temp=substr($awardmod_filename,strrpos($awardmod_filename,'_')+1); //we still have the file extentsion
            $awardmod_temp=substr($awardmod_temp,0,strpos($awardmod_temp,'.'));
            $awardmod_dimensions = explode('x',$awardmod_temp);    // there ... now the array will hold 100 and 20 in [0] and [1] respecively ... :)
            $awardmod_name=str_replace('_',' ',substr($awardmod_filename,0,strrpos($awardmod_filename,'_')));
            if($pun_config['o_avatars'] == '1' && $pun_user['show_avatars'] != '0')
                $user_image_award = "\t\t\t\t\t".'<dd><img src="img/awards/'.$awardmod_filename.'" width="'.$awardmod_dimensions[0].'" height="'.$awardmod_dimensions[1].'" alt="Award: '.$awardmod_name.'" /></dd>';
            else
                $user_image_award = "\t\t\t\t\t".'<dd>Award: "'.$awardmod_name.'"</dd>';
        }
        // Image Award Mod Block End

        $username = '<a href="profile.php?id='.$cur_post['poster_id'].'">'.pun_htmlspecialchars($cur_post['username']).'</a>';
        $user_title = get_title($cur_post);

        if ($pun_config['o_censoring'] == '1')
            $user_title = censor_words($user_title);

        // Format the online indicator
        $is_online = ($cur_post['is_online'] == $cur_post['poster_id']) ? '<strong>'.$lang_topic['Online'].'</strong>' : $lang_topic['Offline'];

/*        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png" '.$img_size[3].' alt="" />';
        }
        else
            $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/default.gif" alt="" />';
*/

        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0' && $cur_post['g_use_avatar'] == '1')
        {
            $user_avatar = pun_htmlspecialchars($cur_post['avatar']);
            if(!stristr($user_avatar,"http://"))
                $user_avatar = '<img src="'.$pun_config['o_base_url'].'/'.$user_avatar.'" class="pavatar" alt="'.pun_htmlspecialchars($cur_post['username']).'" />';
            else
                $user_avatar = '<img src="'.$user_avatar.'" alt="" />';
        }
        else
            $user_avatar = '';

        // We only show sex, location, register date, post count and the contact links if "Show user info" is enabled
        if ($pun_config['o_show_user_info'] == '1')
        {
            if ($cur_post['sex'] != '')
                $user_info[] = '<dd>'.$lang_common['Sex'].': '.($cur_post['sex'] == 'male' ? $lang_common['Male'] : $lang_common['Female']);

            if ($cur_post['location'] != '')
            {
                if ($pun_config['o_censoring'] == '1')
                    $cur_post['location'] = censor_words($cur_post['location']);

                $user_info[] = '<dd>'.$lang_topic['From'].': '.pun_htmlspecialchars($cur_post['location']);
            }

            $user_info[] = '<dd>'.$lang_common['Registered'].': '.date($pun_config['o_date_format'], $cur_post['registered']);

            if ($pun_config['o_show_post_count'] == '1' || $pun_user['g_id'] < PUN_GUEST)
                $user_info[] = '<dd>'.$lang_common['Posts'].': '.$cur_post['num_posts'];

            // Now let's deal with the contact links (E-mail and URL)
            if (($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) || $pun_user['g_id'] < PUN_GUEST)
                $user_contacts[] = '<a href="mailto:'.$cur_post['email'].'">'.$lang_common['E-mail'].'</a>';
            else if ($cur_post['email_setting'] == '1' && !$pun_user['is_guest'])
                $user_contacts[] = '<a href="misc.php?email='.$cur_post['poster_id'].'">'.$lang_common['E-mail'].'</a>';

            require(PUN_ROOT.'include/pms/viewtopic_PM-link.php');

            if ($cur_post['url'] != '')
                $user_contacts[] = '<a href="'.pun_htmlspecialchars($cur_post['url']).'">'.$lang_topic['Website'].'</a>';
        }

        if ($pun_user['g_id'] < PUN_GUEST)
        {
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

            if ($cur_post['admin_note'] != '')
                $user_info[] = '<dd>'.$lang_topic['Note'].': <strong>'.pun_htmlspecialchars($cur_post['admin_note']).'</strong>';
        }
    }
    // If the poster is a guest (or a user that has been deleted)
    else
    {
        $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/guest.gif" alt="" />';
        $username = pun_htmlspecialchars($cur_post['username']);
        $user_title = get_title($cur_post);

        if ($pun_user['g_id'] < PUN_GUEST)
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

        if ($pun_config['o_show_user_info'] == '1' && $cur_post['poster_email'] != '' && !$pun_user['is_guest'])
            $user_contacts[] = '<a href="mailto:'.$cur_post['poster_email'].'">'.$lang_common['E-mail'].'</a>';
    }

    // Generation post action array (quote, edit, delete etc.)
    if (!$is_admmod)
    {
        if (!$pun_user['is_guest'])
            $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>';

        if ($cur_topic['closed'] == '0')
        {
            if ($cur_post['poster_id'] == $pun_user['id'])
            {
                if ((($start_from + $post_count) == 1 && $pun_user['g_delete_topics'] == '1') || (($start_from + $post_count) > 1 && $pun_user['g_delete_posts'] == '1'))
                    $post_actions[] = '<li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>';
                if ($pun_user['g_edit_posts'] == '1')
                    $post_actions[] = '<li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>';
            }

            if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1')
                $post_actions[] = '<li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';
        }
    }
    else
        $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>'.$lang_topic['Link separator'].'</li><li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>'.$lang_topic['Link separator'].'</li><li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>'.$lang_topic['Link separator'].'</li><li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';


    // Switch the background color for every message.
    $bg_switch = ($bg_switch) ? $bg_switch = false : $bg_switch = true;
    $vtbg = ($bg_switch) ? ' roweven' : ' rowodd';


    // Perform the main parsing of the message (BBCode, smilies, censor words etc)
    $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);

    // Do signature parsing/caching
    if ($cur_post['signature'] != '' && $pun_user['show_sig'] != '0')
    {
        if (isset($signature_cache[$cur_post['poster_id']]))
            $signature = $signature_cache[$cur_post['poster_id']];
        else
        {
            $signature = parse_signature($cur_post['signature']);
            $signature_cache[$cur_post['poster_id']] = $signature;
        }
    }

    // Attachment Mod Block Start
    $attach_output = '';
    $attach_num = 0;

    // Check if this post has any attachments
for ($i=0; $i < sizeof($att_arr)-1;$i++)
{
    if($att_arr[$i]['post_id'] == $cur_post['id']){
        $attach_num++;
        if($attach_allow_download){//check if the user is allowed to download it.
            $attach_output = $lang_attach['Attachments:'].' ';
            $attachment_extension .= attach_get_extension($att_arr[$i]['filename']);
            $attach_output .= '<br />'."\n\t\t\t\t\t\t".attach_icon($att_arr[$i]['extension']).' <a href="./attachment.php?item='.$att_arr[$i]['id'].'">'.$att_arr[$i]['filename'].'</a>, '.$lang_attach['Size:'].' '.number_format($att_arr[$i]['size']).' '.$lang_attach['bytes'].', '.$lang_attach['Downloads:'].' '.number_format($att_arr[$i]['downloads']);
        }
    }
}    // Attachment Mod Block End

?>
<div id="p<?php echo $cur_post['id'] ?>" class="blockpost<?php echo $vtbg ?><?php if (($post_count + $start_from) == 1) echo ' firstpost'; ?>">
    <h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?> </span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>
    <div class="box">
        <div class="inbox">
            <div class="postleft">
                <dl>
                    <dt><strong><?php echo $username ?></strong></dt>
                    <dd class="usertitle"><strong><?php echo $user_title ?></strong></dd>
                    <?php if (!empty($user_avatar)) echo '<dd class="postavatar">'.$user_avatar.'</dd>'; ?>
                    <?php if (!empty($ratio)) echo '<dd class="ratio">'.$lang_common['Ratio'].': '.$ratio.'</dd>'; ?>
<?php if (strlen($user_image_award)>0) echo $user_image_award; ?>
<?php if (count($user_info)) echo "\t\t\t\t\t".implode('</dd>'."\n\t\t\t\t\t", $user_info).'</dd>'."\n"; ?>
<?php if (count($user_contacts)) echo "\t\t\t\t\t".'<dd class="usercontacts">'.implode('  ', $user_contacts).'</dd>'."\n"; ?>
            <div class="postfootleft"><?php if ($cur_post['poster_id'] > 1) echo '<p>'.$is_online.'</p>'; ?></div>
                </dl>
            </div>
            <div class="postright">
                <h3><?php if (($post_count + $start_from) > 1) echo ' Re: '; ?><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></h3>
                <div class="postmsg">
                    <?php echo $cur_post['message']."\n" ?>
<?php if ($cur_post['edited'] != '') echo "\t\t\t\t\t".'<p class="postedit"><em>'.$lang_topic['Last edit'].' '.pun_htmlspecialchars($cur_post['edited_by']).' ('.format_time($cur_post['edited']).')</em></p>'."\n"; ?>
<?php if ($attach_allow_download && $attach_output != '') echo "\t\t\t\t\t".'<div class="postsignature"><hr />'.$attach_output.'</div>'."\n"; ## Attachment Mod row ?>
<?php if ($signature != '') echo "\t\t\t\t".'<div class="postsignature"><hr />'.$signature.'</div>'."\n"; ?>
                </div>
            </div>
            <div class="clearer"></div>
            <div class="postfootright"><?php echo (count($post_actions)) ? '<ul>'.implode($lang_topic['Link separator'].'</li>', $post_actions).'</li></ul></div>'."\n" : '<div> </div></div>'."\n" ?>
        </div>
    </div>
</div>

<?php

}

?>
<div class="postlinksb">
    <div class="inbox">
        <p class="postlink conr"><?php echo $post_link ?></p>
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <ul><li><a href="forum.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <?php echo $subscraction ?>
    </div>
</div>

<?php

// Display quick post if enabled
if ($quickpost)
{

?>
<div class="blockform">
    <h2><span><?php echo $lang_topic['Quick post'] ?></span></h2>
    <div class="box">
            <form id="post" method="post" name="qpost" action="post.php?tid=<?php echo $id ?>" onsubmit="this.submit.disabled=true;if(process_form(this)){return true;}else{this.submit.disabled=false;return false;}">
            <div class="inform">
                <fieldset>
                    <legend><?php echo $lang_common['Write message legend'] ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
                        <?php if ($quickpost_buttons) require PUN_ROOT.'mod_easy_bbcode.php'; ?>
                        <?php require PUN_ROOT.'mod_modern_bbcode.php'; ?>
                        <label><textarea name="req_message" rows="7" cols="75" tabindex="1"></textarea></label>
                        <ul class="bblinks">
                            <li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#smilies" onclick="window.open(this.href); return false;"><?php echo $lang_common['Smilies'] ?></a>: <?php echo ($pun_config['o_smilies'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                        </ul>
                    </div>
                </fieldset>
            </div>
            <p><input type="submit" name="submit" tabindex="2" value="<?php echo $lang_common['Submit'] ?>" accesskey="s" /></p>
        </form>
    </div>
</div>
<?php

}

// Increment "num_views" for topic
$low_prio = ($db_type == 'mysql') ? 'LOW_PRIORITY ' : '';
$db->query('UPDATE '.$low_prio.$db->prefix.'topics SET num_views=num_views+1 WHERE id='.$id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());

$forum_id = $cur_topic['forum_id'];
$footer_style = 'viewtopic';
require PUN_ROOT.'footer.php'

Re: Help with slow query

Nope. Same thing. No errors but the debug info shows that it still takes over 2.7s to generate the page.
I'm surprised that the largest punBB forums haven't stumbled onto this same issue as well.
True, it only starts to be noticeable after a few thousand posts but still....

Oh well, what matters is that punBB has much nicer people behind it and backing it up than any other BB wink

Re: Help with slow query

Oh, my change was supposed to be a fix for the pid= problem (the page taking 12 secs to load) smile

Could I supply you with a relatively unmodified version of viewtopic.php to try (name it viewtopic_test.php or something like that and upload it) to see if the issue is modifications?

Re: Help with slow query

Sure, I'm willing to do anything to squezee a bit more performance out of it smile

Re: Help with slow query

Cool, here it is smile

<?php
/***********************************************************************

  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)

  This file is part of PunBB.

  PunBB 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.

  PunBB is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  MA  02111-1307  USA

************************************************************************/


define('PUN_ROOT', './');
require PUN_ROOT.'include/common.php';


if ($pun_user['g_read_board'] == '0')
    message($lang_common['No view']);


$action = isset($_GET['action']) ? $_GET['action'] : null;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;
if ($id < 1 && $pid < 1)
    message($lang_common['Bad request']);

// Load the viewtopic.php language file
require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';


// If a post ID is specified we determine topic ID and page number so we can redirect to the correct message
if ($pid)
{
    $result = $db->query('SELECT topic_id, posted FROM '.$db->prefix.'posts WHERE id='.$pid) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    if (!$db->num_rows($result))
        message($lang_common['Bad request']);

    list($id, $posted) = $db->fetch_row($result);

    // Determine on what page the post is located (depending on $pun_user['disp_posts'])
    $result = $db->query('SELECT count(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' and posted <= '.$posted) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $post_number = $db->result($result);

    $_GET['p'] = ceil($post_number / $pun_user['disp_posts']);
}

// If action=new, we redirect to the first new post (if any)
else if ($action == 'new' && !$pun_user['is_guest'])
{
    $result = $db->query('SELECT MIN(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id.' AND posted>'.$pun_user['last_visit']) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $first_new_post_id = $db->result($result);

    if ($first_new_post_id)
        header('Location: viewtopic.php?pid='.$first_new_post_id.'#p'.$first_new_post_id);
    else    // If there is no new post, we go to the last post
        header('Location: viewtopic.php?id='.$id.'&action=last');

    exit;
}

// If action=last, we redirect to the last post
else if ($action == 'last')
{
    $result = $db->query('SELECT MAX(id) FROM '.$db->prefix.'posts WHERE topic_id='.$id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
    $last_post_id = $db->result($result);

    if ($last_post_id)
    {
        header('Location: viewtopic.php?pid='.$last_post_id.'#p'.$last_post_id);
        exit;
    }
}


// Fetch some info about the topic
if (!$pun_user['is_guest'])
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, s.user_id AS is_subscribed FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
else
    $result = $db->query('SELECT t.subject, t.closed, t.num_replies, t.sticky, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, 0 FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

if (!$db->num_rows($result))
    message($lang_common['Bad request']);

$cur_topic = $db->fetch_assoc($result);

// Sort out who the moderators are and if we are currently a moderator (or an admin)
$mods_array = ($cur_topic['moderators'] != '') ? unserialize($cur_topic['moderators']) : array();
$is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_id'] == PUN_MOD && array_key_exists($pun_user['username'], $mods_array))) ? true : false;

// Can we or can we not post replies?
if ($cur_topic['closed'] == '0')
{
    if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1' || $is_admmod)
        $post_link = '<a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
    else
        $post_link = ' ';
}
else
{
    $post_link = $lang_topic['Topic closed'];

    if ($is_admmod)
        $post_link .= ' / <a href="post.php?tid='.$id.'">'.$lang_topic['Post reply'].'</a>';
}


// Determine the post offset (based on $_GET['p'])
$num_pages = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);

$p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : $_GET['p'];
$start_from = $pun_user['disp_posts'] * ($p - 1);

// Generate paging links
$paging_links = $lang_common['Pages'].': '.paginate($num_pages, $p, 'viewtopic.php?id='.$id);


if ($pun_config['o_censoring'] == '1')
    $cur_topic['subject'] = censor_words($cur_topic['subject']);


$quickpost = false;
if ($pun_config['o_quickpost'] == '1' &&
    !$pun_user['is_guest'] &&
    ($cur_topic['post_replies'] == '1' || ($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1')) &&
    ($cur_topic['closed'] == '0' || $is_admmod))
{
    $required_fields = array('req_message' => $lang_common['Message']);
    $quickpost = true;
}

if (!$pun_user['is_guest'] && $pun_config['o_subscriptions'] == '1')
{
    if ($cur_topic['is_subscribed'])
        // I apologize for the variable naming here. It's a mix of subscription and action I guess :-)
        $subscraction = '<p class="subscribelink clearb">'.$lang_topic['Is subscribed'].' - <a href="misc.php?unsubscribe='.$id.'">'.$lang_topic['Unsubscribe'].'</a></p>'."\n";
    else
        $subscraction = '<p class="subscribelink clearb"><a href="misc.php?subscribe='.$id.'">'.$lang_topic['Subscribe'].'</a></p>'."\n";
}
else
    $subscraction = '<div class="clearer"></div>'."\n";

$page_title = pun_htmlspecialchars($pun_config['o_board_title'].' / '.$cur_topic['subject']);
define('PUN_ALLOW_INDEX', 1);
require PUN_ROOT.'header.php';

?>
<div class="linkst">
    <div class="inbox">
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <p class="postlink conr"><?php echo $post_link ?></p>
        <ul><li><a href="index.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <div class="clearer"></div>
    </div>
</div>

<?php


require PUN_ROOT.'include/parser.php';

$bg_switch = true;    // Used for switching background color in posts
$post_count = 0;    // Keep track of post numbers

// Start: Mod by Smartys
$p_array = array();
$result = $db->query('SELECT p.id FROM '.$db->prefix.'posts AS p WHERE p.topic_id='.$id.' ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' ').'LIMIT '.$start_from.','.$pun_user['disp_posts'], false) or error('Unable to fetch post IDs', __FILE__, __LINE__, $db->error());
while (list($p_id) = $db->fetch_row($result))
{
    $p_array[] = $p_id;
}
$post_ids = implode(",", $p_array); 

$result = $db->query('
SELECT u.email, u.group_id AS gro, u.title, u.url, u.sex, u.location, u.use_avatar, u.avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, u.bt_uploaded, u.bt_downloaded, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, g_use_avatar, o.user_id AS is_online
FROM '.$db->prefix.'posts AS p
INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id
INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0)
WHERE p.id IN ('.$post_ids.')
ORDER BY p.id'.($pun_user['show_posts_desc'] == '1' ? ' DESC ' : ' '), false)
    or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());

// End: Mod by Smartys
while ($cur_post = $db->fetch_assoc($result))
{
    $post_count++;
    $user_avatar = '';
    $user_info = array();
    $user_contacts = array();
    $post_actions = array();
    $is_online = '';
    $signature = '';

    // If the poster is a registered user.
    if ($cur_post['poster_id'] > 1)
    {
        $username = '<a href="profile.php?id='.$cur_post['poster_id'].'">'.pun_htmlspecialchars($cur_post['username']).'</a>';
        $user_title = get_title($cur_post);

        if ($pun_config['o_censoring'] == '1')
            $user_title = censor_words($user_title);

        // Format the online indicator
        $is_online = ($cur_post['is_online'] == $cur_post['poster_id']) ? '<strong>'.$lang_topic['Online'].'</strong>' : $lang_topic['Offline'];

        if ($pun_config['o_avatars'] == '1' && $cur_post['use_avatar'] == '1' && $pun_user['show_avatars'] != '0')
        {
            if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.gif" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.jpg" '.$img_size[3].' alt="" />';
            else if ($img_size = @getimagesize($pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png'))
                $user_avatar = '<img src="'.$pun_config['o_avatars_dir'].'/'.$cur_post['poster_id'].'.png" '.$img_size[3].' alt="" />';
        }
        else
            $user_avatar = '';

        // We only show location, register date, post count and the contact links if "Show user info" is enabled
        if ($pun_config['o_show_user_info'] == '1')
        {
            if ($cur_post['location'] != '')
            {
                if ($pun_config['o_censoring'] == '1')
                    $cur_post['location'] = censor_words($cur_post['location']);

                $user_info[] = '<dd>'.$lang_topic['From'].': '.pun_htmlspecialchars($cur_post['location']);
            }

            $user_info[] = '<dd>'.$lang_common['Registered'].': '.date($pun_config['o_date_format'], $cur_post['registered']);

            if ($pun_config['o_show_post_count'] == '1' || $pun_user['g_id'] < PUN_GUEST)
                $user_info[] = '<dd>'.$lang_common['Posts'].': '.$cur_post['num_posts'];

            // Now let's deal with the contact links (E-mail and URL)
            if (($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) || $pun_user['g_id'] < PUN_GUEST)
                $user_contacts[] = '<a href="mailto:'.$cur_post['email'].'">'.$lang_common['E-mail'].'</a>';
            else if ($cur_post['email_setting'] == '1' && !$pun_user['is_guest'])
                $user_contacts[] = '<a href="misc.php?email='.$cur_post['poster_id'].'">'.$lang_common['E-mail'].'</a>';

            if ($cur_post['url'] != '')
                $user_contacts[] = '<a href="'.pun_htmlspecialchars($cur_post['url']).'">'.$lang_topic['Website'].'</a>';
        }

        if ($pun_user['g_id'] < PUN_GUEST)
        {
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

            if ($cur_post['admin_note'] != '')
                $user_info[] = '<dd>'.$lang_topic['Note'].': <strong>'.pun_htmlspecialchars($cur_post['admin_note']).'</strong>';
        }
    }
    // If the poster is a guest (or a user that has been deleted)
    else
    {
        $username = pun_htmlspecialchars($cur_post['username']);
        $user_title = get_title($cur_post);

        if ($pun_user['g_id'] < PUN_GUEST)
            $user_info[] = '<dd>IP: <a href="moderate.php?get_host='.$cur_post['id'].'">'.$cur_post['poster_ip'].'</a>';

        if ($pun_config['o_show_user_info'] == '1' && $cur_post['poster_email'] != '' && !$pun_user['is_guest'])
            $user_contacts[] = '<a href="mailto:'.$cur_post['poster_email'].'">'.$lang_common['E-mail'].'</a>';
    }

    // Generation post action array (quote, edit, delete etc.)
    if (!$is_admmod)
    {
        if (!$pun_user['is_guest'])
            $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>';

        if ($cur_topic['closed'] == '0')
        {
            if ($cur_post['poster_id'] == $pun_user['id'])
            {
                if ((($start_from + $post_count) == 1 && $pun_user['g_delete_topics'] == '1') || (($start_from + $post_count) > 1 && $pun_user['g_delete_posts'] == '1'))
                    $post_actions[] = '<li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>';
                if ($pun_user['g_edit_posts'] == '1')
                    $post_actions[] = '<li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>';
            }

            if (($cur_topic['post_replies'] == '' && $pun_user['g_post_replies'] == '1') || $cur_topic['post_replies'] == '1')
                $post_actions[] = '<li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';
        }
    }
    else
        $post_actions[] = '<li class="postreport"><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a>'.$lang_topic['Link separator'].'</li><li class="postdelete"><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a>'.$lang_topic['Link separator'].'</li><li class="postedit"><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a>'.$lang_topic['Link separator'].'</li><li class="postquote"><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a>';


    // Switch the background color for every message.
    $bg_switch = ($bg_switch) ? $bg_switch = false : $bg_switch = true;
    $vtbg = ($bg_switch) ? ' roweven' : ' rowodd';


    // Perform the main parsing of the message (BBCode, smilies, censor words etc)
    $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);

    // Do signature parsing/caching
    if ($cur_post['signature'] != '' && $pun_user['show_sig'] != '0')
    {
        if (isset($signature_cache[$cur_post['poster_id']]))
            $signature = $signature_cache[$cur_post['poster_id']];
        else
        {
            $signature = parse_signature($cur_post['signature']);
            $signature_cache[$cur_post['poster_id']] = $signature;
        }
    }

?>
<div id="p<?php echo $cur_post['id'] ?>" class="blockpost<?php echo $vtbg ?><?php if (($post_count + $start_from) == 1) echo ' firstpost'; ?>">
    <h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?> </span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>
    <div class="box">
        <div class="inbox">
            <div class="postleft">
                <dl>
                    <dt><strong><?php echo $username ?></strong></dt>
                    <dd class="usertitle"><strong><?php echo $user_title ?></strong></dd>
                    <dd class="postavatar"><?php echo $user_avatar ?></dd>
<?php if (count($user_info)) echo "\t\t\t\t\t".implode('</dd>'."\n\t\t\t\t\t", $user_info).'</dd>'."\n"; ?>
<?php if (count($user_contacts)) echo "\t\t\t\t\t".'<dd class="usercontacts">'.implode('  ', $user_contacts).'</dd>'."\n"; ?>
                </dl>
            </div>
            <div class="postright">
                <h3><?php if (($post_count + $start_from) > 1) echo ' Re: '; ?><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></h3>
                <div class="postmsg">
                    <?php echo $cur_post['message']."\n" ?>
<?php if ($cur_post['edited'] != '') echo "\t\t\t\t\t".'<p class="postedit"><em>'.$lang_topic['Last edit'].' '.pun_htmlspecialchars($cur_post['edited_by']).' ('.format_time($cur_post['edited']).')</em></p>'."\n"; ?>
                </div>
<?php if ($signature != '') echo "\t\t\t\t".'<div class="postsignature"><hr />'.$signature.'</div>'."\n"; ?>
            </div>
            <div class="clearer"></div>
            <div class="postfootleft"><?php if ($cur_post['poster_id'] > 1) echo '<p>'.$is_online.'</p>'; ?></div>
            <div class="postfootright"><?php echo (count($post_actions)) ? '<ul>'.implode($lang_topic['Link separator'].'</li>', $post_actions).'</li></ul></div>'."\n" : '<div> </div></div>'."\n" ?>
        </div>
    </div>
</div>

<?php

}

?>
<div class="postlinksb">
    <div class="inbox">
        <p class="postlink conr"><?php echo $post_link ?></p>
        <p class="pagelink conl"><?php echo $paging_links ?></p>
        <ul><li><a href="index.php"><?php echo $lang_common['Index'] ?></a></li><li> » <a href="viewforum.php?id=<?php echo $cur_topic['forum_id'] ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li><li> » <?php echo pun_htmlspecialchars($cur_topic['subject']) ?></li></ul>
        <?php echo $subscraction ?>
    </div>
</div>

<?php

// Display quick post if enabled
if ($quickpost)
{

?>
<div class="blockform">
    <h2><span><?php echo $lang_topic['Quick post'] ?></span></h2>
    <div class="box">
        <form method="post" action="post.php?tid=<?php echo $id ?>" onsubmit="this.submit.disabled=true;if(process_form(this)){return true;}else{this.submit.disabled=false;return false;}">
            <div class="inform">
                <fieldset>
                    <legend><?php echo $lang_common['Write message legend'] ?></legend>
                    <div class="infldset txtarea">
                        <input type="hidden" name="form_sent" value="1" />
                        <input type="hidden" name="form_user" value="<?php echo (!$pun_user['is_guest']) ? pun_htmlspecialchars($pun_user['username']) : 'Guest'; ?>" />
                        <label><textarea name="req_message" rows="7" cols="75" tabindex="1"></textarea></label>
                        <ul class="bblinks">
                            <li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                            <li><a href="help.php#smilies" onclick="window.open(this.href); return false;"><?php echo $lang_common['Smilies'] ?></a>: <?php echo ($pun_config['o_smilies'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
                        </ul>
                    </div>
                </fieldset>
            </div>
            <p><input type="submit" name="submit" tabindex="2" value="<?php echo $lang_common['Submit'] ?>" accesskey="s" /></p>
        </form>
    </div>
</div>
<?php

}

// Increment "num_views" for topic
$low_prio = ($db_type == 'mysql') ? 'LOW_PRIORITY ' : '';
$db->query('UPDATE '.$low_prio.$db->prefix.'topics SET num_views=num_views+1 WHERE id='.$id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());

$forum_id = $cur_topic['forum_id'];
$footer_style = 'viewtopic';
require PUN_ROOT.'footer.php';

17 (edited by MrMister 2007-01-03 02:12)

Re: Help with slow query

Same thing, only I just noticed:

viewtopic.php?id=691 - 2.7s
viewtopic.php?id=691&p=868 - 2.7s
viewtopic.php?id=691&p=869 (the last page) - 0.2s
viewtopic.php?pid=64395#p64395 (the last post on the +21k post's thread) - 0.2s
viewtopic.php?pid=8379#p8379 (the first post on the +21k post's thread) - 2.7s

I can export the thread's contents and give it to you or create a test account and give you the URL of the forum (it's a private forum so I don't like putting the link to it on a public forum smile) if you think it might be easier.

Re: Help with slow query

Mmm, an export would be nice: need my email?

Re: Help with slow query

I just did a export of forum, topics and posts, packed it with 7z and got a file with 4.3MB
Just let me know where to send it to.

Re: Help with slow query

My name (smartys) @punbb.org wink

Re: Help with slow query

I sent you the file. Let me know if there are any problems with it.

Re: Help with slow query

I sent you a reply wink