phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / viewtopic.php

History | View | Annotate | Download (67.3 kB)

1
<?php
2
/**
3
*
4
* @package phpBB3
5
* @version $Id: viewtopic.php 11682 2012-02-11 10:45:09Z git-gate $
6
* @copyright (c) 2005 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
*
9
*/
10
11
/**
12
* @ignore
13
*/
14
define('IN_PHPBB', true);
15
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
16
$phpEx = substr(strrchr(__FILE__, '.'), 1);
17
include($phpbb_root_path . 'common.' . $phpEx);
18
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
19
include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
20
21
// Start session management
22
$user->session_begin();
23
$auth->acl($user->data);
24
25
// Initial var setup
26
$forum_id        = request_var('f', 0);
27
$topic_id        = request_var('t', 0);
28
$post_id        = request_var('p', 0);
29
$voted_id        = request_var('vote_id', array('' => 0));
30
31
$voted_id = (sizeof($voted_id) > 1) ? array_unique($voted_id) : $voted_id;
32
33
34
$start                = request_var('start', 0);
35
$view                = request_var('view', '');
36
37
$default_sort_days        = (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0;
38
$default_sort_key        = (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't';
39
$default_sort_dir        = (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a';
40
41
$sort_days        = request_var('st', $default_sort_days);
42
$sort_key        = request_var('sk', $default_sort_key);
43
$sort_dir        = request_var('sd', $default_sort_dir);
44
45
$update                = request_var('update', false);
46
47
$s_can_vote = false;
48
/**
49
* @todo normalize?
50
*/
51
$hilit_words        = request_var('hilit', '', true);
52
53
// Do we have a topic or post id?
54
if (!$topic_id && !$post_id)
55
{
56
        trigger_error('NO_TOPIC');
57
}
58
59
// Find topic id if user requested a newer or older topic
60
if ($view && !$post_id)
61
{
62
        if (!$forum_id)
63
        {
64
                $sql = 'SELECT forum_id
65
                        FROM ' . TOPICS_TABLE . "
66
                        WHERE topic_id = $topic_id";
67
                $result = $db->sql_query($sql);
68
                $forum_id = (int) $db->sql_fetchfield('forum_id');
69
                $db->sql_freeresult($result);
70
71
                if (!$forum_id)
72
                {
73
                        trigger_error('NO_TOPIC');
74
                }
75
        }
76
77
        if ($view == 'unread')
78
        {
79
                // Get topic tracking info
80
                $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_id);
81
82
                $topic_last_read = (isset($topic_tracking_info[$topic_id])) ? $topic_tracking_info[$topic_id] : 0;
83
84
                $sql = 'SELECT post_id, topic_id, forum_id
85
                        FROM ' . POSTS_TABLE . "
86
                        WHERE topic_id = $topic_id
87
                                " . (($auth->acl_get('m_approve', $forum_id)) ? '' : 'AND post_approved = 1') . "
88
                                AND post_time > $topic_last_read
89
                                AND forum_id = $forum_id
90
                        ORDER BY post_time ASC";
91
                $result = $db->sql_query_limit($sql, 1);
92
                $row = $db->sql_fetchrow($result);
93
                $db->sql_freeresult($result);
94
95
                if (!$row)
96
                {
97
                        $sql = 'SELECT topic_last_post_id as post_id, topic_id, forum_id
98
                                FROM ' . TOPICS_TABLE . '
99
                                WHERE topic_id = ' . $topic_id;
100
                        $result = $db->sql_query($sql);
101
                        $row = $db->sql_fetchrow($result);
102
                        $db->sql_freeresult($result);
103
                }
104
105
                if (!$row)
106
                {
107
                        // Setup user environment so we can process lang string
108
                        $user->setup('viewtopic');
109
110
                        trigger_error('NO_TOPIC');
111
                }
112
113
                $post_id = $row['post_id'];
114
                $topic_id = $row['topic_id'];
115
        }
116
        else if ($view == 'next' || $view == 'previous')
117
        {
118
                $sql_condition = ($view == 'next') ? '>' : '<';
119
                $sql_ordering = ($view == 'next') ? 'ASC' : 'DESC';
120
121
                $sql = 'SELECT forum_id, topic_last_post_time
122
                        FROM ' . TOPICS_TABLE . '
123
                        WHERE topic_id = ' . $topic_id;
124
                $result = $db->sql_query($sql);
125
                $row = $db->sql_fetchrow($result);
126
                $db->sql_freeresult($result);
127
128
                if (!$row)
129
                {
130
                        $user->setup('viewtopic');
131
                        // OK, the topic doesn't exist. This error message is not helpful, but technically correct.
132
                        trigger_error(($view == 'next') ? 'NO_NEWER_TOPICS' : 'NO_OLDER_TOPICS');
133
                }
134
                else
135
                {
136
                        $sql = 'SELECT topic_id, forum_id
137
                                FROM ' . TOPICS_TABLE . '
138
                                WHERE forum_id = ' . $row['forum_id'] . "
139
                                        AND topic_moved_id = 0
140
                                        AND topic_last_post_time $sql_condition {$row['topic_last_post_time']}
141
                                        " . (($auth->acl_get('m_approve', $row['forum_id'])) ? '' : 'AND topic_approved = 1') . "
142
                                ORDER BY topic_last_post_time $sql_ordering";
143
                        $result = $db->sql_query_limit($sql, 1);
144
                        $row = $db->sql_fetchrow($result);
145
                        $db->sql_freeresult($result);
146
147
                        if (!$row)
148
                        {
149
                                $user->setup('viewtopic');
150
                                trigger_error(($view == 'next') ? 'NO_NEWER_TOPICS' : 'NO_OLDER_TOPICS');
151
                        }
152
                        else
153
                        {
154
                                $topic_id = $row['topic_id'];
155
156
                                // Check for global announcement correctness?
157
                                if (!$row['forum_id'] && !$forum_id)
158
                                {
159
                                        trigger_error('NO_TOPIC');
160
                                }
161
                                else if ($row['forum_id'])
162
                                {
163
                                        $forum_id = $row['forum_id'];
164
                                }
165
                        }
166
                }
167
        }
168
169
        // Check for global announcement correctness?
170
        if ((!isset($row) || !$row['forum_id']) && !$forum_id)
171
        {
172
                trigger_error('NO_TOPIC');
173
        }
174
        else if (isset($row) && $row['forum_id'])
175
        {
176
                $forum_id = $row['forum_id'];
177
        }
178
}
179
180
// This rather complex gaggle of code handles querying for topics but
181
// also allows for direct linking to a post (and the calculation of which
182
// page the post is on and the correct display of viewtopic)
183
$sql_array = array(
184
        'SELECT'        => 't.*, f.*',
185
186
        'FROM'                => array(FORUMS_TABLE => 'f'),
187
);
188
189
// Firebird handles two columns of the same name a little differently, this
190
// addresses that by forcing the forum_id to come from the forums table.
191
if ($db->sql_layer === 'firebird')
192
{
193
        $sql_array['SELECT'] = 'f.forum_id AS forum_id, ' . $sql_array['SELECT'];
194
}
195
196
// The FROM-Order is quite important here, else t.* columns can not be correctly bound.
197
if ($post_id)
198
{
199
        $sql_array['SELECT'] .= ', p.post_approved, p.post_time, p.post_id';
200
        $sql_array['FROM'][POSTS_TABLE] = 'p';
201
}
202
203
// Topics table need to be the last in the chain
204
$sql_array['FROM'][TOPICS_TABLE] = 't';
205
206
if ($user->data['is_registered'])
207
{
208
        $sql_array['SELECT'] .= ', tw.notify_status';
209
        $sql_array['LEFT_JOIN'] = array();
210
211
        $sql_array['LEFT_JOIN'][] = array(
212
                'FROM'        => array(TOPICS_WATCH_TABLE => 'tw'),
213
                'ON'        => 'tw.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tw.topic_id'
214
        );
215
216
        if ($config['allow_bookmarks'])
217
        {
218
                $sql_array['SELECT'] .= ', bm.topic_id as bookmarked';
219
                $sql_array['LEFT_JOIN'][] = array(
220
                        'FROM'        => array(BOOKMARKS_TABLE => 'bm'),
221
                        'ON'        => 'bm.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = bm.topic_id'
222
                );
223
        }
224
225
        if ($config['load_db_lastread'])
226
        {
227
                $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as forum_mark_time';
228
229
                $sql_array['LEFT_JOIN'][] = array(
230
                        'FROM'        => array(TOPICS_TRACK_TABLE => 'tt'),
231
                        'ON'        => 'tt.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tt.topic_id'
232
                );
233
234
                $sql_array['LEFT_JOIN'][] = array(
235
                        'FROM'        => array(FORUMS_TRACK_TABLE => 'ft'),
236
                        'ON'        => 'ft.user_id = ' . $user->data['user_id'] . ' AND t.forum_id = ft.forum_id'
237
                );
238
        }
239
}
240
241
if (!$post_id)
242
{
243
        $sql_array['WHERE'] = "t.topic_id = $topic_id";
244
}
245
else
246
{
247
        $sql_array['WHERE'] = "p.post_id = $post_id AND t.topic_id = p.topic_id";
248
}
249
250
$sql_array['WHERE'] .= ' AND (f.forum_id = t.forum_id';
251
252
if (!$forum_id)
253
{
254
        // If it is a global announcement make sure to set the forum id to a postable forum
255
        $sql_array['WHERE'] .= ' OR (t.topic_type = ' . POST_GLOBAL . '
256
                AND f.forum_type = ' . FORUM_POST . ')';
257
}
258
else
259
{
260
        $sql_array['WHERE'] .= ' OR (t.topic_type = ' . POST_GLOBAL . "
261
                AND f.forum_id = $forum_id)";
262
}
263
264
$sql_array['WHERE'] .= ')';
265
266
// Join to forum table on topic forum_id unless topic forum_id is zero
267
// whereupon we join on the forum_id passed as a parameter ... this
268
// is done so navigation, forum name, etc. remain consistent with where
269
// user clicked to view a global topic
270
$sql = $db->sql_build_query('SELECT', $sql_array);
271
$result = $db->sql_query($sql);
272
$topic_data = $db->sql_fetchrow($result);
273
$db->sql_freeresult($result);
274
275
// link to unapproved post or incorrect link
276
if (!$topic_data)
277
{
278
        // If post_id was submitted, we try at least to display the topic as a last resort...
279
        if ($post_id && $topic_id)
280
        {
281
                redirect(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id" . (($forum_id) ? "&amp;f=$forum_id" : '')));
282
        }
283
284
        trigger_error('NO_TOPIC');
285
}
286
287
$forum_id = (int) $topic_data['forum_id'];
288
// This is for determining where we are (page)
289
if ($post_id)
290
{
291
        // are we where we are supposed to be?
292
        if (!$topic_data['post_approved'] && !$auth->acl_get('m_approve', $topic_data['forum_id']))
293
        {
294
                // If post_id was submitted, we try at least to display the topic as a last resort...
295
                if ($topic_id)
296
                {
297
                        redirect(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id" . (($forum_id) ? "&amp;f=$forum_id" : '')));
298
                }
299
300
                trigger_error('NO_TOPIC');
301
        }
302
        if ($post_id == $topic_data['topic_first_post_id'] || $post_id == $topic_data['topic_last_post_id'])
303
        {
304
                $check_sort = ($post_id == $topic_data['topic_first_post_id']) ? 'd' : 'a';
305
306
                if ($sort_dir == $check_sort)
307
                {
308
                        $topic_data['prev_posts'] = ($auth->acl_get('m_approve', $forum_id)) ? $topic_data['topic_replies_real'] : $topic_data['topic_replies'];
309
                }
310
                else
311
                {
312
                        $topic_data['prev_posts'] = 0;
313
                }
314
        }
315
        else
316
        {
317
                $sql = 'SELECT COUNT(p.post_id) AS prev_posts
318
                        FROM ' . POSTS_TABLE . " p
319
                        WHERE p.topic_id = {$topic_data['topic_id']}
320
                                " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '');
321
322
                if ($sort_dir == 'd')
323
                {
324
                        $sql .= " AND (p.post_time > {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id >= {$topic_data['post_id']}))";
325
                }
326
                else
327
                {
328
                        $sql .= " AND (p.post_time < {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id <= {$topic_data['post_id']}))";
329
                }
330
331
                $result = $db->sql_query($sql);
332
                $row = $db->sql_fetchrow($result);
333
                $db->sql_freeresult($result);
334
335
                $topic_data['prev_posts'] = $row['prev_posts'] - 1;
336
        }
337
}
338
339
$topic_id = (int) $topic_data['topic_id'];
340
//
341
$topic_replies = ($auth->acl_get('m_approve', $forum_id)) ? $topic_data['topic_replies_real'] : $topic_data['topic_replies'];
342
343
// Check sticky/announcement time limit
344
if (($topic_data['topic_type'] == POST_STICKY || $topic_data['topic_type'] == POST_ANNOUNCE) && $topic_data['topic_time_limit'] && ($topic_data['topic_time'] + $topic_data['topic_time_limit']) < time())
345
{
346
        $sql = 'UPDATE ' . TOPICS_TABLE . '
347
                SET topic_type = ' . POST_NORMAL . ', topic_time_limit = 0
348
                WHERE topic_id = ' . $topic_id;
349
        $db->sql_query($sql);
350
351
        $topic_data['topic_type'] = POST_NORMAL;
352
        $topic_data['topic_time_limit'] = 0;
353
}
354
355
// Setup look and feel
356
$user->setup('viewtopic', $topic_data['forum_style']);
357
358
if (!$topic_data['topic_approved'] && !$auth->acl_get('m_approve', $forum_id))
359
{
360
        trigger_error('NO_TOPIC');
361
}
362
363
// Start auth check
364
if (!$auth->acl_get('f_read', $forum_id))
365
{
366
        if ($user->data['user_id'] != ANONYMOUS)
367
        {
368
                trigger_error('SORRY_AUTH_READ');
369
        }
370
371
        login_box('', $user->lang['LOGIN_VIEWFORUM']);
372
}
373
374
// Forum is passworded ... check whether access has been granted to this
375
// user this session, if not show login box
376
if ($topic_data['forum_password'])
377
{
378
        login_forum_box($topic_data);
379
}
380
381
// Redirect to login or to the correct post upon emailed notification links
382
if (isset($_GET['e']))
383
{
384
        $jump_to = request_var('e', 0);
385
386
        $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id");
387
388
        if ($user->data['user_id'] == ANONYMOUS)
389
        {
390
                login_box($redirect_url . "&amp;p=$post_id&amp;e=$jump_to", $user->lang['LOGIN_NOTIFY_TOPIC']);
391
        }
392
393
        if ($jump_to > 0)
394
        {
395
                // We direct the already logged in user to the correct post...
396
                redirect($redirect_url . ((!$post_id) ? "&amp;p=$jump_to" : "&amp;p=$post_id") . "#p$jump_to");
397
        }
398
}
399
400
// What is start equal to?
401
if ($post_id)
402
{
403
        $start = floor(($topic_data['prev_posts']) / $config['posts_per_page']) * $config['posts_per_page'];
404
}
405
406
// Get topic tracking info
407
if (!isset($topic_tracking_info))
408
{
409
        $topic_tracking_info = array();
410
411
        // Get topic tracking info
412
        if ($config['load_db_lastread'] && $user->data['is_registered'])
413
        {
414
                $tmp_topic_data = array($topic_id => $topic_data);
415
                $topic_tracking_info = get_topic_tracking($forum_id, $topic_id, $tmp_topic_data, array($forum_id => $topic_data['forum_mark_time']));
416
                unset($tmp_topic_data);
417
        }
418
        else if ($config['load_anon_lastread'] || $user->data['is_registered'])
419
        {
420
                $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_id);
421
        }
422
}
423
424
// Post ordering options
425
$limit_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
426
427
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
428
$sort_by_sql = array('a' => array('u.username_clean', 'p.post_id'), 't' => 'p.post_time', 's' => array('p.post_subject', 'p.post_id'));
429
$join_user_sql = array('a' => true, 't' => false, 's' => false);
430
431
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
432
433
gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir);
434
435
// Obtain correct post count and ordering SQL if user has
436
// requested anything different
437
if ($sort_days)
438
{
439
        $min_post_time = time() - ($sort_days * 86400);
440
441
        $sql = 'SELECT COUNT(post_id) AS num_posts
442
                FROM ' . POSTS_TABLE . "
443
                WHERE topic_id = $topic_id
444
                        AND post_time >= $min_post_time
445
                " . (($auth->acl_get('m_approve', $forum_id)) ? '' : 'AND post_approved = 1');
446
        $result = $db->sql_query($sql);
447
        $total_posts = (int) $db->sql_fetchfield('num_posts');
448
        $db->sql_freeresult($result);
449
450
        $limit_posts_time = "AND p.post_time >= $min_post_time ";
451
452
        if (isset($_POST['sort']))
453
        {
454
                $start = 0;
455
        }
456
}
457
else
458
{
459
        $total_posts = $topic_replies + 1;
460
        $limit_posts_time = '';
461
}
462
463
// Was a highlight request part of the URI?
464
$highlight_match = $highlight = '';
465
if ($hilit_words)
466
{
467
        foreach (explode(' ', trim($hilit_words)) as $word)
468
        {
469
                if (trim($word))
470
                {
471
                        $word = str_replace('\*', '\w+?', preg_quote($word, '#'));
472
                        $word = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $word);
473
                        $highlight_match .= (($highlight_match != '') ? '|' : '') . $word;
474
                }
475
        }
476
477
        $highlight = urlencode($hilit_words);
478
}
479
480
// Make sure $start is set to the last page if it exceeds the amount
481
if ($start < 0 || $start >= $total_posts)
482
{
483
        $start = ($start < 0) ? 0 : floor(($total_posts - 1) / $config['posts_per_page']) * $config['posts_per_page'];
484
}
485
486
// General Viewtopic URL for return links
487
$viewtopic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start") . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : '') . (($highlight_match) ? "&amp;hilit=$highlight" : ''));
488
489
// Are we watching this topic?
490
$s_watching_topic = array(
491
        'link'                        => '',
492
        'title'                        => '',
493
        'is_watching'        => false,
494
);
495
496
if (($config['email_enable'] || $config['jab_enable']) && $config['allow_topic_notify'])
497
{
498
        $notify_status = (isset($topic_data['notify_status'])) ? $topic_data['notify_status'] : null;
499
        watch_topic_forum('topic', $s_watching_topic, $user->data['user_id'], $forum_id, $topic_id, $notify_status, $start, $topic_data['topic_title']);
500
501
        // Reset forum notification if forum notify is set
502
        if ($config['allow_forum_notify'] && $auth->acl_get('f_subscribe', $forum_id))
503
        {
504
                $s_watching_forum = $s_watching_topic;
505
                watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0);
506
        }
507
}
508
509
// Bookmarks
510
if ($config['allow_bookmarks'] && $user->data['is_registered'] && request_var('bookmark', 0))
511
{
512
        if (check_link_hash(request_var('hash', ''), "topic_$topic_id"))
513
        {
514
                if (!$topic_data['bookmarked'])
515
                {
516
                        $sql = 'INSERT INTO ' . BOOKMARKS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
517
                                'user_id'        => $user->data['user_id'],
518
                                'topic_id'        => $topic_id,
519
                        ));
520
                        $db->sql_query($sql);
521
                }
522
                else
523
                {
524
                        $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . "
525
                                WHERE user_id = {$user->data['user_id']}
526
                                        AND topic_id = $topic_id";
527
                        $db->sql_query($sql);
528
                }
529
                $message = (($topic_data['bookmarked']) ? $user->lang['BOOKMARK_REMOVED'] : $user->lang['BOOKMARK_ADDED']) . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $viewtopic_url . '">', '</a>');
530
        }
531
        else
532
        {
533
                $message = $user->lang['BOOKMARK_ERR'] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $viewtopic_url . '">', '</a>');
534
        }
535
        meta_refresh(3, $viewtopic_url);
536
537
        trigger_error($message);
538
}
539
540
// Grab ranks
541
$ranks = $cache->obtain_ranks();
542
543
// Grab icons
544
$icons = $cache->obtain_icons();
545
546
// Grab extensions
547
$extensions = array();
548
if ($topic_data['topic_attachment'])
549
{
550
        $extensions = $cache->obtain_attach_extensions($forum_id);
551
}
552
553
// Forum rules listing
554
$s_forum_rules = '';
555
gen_forum_auth_level('topic', $forum_id, $topic_data['forum_status']);
556
557
// Quick mod tools
558
$allow_change_type = ($auth->acl_get('m_', $forum_id) || ($user->data['is_registered'] && $user->data['user_id'] == $topic_data['topic_poster'])) ? true : false;
559
560
$topic_mod = '';
561
$topic_mod .= ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_user_lock', $forum_id) && $user->data['is_registered'] && $user->data['user_id'] == $topic_data['topic_poster'] && $topic_data['topic_status'] == ITEM_UNLOCKED)) ? (($topic_data['topic_status'] == ITEM_UNLOCKED) ? '<option value="lock">' . $user->lang['LOCK_TOPIC'] . '</option>' : '<option value="unlock">' . $user->lang['UNLOCK_TOPIC'] . '</option>') : '';
562
$topic_mod .= ($auth->acl_get('m_delete', $forum_id)) ? '<option value="delete_topic">' . $user->lang['DELETE_TOPIC'] . '</option>' : '';
563
$topic_mod .= ($auth->acl_get('m_move', $forum_id) && $topic_data['topic_status'] != ITEM_MOVED) ? '<option value="move">' . $user->lang['MOVE_TOPIC'] . '</option>' : '';
564
$topic_mod .= ($auth->acl_get('m_split', $forum_id)) ? '<option value="split">' . $user->lang['SPLIT_TOPIC'] . '</option>' : '';
565
$topic_mod .= ($auth->acl_get('m_merge', $forum_id)) ? '<option value="merge">' . $user->lang['MERGE_POSTS'] . '</option>' : '';
566
$topic_mod .= ($auth->acl_get('m_merge', $forum_id)) ? '<option value="merge_topic">' . $user->lang['MERGE_TOPIC'] . '</option>' : '';
567
$topic_mod .= ($auth->acl_get('m_move', $forum_id)) ? '<option value="fork">' . $user->lang['FORK_TOPIC'] . '</option>' : '';
568
$topic_mod .= ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', $forum_id) && $topic_data['topic_type'] != POST_NORMAL) ? '<option value="make_normal">' . $user->lang['MAKE_NORMAL'] . '</option>' : '';
569
$topic_mod .= ($allow_change_type && $auth->acl_get('f_sticky', $forum_id) && $topic_data['topic_type'] != POST_STICKY) ? '<option value="make_sticky">' . $user->lang['MAKE_STICKY'] . '</option>' : '';
570
$topic_mod .= ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_ANNOUNCE) ? '<option value="make_announce">' . $user->lang['MAKE_ANNOUNCE'] . '</option>' : '';
571
$topic_mod .= ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL) ? '<option value="make_global">' . $user->lang['MAKE_GLOBAL'] . '</option>' : '';
572
$topic_mod .= ($auth->acl_get('m_', $forum_id)) ? '<option value="topic_logs">' . $user->lang['VIEW_TOPIC_LOGS'] . '</option>' : '';
573
574
// If we've got a hightlight set pass it on to pagination.
575
$pagination = generate_pagination(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : '') . (($highlight_match) ? "&amp;hilit=$highlight" : '')), $total_posts, $config['posts_per_page'], $start);
576
577
// Navigation links
578
generate_forum_nav($topic_data);
579
580
// Forum Rules
581
generate_forum_rules($topic_data);
582
583
// Moderators
584
$forum_moderators = array();
585
if ($config['load_moderators'])
586
{
587
        get_moderators($forum_moderators, $forum_id);
588
}
589
590
// This is only used for print view so ...
591
$server_path = (!$view) ? $phpbb_root_path : generate_board_url() . '/';
592
593
// Replace naughty words in title
594
$topic_data['topic_title'] = censor_text($topic_data['topic_title']);
595
596
$s_search_hidden_fields = array(
597
        't' => $topic_id,
598
        'sf' => 'msgonly',
599
);
600
if ($_SID)
601
{
602
        $s_search_hidden_fields['sid'] = $_SID;
603
}
604
605
if (!empty($_EXTRA_URL))
606
{
607
        foreach ($_EXTRA_URL as $url_param)
608
        {
609
                $url_param = explode('=', $url_param, 2);
610
                $s_search_hidden_fields[$url_param[0]] = $url_param[1];
611
        }
612
}
613
614
// Send vars to template
615
$template->assign_vars(array(
616
        'FORUM_ID'                 => $forum_id,
617
        'FORUM_NAME'         => $topic_data['forum_name'],
618
        'FORUM_DESC'        => generate_text_for_display($topic_data['forum_desc'], $topic_data['forum_desc_uid'], $topic_data['forum_desc_bitfield'], $topic_data['forum_desc_options']),
619
        'TOPIC_ID'                 => $topic_id,
620
        'TOPIC_TITLE'         => $topic_data['topic_title'],
621
        'TOPIC_POSTER'        => $topic_data['topic_poster'],
622
623
        'TOPIC_AUTHOR_FULL'                => get_username_string('full', $topic_data['topic_poster'], $topic_data['topic_first_poster_name'], $topic_data['topic_first_poster_colour']),
624
        'TOPIC_AUTHOR_COLOUR'        => get_username_string('colour', $topic_data['topic_poster'], $topic_data['topic_first_poster_name'], $topic_data['topic_first_poster_colour']),
625
        'TOPIC_AUTHOR'                        => get_username_string('username', $topic_data['topic_poster'], $topic_data['topic_first_poster_name'], $topic_data['topic_first_poster_colour']),
626
627
        'PAGINATION'         => $pagination,
628
        'PAGE_NUMBER'         => on_page($total_posts, $config['posts_per_page'], $start),
629
        'TOTAL_POSTS'        => ($total_posts == 1) ? $user->lang['VIEW_TOPIC_POST'] : sprintf($user->lang['VIEW_TOPIC_POSTS'], $total_posts),
630
        'U_MCP'                 => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&amp;mode=topic_view&amp;f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start") . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : ''), true, $user->session_id) : '',
631
        'MODERATORS'        => (isset($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id])) ? implode(', ', $forum_moderators[$forum_id]) : '',
632
633
        'POST_IMG'                         => ($topic_data['forum_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', 'FORUM_LOCKED') : $user->img('button_topic_new', 'POST_NEW_TOPIC'),
634
        'QUOTE_IMG'                 => $user->img('icon_post_quote', 'REPLY_WITH_QUOTE'),
635
        'REPLY_IMG'                        => ($topic_data['forum_status'] == ITEM_LOCKED || $topic_data['topic_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', 'TOPIC_LOCKED') : $user->img('button_topic_reply', 'REPLY_TO_TOPIC'),
636
        'EDIT_IMG'                         => $user->img('icon_post_edit', 'EDIT_POST'),
637
        'DELETE_IMG'                 => $user->img('icon_post_delete', 'DELETE_POST'),
638
        'INFO_IMG'                         => $user->img('icon_post_info', 'VIEW_INFO'),
639
        'PROFILE_IMG'                => $user->img('icon_user_profile', 'READ_PROFILE'),
640
        'SEARCH_IMG'                 => $user->img('icon_user_search', 'SEARCH_USER_POSTS'),
641
        'PM_IMG'                         => $user->img('icon_contact_pm', 'SEND_PRIVATE_MESSAGE'),
642
        'EMAIL_IMG'                 => $user->img('icon_contact_email', 'SEND_EMAIL'),
643
        'WWW_IMG'                         => $user->img('icon_contact_www', 'VISIT_WEBSITE'),
644
        'ICQ_IMG'                         => $user->img('icon_contact_icq', 'ICQ'),
645
        'AIM_IMG'                         => $user->img('icon_contact_aim', 'AIM'),
646
        'MSN_IMG'                         => $user->img('icon_contact_msnm', 'MSNM'),
647
        'YIM_IMG'                         => $user->img('icon_contact_yahoo', 'YIM'),
648
        'JABBER_IMG'                => $user->img('icon_contact_jabber', 'JABBER') ,
649
        'REPORT_IMG'                => $user->img('icon_post_report', 'REPORT_POST'),
650
        'REPORTED_IMG'                => $user->img('icon_topic_reported', 'POST_REPORTED'),
651
        'UNAPPROVED_IMG'        => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED'),
652
        'WARN_IMG'                        => $user->img('icon_user_warn', 'WARN_USER'),
653
654
        'S_IS_LOCKED'                        => ($topic_data['topic_status'] == ITEM_UNLOCKED && $topic_data['forum_status'] == ITEM_UNLOCKED) ? false : true,
655
        'S_SELECT_SORT_DIR'         => $s_sort_dir,
656
        'S_SELECT_SORT_KEY'         => $s_sort_key,
657
        'S_SELECT_SORT_DAYS'         => $s_limit_days,
658
        'S_SINGLE_MODERATOR'        => (!empty($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id]) > 1) ? false : true,
659
        'S_TOPIC_ACTION'                 => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start")),
660
        'S_TOPIC_MOD'                         => ($topic_mod != '') ? '<select name="action" id="quick-mod-select">' . $topic_mod . '</select>' : '',
661
        'S_MOD_ACTION'                         => append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start") . "&amp;quickmod=1&amp;redirect=" . urlencode(str_replace('&amp;', '&', $viewtopic_url)), true, $user->session_id),
662
663
        'S_VIEWTOPIC'                        => true,
664
        'S_DISPLAY_SEARCHBOX'        => ($auth->acl_get('u_search') && $auth->acl_get('f_search', $forum_id) && $config['load_search']) ? true : false,
665
        'S_SEARCHBOX_ACTION'        => append_sid("{$phpbb_root_path}search.$phpEx"),
666
        'S_SEARCH_LOCAL_HIDDEN_FIELDS'        => build_hidden_fields($s_search_hidden_fields),
667
668
        'S_DISPLAY_POST_INFO'        => ($topic_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS)) ? true : false,
669
        'S_DISPLAY_REPLY_INFO'        => ($topic_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_reply', $forum_id) || $user->data['user_id'] == ANONYMOUS)) ? true : false,
670
        'S_ENABLE_FEEDS_TOPIC'        => ($config['feed_topic'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $topic_data['forum_options'])) ? true : false,
671
672
        'U_TOPIC'                                => "{$server_path}viewtopic.$phpEx?f=$forum_id&amp;t=$topic_id",
673
        'U_FORUM'                                => $server_path,
674
        'U_VIEW_TOPIC'                         => $viewtopic_url,
675
        'U_VIEW_FORUM'                         => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
676
        'U_VIEW_OLDER_TOPIC'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=previous"),
677
        'U_VIEW_NEWER_TOPIC'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=next"),
678
        'U_PRINT_TOPIC'                        => ($auth->acl_get('f_print', $forum_id)) ? $viewtopic_url . '&amp;view=print' : '',
679
        'U_EMAIL_TOPIC'                        => ($auth->acl_get('f_email', $forum_id) && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&amp;t=$topic_id") : '',
680
681
        'U_WATCH_TOPIC'                 => $s_watching_topic['link'],
682
        'L_WATCH_TOPIC'                 => $s_watching_topic['title'],
683
        'S_WATCHING_TOPIC'                => $s_watching_topic['is_watching'],
684
685
        'U_BOOKMARK_TOPIC'                => ($user->data['is_registered'] && $config['allow_bookmarks']) ? $viewtopic_url . '&amp;bookmark=1&amp;hash=' . generate_link_hash("topic_$topic_id") : '',
686
        'L_BOOKMARK_TOPIC'                => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'],
687
688
        'U_POST_NEW_TOPIC'                 => ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=post&amp;f=$forum_id") : '',
689
        'U_POST_REPLY_TOPIC'         => ($auth->acl_get('f_reply', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=reply&amp;f=$forum_id&amp;t=$topic_id") : '',
690
        'U_BUMP_TOPIC'                        => (bump_topic_allowed($forum_id, $topic_data['topic_bumped'], $topic_data['topic_last_post_time'], $topic_data['topic_poster'], $topic_data['topic_last_poster_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=bump&amp;f=$forum_id&amp;t=$topic_id&amp;hash=" . generate_link_hash("topic_$topic_id")) : '')
691
);
692
693
// Does this topic contain a poll?
694
if (!empty($topic_data['poll_start']))
695
{
696
        $sql = 'SELECT o.*, p.bbcode_bitfield, p.bbcode_uid
697
                FROM ' . POLL_OPTIONS_TABLE . ' o, ' . POSTS_TABLE . " p
698
                WHERE o.topic_id = $topic_id
699
                        AND p.post_id = {$topic_data['topic_first_post_id']}
700
                        AND p.topic_id = o.topic_id
701
                ORDER BY o.poll_option_id";
702
        $result = $db->sql_query($sql);
703
704
        $poll_info = array();
705
        while ($row = $db->sql_fetchrow($result))
706
        {
707
                $poll_info[] = $row;
708
        }
709
        $db->sql_freeresult($result);
710
711
        $cur_voted_id = array();
712
        if ($user->data['is_registered'])
713
        {
714
                $sql = 'SELECT poll_option_id
715
                        FROM ' . POLL_VOTES_TABLE . '
716
                        WHERE topic_id = ' . $topic_id . '
717
                                AND vote_user_id = ' . $user->data['user_id'];
718
                $result = $db->sql_query($sql);
719
720
                while ($row = $db->sql_fetchrow($result))
721
                {
722
                        $cur_voted_id[] = $row['poll_option_id'];
723
                }
724
                $db->sql_freeresult($result);
725
        }
726
        else
727
        {
728
                // Cookie based guest tracking ... I don't like this but hum ho
729
                // it's oft requested. This relies on "nice" users who don't feel
730
                // the need to delete cookies to mess with results.
731
                if (isset($_COOKIE[$config['cookie_name'] . '_poll_' . $topic_id]))
732
                {
733
                        $cur_voted_id = explode(',', $_COOKIE[$config['cookie_name'] . '_poll_' . $topic_id]);
734
                        $cur_voted_id = array_map('intval', $cur_voted_id);
735
                }
736
        }
737
738
        // Can not vote at all if no vote permission
739
        $s_can_vote = ($auth->acl_get('f_vote', $forum_id) &&
740
                (($topic_data['poll_length'] != 0 && $topic_data['poll_start'] + $topic_data['poll_length'] > time()) || $topic_data['poll_length'] == 0) &&
741
                $topic_data['topic_status'] != ITEM_LOCKED &&
742
                $topic_data['forum_status'] != ITEM_LOCKED &&
743
                (!sizeof($cur_voted_id) ||
744
                ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']))) ? true : false;
745
        $s_display_results = (!$s_can_vote || ($s_can_vote && sizeof($cur_voted_id)) || $view == 'viewpoll') ? true : false;
746
747
        if ($update && $s_can_vote)
748
        {
749
750
                if (!sizeof($voted_id) || sizeof($voted_id) > $topic_data['poll_max_options'] || in_array(VOTE_CONVERTED, $cur_voted_id) || !check_form_key('posting'))
751
                {
752
                        $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start"));
753
754
                        meta_refresh(5, $redirect_url);
755
                        if (!sizeof($voted_id))
756
                        {
757
                                $message = 'NO_VOTE_OPTION';
758
                        }
759
                        else if (sizeof($voted_id) > $topic_data['poll_max_options'])
760
                        {
761
                                $message = 'TOO_MANY_VOTE_OPTIONS';
762
                        }
763
                        else if (in_array(VOTE_CONVERTED, $cur_voted_id))
764
                        {
765
                                $message = 'VOTE_CONVERTED';
766
                        }
767
                        else
768
                        {
769
                                $message = 'FORM_INVALID';
770
                        }
771
772
                        $message = $user->lang[$message] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
773
                        trigger_error($message);
774
                }
775
776
                foreach ($voted_id as $option)
777
                {
778
                        if (in_array($option, $cur_voted_id))
779
                        {
780
                                continue;
781
                        }
782
783
                        $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . '
784
                                SET poll_option_total = poll_option_total + 1
785
                                WHERE poll_option_id = ' . (int) $option . '
786
                                        AND topic_id = ' . (int) $topic_id;
787
                        $db->sql_query($sql);
788
789
                        if ($user->data['is_registered'])
790
                        {
791
                                $sql_ary = array(
792
                                        'topic_id'                        => (int) $topic_id,
793
                                        'poll_option_id'        => (int) $option,
794
                                        'vote_user_id'                => (int) $user->data['user_id'],
795
                                        'vote_user_ip'                => (string) $user->ip,
796
                                );
797
798
                                $sql = 'INSERT INTO ' . POLL_VOTES_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
799
                                $db->sql_query($sql);
800
                        }
801
                }
802
803
                foreach ($cur_voted_id as $option)
804
                {
805
                        if (!in_array($option, $voted_id))
806
                        {
807
                                $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . '
808
                                        SET poll_option_total = poll_option_total - 1
809
                                        WHERE poll_option_id = ' . (int) $option . '
810
                                                AND topic_id = ' . (int) $topic_id;
811
                                $db->sql_query($sql);
812
813
                                if ($user->data['is_registered'])
814
                                {
815
                                        $sql = 'DELETE FROM ' . POLL_VOTES_TABLE . '
816
                                                WHERE topic_id = ' . (int) $topic_id . '
817
                                                        AND poll_option_id = ' . (int) $option . '
818
                                                        AND vote_user_id = ' . (int) $user->data['user_id'];
819
                                        $db->sql_query($sql);
820
                                }
821
                        }
822
                }
823
824
                if ($user->data['user_id'] == ANONYMOUS && !$user->data['is_bot'])
825
                {
826
                        $user->set_cookie('poll_' . $topic_id, implode(',', $voted_id), time() + 31536000);
827
                }
828
829
                $sql = 'UPDATE ' . TOPICS_TABLE . '
830
                        SET poll_last_vote = ' . time() . "
831
                        WHERE topic_id = $topic_id";
832
                //, topic_last_post_time = ' . time() . " -- for bumping topics with new votes, ignore for now
833
                $db->sql_query($sql);
834
835
                $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start"));
836
837
                meta_refresh(5, $redirect_url);
838
                trigger_error($user->lang['VOTE_SUBMITTED'] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>'));
839
        }
840
841
        $poll_total = 0;
842
        foreach ($poll_info as $poll_option)
843
        {
844
                $poll_total += $poll_option['poll_option_total'];
845
        }
846
847
        if ($poll_info[0]['bbcode_bitfield'])
848
        {
849
                $poll_bbcode = new bbcode();
850
        }
851
        else
852
        {
853
                $poll_bbcode = false;
854
        }
855
856
        for ($i = 0, $size = sizeof($poll_info); $i < $size; $i++)
857
        {
858
                $poll_info[$i]['poll_option_text'] = censor_text($poll_info[$i]['poll_option_text']);
859
860
                if ($poll_bbcode !== false)
861
                {
862
                        $poll_bbcode->bbcode_second_pass($poll_info[$i]['poll_option_text'], $poll_info[$i]['bbcode_uid'], $poll_option['bbcode_bitfield']);
863
                }
864
865
                $poll_info[$i]['poll_option_text'] = bbcode_nl2br($poll_info[$i]['poll_option_text']);
866
                $poll_info[$i]['poll_option_text'] = smiley_text($poll_info[$i]['poll_option_text']);
867
        }
868
869
        $topic_data['poll_title'] = censor_text($topic_data['poll_title']);
870
871
        if ($poll_bbcode !== false)
872
        {
873
                $poll_bbcode->bbcode_second_pass($topic_data['poll_title'], $poll_info[0]['bbcode_uid'], $poll_info[0]['bbcode_bitfield']);
874
        }
875
876
        $topic_data['poll_title'] = bbcode_nl2br($topic_data['poll_title']);
877
        $topic_data['poll_title'] = smiley_text($topic_data['poll_title']);
878
879
        unset($poll_bbcode);
880
881
        foreach ($poll_info as $poll_option)
882
        {
883
                $option_pct = ($poll_total > 0) ? $poll_option['poll_option_total'] / $poll_total : 0;
884
                $option_pct_txt = sprintf("%.1d%%", round($option_pct * 100));
885
886
                $template->assign_block_vars('poll_option', array(
887
                        'POLL_OPTION_ID'                 => $poll_option['poll_option_id'],
888
                        'POLL_OPTION_CAPTION'         => $poll_option['poll_option_text'],
889
                        'POLL_OPTION_RESULT'         => $poll_option['poll_option_total'],
890
                        'POLL_OPTION_PERCENT'         => $option_pct_txt,
891
                        'POLL_OPTION_PCT'                => round($option_pct * 100),
892
                        'POLL_OPTION_IMG'                 => $user->img('poll_center', $option_pct_txt, round($option_pct * 250)),
893
                        'POLL_OPTION_VOTED'                => (in_array($poll_option['poll_option_id'], $cur_voted_id)) ? true : false)
894
                );
895
        }
896
897
        $poll_end = $topic_data['poll_length'] + $topic_data['poll_start'];
898
899
        $template->assign_vars(array(
900
                'POLL_QUESTION'                => $topic_data['poll_title'],
901
                'TOTAL_VOTES'                 => $poll_total,
902
                'POLL_LEFT_CAP_IMG'        => $user->img('poll_left'),
903
                'POLL_RIGHT_CAP_IMG'=> $user->img('poll_right'),
904
905
                'L_MAX_VOTES'                => ($topic_data['poll_max_options'] == 1) ? $user->lang['MAX_OPTION_SELECT'] : sprintf($user->lang['MAX_OPTIONS_SELECT'], $topic_data['poll_max_options']),
906
                'L_POLL_LENGTH'                => ($topic_data['poll_length']) ? sprintf($user->lang[($poll_end > time()) ? 'POLL_RUN_TILL' : 'POLL_ENDED_AT'], $user->format_date($poll_end)) : '',
907
908
                'S_HAS_POLL'                => true,
909
                'S_CAN_VOTE'                => $s_can_vote,
910
                'S_DISPLAY_RESULTS'        => $s_display_results,
911
                'S_IS_MULTI_CHOICE'        => ($topic_data['poll_max_options'] > 1) ? true : false,
912
                'S_POLL_ACTION'                => $viewtopic_url,
913
914
                'U_VIEW_RESULTS'        => $viewtopic_url . '&amp;view=viewpoll')
915
        );
916
917
        unset($poll_end, $poll_info, $voted_id);
918
}
919
920
// If the user is trying to reach the second half of the topic, fetch it starting from the end
921
$store_reverse = false;
922
$sql_limit = $config['posts_per_page'];
923
$sql_sort_order = $direction = '';
924
925
if ($start > $total_posts / 2)
926
{
927
        $store_reverse = true;
928
929
        if ($start + $config['posts_per_page'] > $total_posts)
930
        {
931
                $sql_limit = min($config['posts_per_page'], max(1, $total_posts - $start));
932
        }
933
934
        // Select the sort order
935
        $direction = (($sort_dir == 'd') ? 'ASC' : 'DESC');
936
        $sql_start = max(0, $total_posts - $sql_limit - $start);
937
}
938
else
939
{
940
        // Select the sort order
941
        $direction = (($sort_dir == 'd') ? 'DESC' : 'ASC');
942
        $sql_start = $start;
943
}
944
945
if (is_array($sort_by_sql[$sort_key]))
946
{
947
        $sql_sort_order = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction;
948
}
949
else
950
{
951
        $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . $direction;
952
}
953
954
// Container for user details, only process once
955
$post_list = $user_cache = $id_cache = $attachments = $attach_list = $rowset = $update_count = $post_edit_list = array();
956
$has_attachments = $display_notice = false;
957
$bbcode_bitfield = '';
958
$i = $i_total = 0;
959
960
// Go ahead and pull all data for this topic
961
$sql = 'SELECT p.post_id
962
        FROM ' . POSTS_TABLE . ' p' . (($join_user_sql[$sort_key]) ? ', ' . USERS_TABLE . ' u': '') . "
963
        WHERE p.topic_id = $topic_id
964
                " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . "
965
                " . (($join_user_sql[$sort_key]) ? 'AND u.user_id = p.poster_id': '') . "
966
                $limit_posts_time
967
        ORDER BY $sql_sort_order";
968
$result = $db->sql_query_limit($sql, $sql_limit, $sql_start);
969
970
$i = ($store_reverse) ? $sql_limit - 1 : 0;
971
while ($row = $db->sql_fetchrow($result))
972
{
973
        $post_list[$i] = (int) $row['post_id'];
974
        ($store_reverse) ? $i-- : $i++;
975
}
976
$db->sql_freeresult($result);
977
978
if (!sizeof($post_list))
979
{
980
        if ($sort_days)
981
        {
982
                trigger_error('NO_POSTS_TIME_FRAME');
983
        }
984
        else
985
        {
986
                trigger_error('NO_TOPIC');
987
        }
988
}
989
990
// Holding maximum post time for marking topic read
991
// We need to grab it because we do reverse ordering sometimes
992
$max_post_time = 0;
993
994
$sql = $db->sql_build_query('SELECT', array(
995
        'SELECT'        => 'u.*, z.friend, z.foe, p.*',
996
997
        'FROM'                => array(
998
                USERS_TABLE                => 'u',
999
                POSTS_TABLE                => 'p',
1000
        ),
1001
1002
        'LEFT_JOIN'        => array(
1003
                array(
1004
                        'FROM'        => array(ZEBRA_TABLE => 'z'),
1005
                        'ON'        => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id'
1006
                )
1007
        ),
1008
1009
        'WHERE'                => $db->sql_in_set('p.post_id', $post_list) . '
1010
                AND u.user_id = p.poster_id'
1011
));
1012
1013
$result = $db->sql_query($sql);
1014
1015
$now = phpbb_gmgetdate(time() + $user->timezone + $user->dst);
1016
1017
// Posts are stored in the $rowset array while $attach_list, $user_cache
1018
// and the global bbcode_bitfield are built
1019
while ($row = $db->sql_fetchrow($result))
1020
{
1021
        // Set max_post_time
1022
        if ($row['post_time'] > $max_post_time)
1023
        {
1024
                $max_post_time = $row['post_time'];
1025
        }
1026
1027
        $poster_id = (int) $row['poster_id'];
1028
1029
        // Does post have an attachment? If so, add it to the list
1030
        if ($row['post_attachment'] && $config['allow_attachments'])
1031
        {
1032
                $attach_list[] = (int) $row['post_id'];
1033
1034
                if ($row['post_approved'])
1035
                {
1036
                        $has_attachments = true;
1037
                }
1038
        }
1039
1040
        $rowset[$row['post_id']] = array(
1041
                'hide_post'                        => ($row['foe'] && ($view != 'show' || $post_id != $row['post_id'])) ? true : false,
1042
1043
                'post_id'                        => $row['post_id'],
1044
                'post_time'                        => $row['post_time'],
1045
                'user_id'                        => $row['user_id'],
1046
                'username'                        => $row['username'],
1047
                'user_colour'                => $row['user_colour'],
1048
                'topic_id'                        => $row['topic_id'],
1049
                'forum_id'                        => $row['forum_id'],
1050
                'post_subject'                => $row['post_subject'],
1051
                'post_edit_count'        => $row['post_edit_count'],
1052
                'post_edit_time'        => $row['post_edit_time'],
1053
                'post_edit_reason'        => $row['post_edit_reason'],
1054
                'post_edit_user'        => $row['post_edit_user'],
1055
                'post_edit_locked'        => $row['post_edit_locked'],
1056
1057
                // Make sure the icon actually exists
1058
                'icon_id'                        => (isset($icons[$row['icon_id']]['img'], $icons[$row['icon_id']]['height'], $icons[$row['icon_id']]['width'])) ? $row['icon_id'] : 0,
1059
                'post_attachment'        => $row['post_attachment'],
1060
                'post_approved'                => $row['post_approved'],
1061
                'post_reported'                => $row['post_reported'],
1062
                'post_username'                => $row['post_username'],
1063
                'post_text'                        => $row['post_text'],
1064
                'bbcode_uid'                => $row['bbcode_uid'],
1065
                'bbcode_bitfield'        => $row['bbcode_bitfield'],
1066
                'enable_smilies'        => $row['enable_smilies'],
1067
                'enable_sig'                => $row['enable_sig'],
1068
                'friend'                        => $row['friend'],
1069
                'foe'                                => $row['foe'],
1070
        );
1071
1072
        // Define the global bbcode bitfield, will be used to load bbcodes
1073
        $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
1074
1075
        // Is a signature attached? Are we going to display it?
1076
        if ($row['enable_sig'] && $config['allow_sig'] && $user->optionget('viewsigs'))
1077
        {
1078
                $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['user_sig_bbcode_bitfield']);
1079
        }
1080
1081
        // Cache various user specific data ... so we don't have to recompute
1082
        // this each time the same user appears on this page
1083
        if (!isset($user_cache[$poster_id]))
1084
        {
1085
                if ($poster_id == ANONYMOUS)
1086
                {
1087
                        $user_cache[$poster_id] = array(
1088
                                'joined'                => '',
1089
                                'posts'                        => '',
1090
                                'from'                        => '',
1091
1092
                                'sig'                                        => '',
1093
                                'sig_bbcode_uid'                => '',
1094
                                'sig_bbcode_bitfield'        => '',
1095
1096
                                'online'                        => false,
1097
                                'avatar'                        => ($user->optionget('viewavatars')) ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], $row['user_avatar_width'], $row['user_avatar_height']) : '',
1098
                                'rank_title'                => '',
1099
                                'rank_image'                => '',
1100
                                'rank_image_src'        => '',
1101
                                'sig'                                => '',
1102
                                'profile'                        => '',
1103
                                'pm'                                => '',
1104
                                'email'                                => '',
1105
                                'www'                                => '',
1106
                                'icq_status_img'        => '',
1107
                                'icq'                                => '',
1108
                                'aim'                                => '',
1109
                                'msn'                                => '',
1110
                                'yim'                                => '',
1111
                                'jabber'                        => '',
1112
                                'search'                        => '',
1113
                                'age'                                => '',
1114
1115
                                'username'                        => $row['username'],
1116
                                'user_colour'                => $row['user_colour'],
1117
1118
                                'warnings'                        => 0,
1119
                                'allow_pm'                        => 0,
1120
                        );
1121
1122
                        get_user_rank($row['user_rank'], false, $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']);
1123
                }
1124
                else
1125
                {
1126
                        $user_sig = '';
1127
1128
                        // We add the signature to every posters entry because enable_sig is post dependant
1129
                        if ($row['user_sig'] && $config['allow_sig'] && $user->optionget('viewsigs'))
1130
                        {
1131
                                $user_sig = $row['user_sig'];
1132
                        }
1133
1134
                        $id_cache[] = $poster_id;
1135
1136
                        $user_cache[$poster_id] = array(
1137
                                'joined'                => $user->format_date($row['user_regdate']),
1138
                                'posts'                        => $row['user_posts'],
1139
                                'warnings'                => (isset($row['user_warnings'])) ? $row['user_warnings'] : 0,
1140
                                'from'                        => (!empty($row['user_from'])) ? $row['user_from'] : '',
1141
1142
                                'sig'                                        => $user_sig,
1143
                                'sig_bbcode_uid'                => (!empty($row['user_sig_bbcode_uid'])) ? $row['user_sig_bbcode_uid'] : '',
1144
                                'sig_bbcode_bitfield'        => (!empty($row['user_sig_bbcode_bitfield'])) ? $row['user_sig_bbcode_bitfield'] : '',
1145
1146
                                'viewonline'        => $row['user_allow_viewonline'],
1147
                                'allow_pm'                => $row['user_allow_pm'],
1148
1149
                                'avatar'                => ($user->optionget('viewavatars')) ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], $row['user_avatar_width'], $row['user_avatar_height']) : '',
1150
                                'age'                        => '',
1151
1152
                                'rank_title'                => '',
1153
                                'rank_image'                => '',
1154
                                'rank_image_src'        => '',
1155
1156
                                'username'                        => $row['username'],
1157
                                'user_colour'                => $row['user_colour'],
1158
1159
                                'online'                => false,
1160
                                'profile'                => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&amp;u=$poster_id"),
1161
                                'www'                        => $row['user_website'],
1162
                                'aim'                        => ($row['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&amp;action=aim&amp;u=$poster_id") : '',
1163
                                'msn'                        => ($row['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&amp;action=msnm&amp;u=$poster_id") : '',
1164
                                'yim'                        => ($row['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($row['user_yim']) . '&amp;.src=pg' : '',
1165
                                'jabber'                => ($row['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&amp;action=jabber&amp;u=$poster_id") : '',
1166
                                'search'                => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id=$poster_id&amp;sr=posts") : '',
1167
1168
                                'author_full'                => get_username_string('full', $poster_id, $row['username'], $row['user_colour']),
1169
                                'author_colour'                => get_username_string('colour', $poster_id, $row['username'], $row['user_colour']),
1170
                                'author_username'        => get_username_string('username', $poster_id, $row['username'], $row['user_colour']),
1171
                                'author_profile'        => get_username_string('profile', $poster_id, $row['username'], $row['user_colour']),
1172
                        );
1173
1174
                        get_user_rank($row['user_rank'], $row['user_posts'], $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']);
1175
1176
                        if ((!empty($row['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_email'))
1177
                        {
1178
                                $user_cache[$poster_id]['email'] = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&amp;u=$poster_id") : (($config['board_hide_emails'] && !$auth->acl_get('a_email')) ? '' : 'mailto:' . $row['user_email']);
1179
                        }
1180
                        else
1181
                        {
1182
                                $user_cache[$poster_id]['email'] = '';
1183
                        }
1184
1185
                        if (!empty($row['user_icq']))
1186
                        {
1187
                                $user_cache[$poster_id]['icq'] = 'http://www.icq.com/people/' . urlencode($row['user_icq']) . '/';
1188
                                $user_cache[$poster_id]['icq_status_img'] = '<img src="http://web.icq.com/whitepages/online?icq=' . $row['user_icq'] . '&amp;img=5" width="18" height="18" alt="" />';
1189
                        }
1190
                        else
1191
                        {
1192
                                $user_cache[$poster_id]['icq_status_img'] = '';
1193
                                $user_cache[$poster_id]['icq'] = '';
1194
                        }
1195
1196
                        if ($config['allow_birthdays'] && !empty($row['user_birthday']))
1197
                        {
1198
                                list($bday_day, $bday_month, $bday_year) = array_map('intval', explode('-', $row['user_birthday']));
1199
1200
                                if ($bday_year)
1201
                                {
1202
                                        $diff = $now['mon'] - $bday_month;
1203
                                        if ($diff == 0)
1204
                                        {
1205
                                                $diff = ($now['mday'] - $bday_day < 0) ? 1 : 0;
1206
                                        }
1207
                                        else
1208
                                        {
1209
                                                $diff = ($diff < 0) ? 1 : 0;
1210
                                        }
1211
1212
                                        $user_cache[$poster_id]['age'] = (int) ($now['year'] - $bday_year - $diff);
1213
                                }
1214
                        }
1215
                }
1216
        }
1217
}
1218
$db->sql_freeresult($result);
1219
1220
// Load custom profile fields
1221
if ($config['load_cpf_viewtopic'])
1222
{
1223
        if (!class_exists('custom_profile'))
1224
        {
1225
                include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx);
1226
        }
1227
        $cp = new custom_profile();
1228
1229
        // Grab all profile fields from users in id cache for later use - similar to the poster cache
1230
        $profile_fields_tmp = $cp->generate_profile_fields_template('grab', $id_cache);
1231
1232
        // filter out fields not to be displayed on viewtopic. Yes, it's a hack, but this shouldn't break any MODs.
1233
        $profile_fields_cache = array();
1234
        foreach ($profile_fields_tmp as $profile_user_id => $profile_fields)
1235
        {
1236
                $profile_fields_cache[$profile_user_id] = array();
1237
                foreach ($profile_fields as $used_ident => $profile_field)
1238
                {
1239
                        if ($profile_field['data']['field_show_on_vt'])
1240
                        {
1241
                                $profile_fields_cache[$profile_user_id][$used_ident] = $profile_field;
1242
                        }
1243
                }
1244
        }
1245
        unset($profile_fields_tmp);
1246
}
1247
1248
// Generate online information for user
1249
if ($config['load_onlinetrack'] && sizeof($id_cache))
1250
{
1251
        $sql = 'SELECT session_user_id, MAX(session_time) as online_time, MIN(session_viewonline) AS viewonline
1252
                FROM ' . SESSIONS_TABLE . '
1253
                WHERE ' . $db->sql_in_set('session_user_id', $id_cache) . '
1254
                GROUP BY session_user_id';
1255
        $result = $db->sql_query($sql);
1256
1257
        $update_time = $config['load_online_time'] * 60;
1258
        while ($row = $db->sql_fetchrow($result))
1259
        {
1260
                $user_cache[$row['session_user_id']]['online'] = (time() - $update_time < $row['online_time'] && (($row['viewonline']) || $auth->acl_get('u_viewonline'))) ? true : false;
1261
        }
1262
        $db->sql_freeresult($result);
1263
}
1264
unset($id_cache);
1265
1266
// Pull attachment data
1267
if (sizeof($attach_list))
1268
{
1269
        if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
1270
        {
1271
                $sql = 'SELECT *
1272
                        FROM ' . ATTACHMENTS_TABLE . '
1273
                        WHERE ' . $db->sql_in_set('post_msg_id', $attach_list) . '
1274
                                AND in_message = 0
1275
                        ORDER BY filetime DESC, post_msg_id ASC';
1276
                $result = $db->sql_query($sql);
1277
1278
                while ($row = $db->sql_fetchrow($result))
1279
                {
1280
                        $attachments[$row['post_msg_id']][] = $row;
1281
                }
1282
                $db->sql_freeresult($result);
1283
1284
                // No attachments exist, but post table thinks they do so go ahead and reset post_attach flags
1285
                if (!sizeof($attachments))
1286
                {
1287
                        $sql = 'UPDATE ' . POSTS_TABLE . '
1288
                                SET post_attachment = 0
1289
                                WHERE ' . $db->sql_in_set('post_id', $attach_list);
1290
                        $db->sql_query($sql);
1291
1292
                        // We need to update the topic indicator too if the complete topic is now without an attachment
1293
                        if (sizeof($rowset) != $total_posts)
1294
                        {
1295
                                // Not all posts are displayed so we query the db to find if there's any attachment for this topic
1296
                                $sql = 'SELECT a.post_msg_id as post_id
1297
                                        FROM ' . ATTACHMENTS_TABLE . ' a, ' . POSTS_TABLE . " p
1298
                                        WHERE p.topic_id = $topic_id
1299
                                                AND p.post_approved = 1
1300
                                                AND p.topic_id = a.topic_id";
1301
                                $result = $db->sql_query_limit($sql, 1);
1302
                                $row = $db->sql_fetchrow($result);
1303
                                $db->sql_freeresult($result);
1304
1305
                                if (!$row)
1306
                                {
1307
                                        $sql = 'UPDATE ' . TOPICS_TABLE . "
1308
                                                SET topic_attachment = 0
1309
                                                WHERE topic_id = $topic_id";
1310
                                        $db->sql_query($sql);
1311
                                }
1312
                        }
1313
                        else
1314
                        {
1315
                                $sql = 'UPDATE ' . TOPICS_TABLE . "
1316
                                        SET topic_attachment = 0
1317
                                        WHERE topic_id = $topic_id";
1318
                                $db->sql_query($sql);
1319
                        }
1320
                }
1321
                else if ($has_attachments && !$topic_data['topic_attachment'])
1322
                {
1323
                        // Topic has approved attachments but its flag is wrong
1324
                        $sql = 'UPDATE ' . TOPICS_TABLE . "
1325
                                SET topic_attachment = 1
1326
                                WHERE topic_id = $topic_id";
1327
                        $db->sql_query($sql);
1328
1329
                        $topic_data['topic_attachment'] = 1;
1330
                }
1331
        }
1332
        else
1333
        {
1334
                $display_notice = true;
1335
        }
1336
}
1337
1338
// Instantiate BBCode if need be
1339
if ($bbcode_bitfield !== '')
1340
{
1341
        $bbcode = new bbcode(base64_encode($bbcode_bitfield));
1342
}
1343
1344
$i_total = sizeof($rowset) - 1;
1345
$prev_post_id = '';
1346
1347
$template->assign_vars(array(
1348
        'S_NUM_POSTS' => sizeof($post_list))
1349
);
1350
1351
// Output the posts
1352
$first_unread = $post_unread = false;
1353
for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
1354
{
1355
        // A non-existing rowset only happens if there was no user present for the entered poster_id
1356
        // This could be a broken posts table.
1357
        if (!isset($rowset[$post_list[$i]]))
1358
        {
1359
                continue;
1360
        }
1361
1362
        $row =& $rowset[$post_list[$i]];
1363
        $poster_id = $row['user_id'];
1364
1365
        // End signature parsing, only if needed
1366
        if ($user_cache[$poster_id]['sig'] && $row['enable_sig'] && empty($user_cache[$poster_id]['sig_parsed']))
1367
        {
1368
                $user_cache[$poster_id]['sig'] = censor_text($user_cache[$poster_id]['sig']);
1369
1370
                if ($user_cache[$poster_id]['sig_bbcode_bitfield'])
1371
                {
1372
                        $bbcode->bbcode_second_pass($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$poster_id]['sig_bbcode_bitfield']);
1373
                }
1374
1375
                $user_cache[$poster_id]['sig'] = bbcode_nl2br($user_cache[$poster_id]['sig']);
1376
                $user_cache[$poster_id]['sig'] = smiley_text($user_cache[$poster_id]['sig']);
1377
                $user_cache[$poster_id]['sig_parsed'] = true;
1378
        }
1379
1380
        // Parse the message and subject
1381
        $message = censor_text($row['post_text']);
1382
1383
        // Second parse bbcode here
1384
        if ($row['bbcode_bitfield'])
1385
        {
1386
                $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
1387
        }
1388
1389
        $message = bbcode_nl2br($message);
1390
        $message = smiley_text($message);
1391
1392
        if (!empty($attachments[$row['post_id']]))
1393
        {
1394
                parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count);
1395
        }
1396
1397
        // Replace naughty words such as farty pants
1398
        $row['post_subject'] = censor_text($row['post_subject']);
1399
1400
        // Highlight active words (primarily for search)
1401
        if ($highlight_match)
1402
        {
1403
                $message = preg_replace('#(?!<.*)(?<!\w)(' . $highlight_match . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">\1</span>', $message);
1404
                $row['post_subject'] = preg_replace('#(?!<.*)(?<!\w)(' . $highlight_match . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">\1</span>', $row['post_subject']);
1405
        }
1406
1407
        // Editing information
1408
        if (($row['post_edit_count'] && $config['display_last_edited']) || $row['post_edit_reason'])
1409
        {
1410
                // Get usernames for all following posts if not already stored
1411
                if (!sizeof($post_edit_list) && ($row['post_edit_reason'] || ($row['post_edit_user'] && !isset($user_cache[$row['post_edit_user']]))))
1412
                {
1413
                        // Remove all post_ids already parsed (we do not have to check them)
1414
                        $post_storage_list = (!$store_reverse) ? array_slice($post_list, $i) : array_slice(array_reverse($post_list), $i);
1415
1416
                        $sql = 'SELECT DISTINCT u.user_id, u.username, u.user_colour
1417
                                FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
1418
                                WHERE ' . $db->sql_in_set('p.post_id', $post_storage_list) . '
1419
                                        AND p.post_edit_count <> 0
1420
                                        AND p.post_edit_user <> 0
1421
                                        AND p.post_edit_user = u.user_id';
1422
                        $result2 = $db->sql_query($sql);
1423
                        while ($user_edit_row = $db->sql_fetchrow($result2))
1424
                        {
1425
                                $post_edit_list[$user_edit_row['user_id']] = $user_edit_row;
1426
                        }
1427
                        $db->sql_freeresult($result2);
1428
1429
                        unset($post_storage_list);
1430
                }
1431
1432
                $l_edit_time_total = ($row['post_edit_count'] == 1) ? $user->lang['EDITED_TIME_TOTAL'] : $user->lang['EDITED_TIMES_TOTAL'];
1433
1434
                if ($row['post_edit_reason'])
1435
                {
1436
                        // User having edited the post also being the post author?
1437
                        if (!$row['post_edit_user'] || $row['post_edit_user'] == $poster_id)
1438
                        {
1439
                                $display_username = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
1440
                        }
1441
                        else
1442
                        {
1443
                                $display_username = get_username_string('full', $row['post_edit_user'], $post_edit_list[$row['post_edit_user']]['username'], $post_edit_list[$row['post_edit_user']]['user_colour']);
1444
                        }
1445
1446
                        $l_edited_by = sprintf($l_edit_time_total, $display_username, $user->format_date($row['post_edit_time'], false, true), $row['post_edit_count']);
1447
                }
1448
                else
1449
                {
1450
                        if ($row['post_edit_user'] && !isset($user_cache[$row['post_edit_user']]))
1451
                        {
1452
                                $user_cache[$row['post_edit_user']] = $post_edit_list[$row['post_edit_user']];
1453
                        }
1454
1455
                        // User having edited the post also being the post author?
1456
                        if (!$row['post_edit_user'] || $row['post_edit_user'] == $poster_id)
1457
                        {
1458
                                $display_username = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
1459
                        }
1460
                        else
1461
                        {
1462
                                $display_username = get_username_string('full', $row['post_edit_user'], $user_cache[$row['post_edit_user']]['username'], $user_cache[$row['post_edit_user']]['user_colour']);
1463
                        }
1464
1465
                        $l_edited_by = sprintf($l_edit_time_total, $display_username, $user->format_date($row['post_edit_time'], false, true), $row['post_edit_count']);
1466
                }
1467
        }
1468
        else
1469
        {
1470
                $l_edited_by = '';
1471
        }
1472
1473
        // Bump information
1474
        if ($topic_data['topic_bumped'] && $row['post_id'] == $topic_data['topic_last_post_id'] && isset($user_cache[$topic_data['topic_bumper']]) )
1475
        {
1476
                // It is safe to grab the username from the user cache array, we are at the last
1477
                // post and only the topic poster and last poster are allowed to bump.
1478
                // Admins and mods are bound to the above rules too...
1479
                $l_bumped_by = sprintf($user->lang['BUMPED_BY'], $user_cache[$topic_data['topic_bumper']]['username'], $user->format_date($topic_data['topic_last_post_time'], false, true));
1480
        }
1481
        else
1482
        {
1483
                $l_bumped_by = '';
1484
        }
1485
1486
        $cp_row = array();
1487
1488
        //
1489
        if ($config['load_cpf_viewtopic'])
1490
        {
1491
                $cp_row = (isset($profile_fields_cache[$poster_id])) ? $cp->generate_profile_fields_template('show', false, $profile_fields_cache[$poster_id]) : array();
1492
        }
1493
1494
        $post_unread = (isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
1495
1496
        $s_first_unread = false;
1497
        if (!$first_unread && $post_unread)
1498
        {
1499
                $s_first_unread = $first_unread = true;
1500
        }
1501
1502
        $edit_allowed = ($user->data['is_registered'] && ($auth->acl_get('m_edit', $forum_id) || (
1503
                $user->data['user_id'] == $poster_id &&
1504
                $auth->acl_get('f_edit', $forum_id) &&
1505
                !$row['post_edit_locked'] &&
1506
                ($row['post_time'] > time() - ($config['edit_time'] * 60) || !$config['edit_time'])
1507
        )));
1508
1509
        $delete_allowed = ($user->data['is_registered'] && ($auth->acl_get('m_delete', $forum_id) || (
1510
                $user->data['user_id'] == $poster_id &&
1511
                $auth->acl_get('f_delete', $forum_id) &&
1512
                $topic_data['topic_last_post_id'] == $row['post_id'] &&
1513
                ($row['post_time'] > time() - ($config['delete_time'] * 60) || !$config['delete_time']) &&
1514
                // we do not want to allow removal of the last post if a moderator locked it!
1515
                !$row['post_edit_locked']
1516
        )));
1517
1518
        //
1519
        $postrow = array(
1520
                'POST_AUTHOR_FULL'                => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_full'] : get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1521
                'POST_AUTHOR_COLOUR'        => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_colour'] : get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1522
                'POST_AUTHOR'                        => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_username'] : get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1523
                'U_POST_AUTHOR'                        => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_profile'] : get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1524
1525
                'RANK_TITLE'                => $user_cache[$poster_id]['rank_title'],
1526
                'RANK_IMG'                        => $user_cache[$poster_id]['rank_image'],
1527
                'RANK_IMG_SRC'                => $user_cache[$poster_id]['rank_image_src'],
1528
                'POSTER_JOINED'                => $user_cache[$poster_id]['joined'],
1529
                'POSTER_POSTS'                => $user_cache[$poster_id]['posts'],
1530
                'POSTER_FROM'                => $user_cache[$poster_id]['from'],
1531
                'POSTER_AVATAR'                => $user_cache[$poster_id]['avatar'],
1532
                'POSTER_WARNINGS'        => $user_cache[$poster_id]['warnings'],
1533
                'POSTER_AGE'                => $user_cache[$poster_id]['age'],
1534
1535
                'POST_DATE'                        => $user->format_date($row['post_time'], false, ($view == 'print') ? true : false),
1536
                'POST_SUBJECT'                => $row['post_subject'],
1537
                'MESSAGE'                        => $message,
1538
                'SIGNATURE'                        => ($row['enable_sig']) ? $user_cache[$poster_id]['sig'] : '',
1539
                'EDITED_MESSAGE'        => $l_edited_by,
1540
                'EDIT_REASON'                => $row['post_edit_reason'],
1541
                'BUMPED_MESSAGE'        => $l_bumped_by,
1542
1543
                'MINI_POST_IMG'                        => ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'),
1544
                'POST_ICON_IMG'                        => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['img'] : '',
1545
                'POST_ICON_IMG_WIDTH'        => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['width'] : '',
1546
                'POST_ICON_IMG_HEIGHT'        => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['height'] : '',
1547
                'ICQ_STATUS_IMG'                => $user_cache[$poster_id]['icq_status_img'],
1548
                'ONLINE_IMG'                        => ($poster_id == ANONYMOUS || !$config['load_onlinetrack']) ? '' : (($user_cache[$poster_id]['online']) ? $user->img('icon_user_online', 'ONLINE') : $user->img('icon_user_offline', 'OFFLINE')),
1549
                'S_ONLINE'                                => ($poster_id == ANONYMOUS || !$config['load_onlinetrack']) ? false : (($user_cache[$poster_id]['online']) ? true : false),
1550
1551
                'U_EDIT'                        => ($edit_allowed) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&amp;f=$forum_id&amp;p={$row['post_id']}") : '',
1552
                'U_QUOTE'                        => ($auth->acl_get('f_reply', $forum_id)) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=quote&amp;f=$forum_id&amp;p={$row['post_id']}") : '',
1553
                'U_INFO'                        => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&amp;mode=post_details&amp;f=$forum_id&amp;p=" . $row['post_id'], true, $user->session_id) : '',
1554
                'U_DELETE'                        => ($delete_allowed) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=delete&amp;f=$forum_id&amp;p={$row['post_id']}") : '',
1555
1556
                'U_PROFILE'                => $user_cache[$poster_id]['profile'],
1557
                'U_SEARCH'                => $user_cache[$poster_id]['search'],
1558
                'U_PM'                        => ($poster_id != ANONYMOUS && $config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_cache[$poster_id]['allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=compose&amp;action=quotepost&amp;p=' . $row['post_id']) : '',
1559
                'U_EMAIL'                => $user_cache[$poster_id]['email'],
1560
                'U_WWW'                        => $user_cache[$poster_id]['www'],
1561
                'U_ICQ'                        => $user_cache[$poster_id]['icq'],
1562
                'U_AIM'                        => $user_cache[$poster_id]['aim'],
1563
                'U_MSN'                        => $user_cache[$poster_id]['msn'],
1564
                'U_YIM'                        => $user_cache[$poster_id]['yim'],
1565
                'U_JABBER'                => $user_cache[$poster_id]['jabber'],
1566
1567
                'U_REPORT'                        => ($auth->acl_get('f_report', $forum_id)) ? append_sid("{$phpbb_root_path}report.$phpEx", 'f=' . $forum_id . '&amp;p=' . $row['post_id']) : '',
1568
                'U_MCP_REPORT'                => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
1569
                'U_MCP_APPROVE'                => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
1570
                'U_MINI_POST'                => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . (($topic_data['topic_type'] == POST_GLOBAL) ? '&amp;f=' . $forum_id : '') . '#p' . $row['post_id'],
1571
                'U_NEXT_POST_ID'        => ($i < $i_total && isset($rowset[$post_list[$i + 1]])) ? $rowset[$post_list[$i + 1]]['post_id'] : '',
1572
                'U_PREV_POST_ID'        => $prev_post_id,
1573
                'U_NOTES'                        => ($auth->acl_getf_global('m_')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $poster_id, true, $user->session_id) : '',
1574
                'U_WARN'                        => ($auth->acl_get('m_warn') && $poster_id != $user->data['user_id'] && $poster_id != ANONYMOUS) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_post&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
1575
1576
                'POST_ID'                        => $row['post_id'],
1577
                'POST_NUMBER'                => $i + $start + 1,
1578
                'POSTER_ID'                        => $poster_id,
1579
1580
                'S_HAS_ATTACHMENTS'        => (!empty($attachments[$row['post_id']])) ? true : false,
1581
                'S_POST_UNAPPROVED'        => ($row['post_approved']) ? false : true,
1582
                'S_POST_REPORTED'        => ($row['post_reported'] && $auth->acl_get('m_report', $forum_id)) ? true : false,
1583
                'S_DISPLAY_NOTICE'        => $display_notice && $row['post_attachment'],
1584
                'S_FRIEND'                        => ($row['friend']) ? true : false,
1585
                'S_UNREAD_POST'                => $post_unread,
1586
                'S_FIRST_UNREAD'        => $s_first_unread,
1587
                'S_CUSTOM_FIELDS'        => (isset($cp_row['row']) && sizeof($cp_row['row'])) ? true : false,
1588
                'S_TOPIC_POSTER'        => ($topic_data['topic_poster'] == $poster_id) ? true : false,
1589
1590
                'S_IGNORE_POST'                => ($row['hide_post']) ? true : false,
1591
                'L_IGNORE_POST'                => ($row['hide_post']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), '<a href="' . $viewtopic_url . "&amp;p={$row['post_id']}&amp;view=show#p{$row['post_id']}" . '">', '</a>') : '',
1592
        );
1593
1594
        if (isset($cp_row['row']) && sizeof($cp_row['row']))
1595
        {
1596
                $postrow = array_merge($postrow, $cp_row['row']);
1597
        }
1598
1599
        // Dump vars into template
1600
        $template->assign_block_vars('postrow', $postrow);
1601
1602
        if (!empty($cp_row['blockrow']))
1603
        {
1604
                foreach ($cp_row['blockrow'] as $field_data)
1605
                {
1606
                        $template->assign_block_vars('postrow.custom_fields', $field_data);
1607
                }
1608
        }
1609
1610
        // Display not already displayed Attachments for this post, we already parsed them. ;)
1611
        if (!empty($attachments[$row['post_id']]))
1612
        {
1613
                foreach ($attachments[$row['post_id']] as $attachment)
1614
                {
1615
                        $template->assign_block_vars('postrow.attachment', array(
1616
                                'DISPLAY_ATTACHMENT'        => $attachment)
1617
                        );
1618
                }
1619
        }
1620
1621
        $prev_post_id = $row['post_id'];
1622
1623
        unset($rowset[$post_list[$i]]);
1624
        unset($attachments[$row['post_id']]);
1625
}
1626
unset($rowset, $user_cache);
1627
1628
// Update topic view and if necessary attachment view counters ... but only for humans and if this is the first 'page view'
1629
if (isset($user->data['session_page']) && !$user->data['is_bot'] && (strpos($user->data['session_page'], '&t=' . $topic_id) === false || isset($user->data['session_created'])))
1630
{
1631
        $sql = 'UPDATE ' . TOPICS_TABLE . '
1632
                SET topic_views = topic_views + 1, topic_last_view_time = ' . time() . "
1633
                WHERE topic_id = $topic_id";
1634
        $db->sql_query($sql);
1635
1636
        // Update the attachment download counts
1637
        if (sizeof($update_count))
1638
        {
1639
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
1640
                        SET download_count = download_count + 1
1641
                        WHERE ' . $db->sql_in_set('attach_id', array_unique($update_count));
1642
                $db->sql_query($sql);
1643
        }
1644
}
1645
1646
// Get last post time for all global announcements
1647
// to keep proper forums tracking
1648
if ($topic_data['topic_type'] == POST_GLOBAL)
1649
{
1650
        $sql = 'SELECT topic_last_post_time as forum_last_post_time
1651
                FROM ' . TOPICS_TABLE . '
1652
                WHERE forum_id = 0
1653
                ORDER BY topic_last_post_time DESC';
1654
        $result = $db->sql_query_limit($sql, 1);
1655
        $topic_data['forum_last_post_time'] = (int) $db->sql_fetchfield('forum_last_post_time');
1656
        $db->sql_freeresult($result);
1657
1658
        $sql = 'SELECT mark_time as forum_mark_time
1659
                FROM ' . FORUMS_TRACK_TABLE . '
1660
                WHERE forum_id = 0
1661
                        AND user_id = ' . $user->data['user_id'];
1662
        $result = $db->sql_query($sql);
1663
        $topic_data['forum_mark_time'] = (int) $db->sql_fetchfield('forum_mark_time');
1664
        $db->sql_freeresult($result);
1665
}
1666
1667
// Only mark topic if it's currently unread. Also make sure we do not set topic tracking back if earlier pages are viewed.
1668
if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id] && $max_post_time > $topic_tracking_info[$topic_id])
1669
{
1670
        markread('topic', (($topic_data['topic_type'] == POST_GLOBAL) ? 0 : $forum_id), $topic_id, $max_post_time);
1671
1672
        // Update forum info
1673
        $all_marked_read = update_forum_tracking_info((($topic_data['topic_type'] == POST_GLOBAL) ? 0 : $forum_id), $topic_data['forum_last_post_time'], (isset($topic_data['forum_mark_time'])) ? $topic_data['forum_mark_time'] : false, false);
1674
}
1675
else
1676
{
1677
        $all_marked_read = true;
1678
}
1679
1680
// If there are absolutely no more unread posts in this forum and unread posts shown, we can savely show the #unread link
1681
if ($all_marked_read)
1682
{
1683
        if ($post_unread)
1684
        {
1685
                $template->assign_vars(array(
1686
                        'U_VIEW_UNREAD_POST'        => '#unread',
1687
                ));
1688
        }
1689
        else if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id])
1690
        {
1691
                $template->assign_vars(array(
1692
                        'U_VIEW_UNREAD_POST'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=unread") . '#unread',
1693
                ));
1694
        }
1695
}
1696
else if (!$all_marked_read)
1697
{
1698
        $last_page = ((floor($start / $config['posts_per_page']) + 1) == max(ceil($total_posts / $config['posts_per_page']), 1)) ? true : false;
1699
1700
        // What can happen is that we are at the last displayed page. If so, we also display the #unread link based in $post_unread
1701
        if ($last_page && $post_unread)
1702
        {
1703
                $template->assign_vars(array(
1704
                        'U_VIEW_UNREAD_POST'        => '#unread',
1705
                ));
1706
        }
1707
        else if (!$last_page)
1708
        {
1709
                $template->assign_vars(array(
1710
                        'U_VIEW_UNREAD_POST'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=unread") . '#unread',
1711
                ));
1712
        }
1713
}
1714
1715
// let's set up quick_reply
1716
$s_quick_reply = false;
1717
if ($user->data['is_registered'] && $config['allow_quick_reply'] && ($topic_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) && $auth->acl_get('f_reply', $forum_id))
1718
{
1719
        // Quick reply enabled forum
1720
        $s_quick_reply = (($topic_data['forum_status'] == ITEM_UNLOCKED && $topic_data['topic_status'] == ITEM_UNLOCKED) || $auth->acl_get('m_edit', $forum_id)) ? true : false;
1721
}
1722
1723
if ($s_can_vote || $s_quick_reply)
1724
{
1725
        add_form_key('posting');
1726
1727
        if ($s_quick_reply)
1728
        {
1729
                $s_attach_sig        = $config['allow_sig'] && $user->optionget('attachsig') && $auth->acl_get('f_sigs', $forum_id) && $auth->acl_get('u_sig');
1730
                $s_smilies                = $config['allow_smilies'] && $user->optionget('smilies') && $auth->acl_get('f_smilies', $forum_id);
1731
                $s_bbcode                = $config['allow_bbcode'] && $user->optionget('bbcode') && $auth->acl_get('f_bbcode', $forum_id);
1732
                $s_notify                = $config['allow_topic_notify'] && ($user->data['user_notify'] || $s_watching_topic['is_watching']);
1733
1734
                $qr_hidden_fields = array(
1735
                        'topic_cur_post_id'                => (int) $topic_data['topic_last_post_id'],
1736
                        'lastclick'                                => (int) time(),
1737
                        'topic_id'                                => (int) $topic_data['topic_id'],
1738
                        'forum_id'                                => (int) $forum_id,
1739
                );
1740
1741
                // Originally we use checkboxes and check with isset(), so we only provide them if they would be checked
1742
                (!$s_bbcode)                                        ? $qr_hidden_fields['disable_bbcode'] = 1                : true;
1743
                (!$s_smilies)                                        ? $qr_hidden_fields['disable_smilies'] = 1                : true;
1744
                (!$config['allow_post_links'])        ? $qr_hidden_fields['disable_magic_url'] = 1        : true;
1745
                ($s_attach_sig)                                        ? $qr_hidden_fields['attach_sig'] = 1                        : true;
1746
                ($s_notify)                                                ? $qr_hidden_fields['notify'] = 1                                : true;
1747
                ($topic_data['topic_status'] == ITEM_LOCKED) ? $qr_hidden_fields['lock_topic'] = 1 : true;
1748
1749
                $template->assign_vars(array(
1750
                        'S_QUICK_REPLY'                        => true,
1751
                        'U_QR_ACTION'                        => append_sid("{$phpbb_root_path}posting.$phpEx", "mode=reply&amp;f=$forum_id&amp;t=$topic_id"),
1752
                        'QR_HIDDEN_FIELDS'                => build_hidden_fields($qr_hidden_fields),
1753
                        'SUBJECT'                                => 'Re: ' . censor_text($topic_data['topic_title']),
1754
                ));
1755
        }
1756
}
1757
// now I have the urge to wash my hands :(
1758
1759
1760
// We overwrite $_REQUEST['f'] if there is no forum specified
1761
// to be able to display the correct online list.
1762
// One downside is that the user currently viewing this topic/post is not taken into account.
1763
if (empty($_REQUEST['f']))
1764
{
1765
        $_REQUEST['f'] = $forum_id;
1766
}
1767
1768
// We need to do the same with the topic_id. See #53025.
1769
if (empty($_REQUEST['t']) && !empty($topic_id))
1770
{
1771
        $_REQUEST['t'] = $topic_id;
1772
}
1773
1774
// Output the page
1775
page_header($user->lang['VIEW_TOPIC'] . ' - ' . $topic_data['topic_title'], true, $forum_id);
1776
1777
$template->set_filenames(array(
1778
        'body' => ($view == 'print') ? 'viewtopic_print.html' : 'viewtopic_body.html')
1779
);
1780
make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"), $forum_id);
1781
1782
page_footer();
1783
1784
?>