source: trunk/smf/SSI.php @ 1184

Revision 1154, 73.1 KB checked in by bogdan2412, 6 months ago (diff)

Updated SMF to latest version 1.1.15.

Been running on live for the past three weeks with no new bug reports.

  • Property svn:eol-style set to native
Line 
1<?php
2/**********************************************************************************
3* SSI.php                                                                         *
4***********************************************************************************
5* SMF: Simple Machines Forum                                                      *
6* Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com)                    *
7* =============================================================================== *
8* Software Version:           SMF 1.1.13                                          *
9* Software by:                Simple Machines (http://www.simplemachines.org)     *
10* Copyright 2006 by:          Simple Machines LLC (http://www.simplemachines.org) *
11*           2001-2006 by:     Lewis Media (http://www.lewismedia.com)             *
12* Support, News, Updates at:  http://www.simplemachines.org                       *
13***********************************************************************************
14* This program is free software; you may redistribute it and/or modify it under   *
15* the terms of the provided license as published by Simple Machines LLC.          *
16*                                                                                 *
17* This program is distributed in the hope that it is and will be useful, but      *
18* WITHOUT ANY WARRANTIES; without even any implied warranty of MERCHANTABILITY    *
19* or FITNESS FOR A PARTICULAR PURPOSE.                                            *
20*                                                                                 *
21* See the "license.txt" file for details of the Simple Machines license.          *
22* The latest version can always be found at http://www.simplemachines.org.        *
23**********************************************************************************/
24
25
26// Don't do anything if SMF is already loaded.
27if (defined('SMF'))
28        return true;
29
30define('SMF', 'SSI');
31
32// We're going to want a few globals... these are all set later.
33global $time_start, $maintenance, $msubject, $mmessage, $mbname, $language;
34global $boardurl, $boarddir, $sourcedir, $webmaster_email, $cookiename;
35global $db_server, $db_name, $db_user, $db_prefix, $db_persist, $db_error_send, $db_last_error;
36global $db_connection, $modSettings, $context, $sc, $user_info, $topic, $board, $txt;
37
38// Remember the current configuration so it can be set back.
39$ssi_magic_quotes_runtime = @get_magic_quotes_runtime();
40@set_magic_quotes_runtime(0);
41$time_start = microtime();
42
43// Make sure some things simply do not exist.
44foreach (array('db_character_set') as $variable)
45        if (isset($GLOBALS[$variable]))
46                unset($GLOBALS[$variable]);
47
48// Get the forum's settings for database and file paths.
49require_once(dirname(__FILE__) . '/Settings.php');
50
51$ssi_error_reporting = error_reporting(E_ALL);
52ini_set('display_errors', false);
53
54// Don't do john didley if the forum's been shut down competely.
55if ($maintenance == 2 && (!isset($ssi_maintenance_off) || $ssi_maintenance_off !== true))
56        die($mmessage);
57
58// Fix for using the current directory as a path.
59if (substr($sourcedir, 0, 1) == '.' && substr($sourcedir, 1, 1) != '.')
60        $sourcedir = dirname(__FILE__) . substr($sourcedir, 1);
61
62// Load the important includes.
63require_once($sourcedir . '/QueryString.php');
64require_once($sourcedir . '/Subs.php');
65require_once($sourcedir . '/Errors.php');
66
67// infoarena integration (must stay here)
68require_once(dirname(__FILE__) . '/infoarena.php');
69
70require_once($sourcedir . '/Load.php');
71require_once($sourcedir . '/Security.php');
72
73if (@version_compare(PHP_VERSION, '4.2.3') != 1)
74        require_once($sourcedir . '/Subs-Compat.php');
75
76// Connect to the MySQL database.
77if (empty($db_persist))
78        $db_connection = @mysql_connect($db_server, $db_user, $db_passwd);
79else
80        $db_connection = @mysql_pconnect($db_server, $db_user, $db_passwd);
81if ($db_connection === false)
82        return false;
83
84// Add the database onto the prefix to avoid conflicts with other scripts.
85if (strpos($db_prefix, '.') === false) {
86        $db_prefix = is_numeric(substr($db_prefix, 0, 1)) ? $db_name . '.' . $db_prefix : '`' . $db_name . '`.' . $db_prefix;
87}
88@mysql_select_db($db_name, $db_connection);
89
90// restore infoarena session (if such a session exists)
91identity_restore();
92
93// Load installed 'Mods' settings.
94reloadSettings();
95// Clean the request variables.
96cleanRequest();
97
98// Seed the random generator?
99if (empty($modSettings['rand_seed']) || mt_rand(1, 250) == 69)
100        smf_seed_generator();
101
102// Check on any hacking attempts.
103if (isset($_REQUEST['GLOBALS']) || isset($_COOKIE['GLOBALS']))
104        die('Hacking attempt...');
105elseif (isset($_REQUEST['ssi_theme']) && (int) $_REQUEST['ssi_theme'] == (int) $ssi_theme)
106        die('Hacking attempt...');
107elseif (isset($_COOKIE['ssi_theme']) && (int) $_COOKIE['ssi_theme'] == (int) $ssi_theme)
108        die('Hacking attempt...');
109elseif (isset($_REQUEST['ssi_layers'], $ssi_layers) && (@get_magic_quotes_gpc() ? stripslashes($_REQUEST['ssi_layers']) : $_REQUEST['ssi_layers']) == $ssi_layers)
110        die('Hacking attempt...');
111if (isset($_REQUEST['context']))
112        die('Hacking attempt...');
113
114// Make sure wireless is always off.
115define('WIRELESS', false);
116
117// Gzip output? (because it must be boolean and true, this can't be hacked.)
118if (isset($ssi_gzip) && $ssi_gzip === true && @ini_get('zlib.output_compression') != '1' && @ini_get('output_handler') != 'ob_gzhandler' && @version_compare(PHP_VERSION, '4.2.0') != -1)
119        ob_start('ob_gzhandler');
120else
121        $modSettings['enableCompressedOutput'] = '0';
122
123// Primarily, this is to fix the URLs...
124ob_start('ob_sessrewrite');
125
126// Start the session... known to scramble SSI includes in cases...
127if (!headers_sent())
128        loadSession();
129else
130{
131        if (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()]))
132        {
133                // Make a stab at it, but ignore the E_WARNINGs generted because we can't send headers.
134                $temp = error_reporting(error_reporting() & !E_WARNING);
135                loadSession();
136                error_reporting($temp);
137        }
138
139        if (!isset($_SESSION['rand_code']))
140                $_SESSION['rand_code'] = '';
141        $sc = &$_SESSION['rand_code'];
142}
143
144// Get rid of $board and $topic... do stuff loadBoard would do.
145unset($board);
146unset($topic);
147$user_info['is_mod'] = false;
148$context['user']['is_mod'] = false;
149$context['linktree'] = array();
150
151// Load the user and their cookie, as well as their settings.
152loadUserSettings();
153// Load the current or SSI theme. (just ues $ssi_theme = ID_THEME;)
154loadTheme(isset($ssi_theme) ? (int) $ssi_theme : 0);
155
156// Take care of any banning that needs to be done.
157if (isset($_REQUEST['ssi_ban']) || (isset($ssi_ban) && $ssi_ban === true))
158        is_not_banned();
159
160// Load the current user's permissions....
161loadPermissions();
162
163// Do we allow guests in here?
164if (empty($ssi_guest_access) && empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && basename($_SERVER['PHP_SELF']) != 'SSI.php')
165{
166        require_once($sourcedir . '/Subs-Auth.php');
167        KickGuest();
168        obExit(null, true);
169}
170
171// Load the stuff like the menu bar, etc.
172if (isset($ssi_layers))
173{
174        $context['template_layers'] = $ssi_layers;
175        template_header();
176}
177else
178        setupThemeContext();
179
180// Make sure they didn't muss around with the settings... but only if it's not cli.
181if (isset($_SERVER['REMOTE_ADDR']) && !isset($_SERVER['is_cli']) && session_id() == '')
182        trigger_error($txt['ssi_session_broken'], E_USER_NOTICE);
183
184// Without visiting the forum this session variable might not be set on submit.
185if (!isset($_SESSION['USER_AGENT']) && (!isset($_GET['ssi_function']) || $_GET['ssi_function'] !== 'pollVote'))
186        $_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
187
188// Call a function passed by GET.
189if (isset($_GET['ssi_function']) && function_exists('ssi_' . $_GET['ssi_function']) && (!empty($modSettings['allow_guestAccess']) || !$user_info['is_guest']))
190{
191        call_user_func('ssi_' . $_GET['ssi_function']);
192        exit;
193}
194if (isset($_GET['ssi_function']))
195        exit;
196// You shouldn't just access SSI.php directly by URL!!
197elseif (basename($_SERVER['PHP_SELF']) == 'SSI.php')
198        die(sprintf($txt['ssi_not_direct'], $user_info['is_admin'] ? '\'' . addslashes(__FILE__) . '\'' : '\'SSI.php\''));
199
200error_reporting($ssi_error_reporting);
201@set_magic_quotes_runtime($ssi_magic_quotes_runtime);
202
203return true;
204
205// This shuts down the SSI and shows the footer.
206function ssi_shutdown()
207{
208        if (!isset($_GET['ssi_function']) || $_GET['ssi_function'] != 'shutdown')
209                template_footer();
210}
211
212// Display a welcome message, like:  Hey, User, you have 0 messages, 0 are new.
213function ssi_welcome($output_method = 'echo')
214{
215        global $context, $txt, $scripturl;
216
217        if ($output_method == 'echo')
218        {
219                if ($context['user']['is_guest'])
220                        echo $txt['welcome_guest'];
221                else
222                        echo $txt['hello_member'], ' <b>', $context['user']['name'], '</b>', allowedTo('pm_read') ? ', ' . $txt[152] . ' <a href="' . $scripturl . '?action=pm">' . $context['user']['messages'] . ' ' . ($context['user']['messages'] == '1' ? $txt[471] : $txt[153]) . '</a>' . $txt['newmessages4'] . ' ' . $context['user']['unread_messages'] . ' ' . ($context['user']['unread_messages'] == '1' ? $txt['newmessages0'] : $txt['newmessages1']) : '', '.';
223        }
224        // Don't echo... then do what?!
225        else
226                return $context['user'];
227}
228
229// Display a menu bar, like is displayed at the top of the forum.
230function ssi_menubar($output_method = 'echo')
231{
232        global $context;
233
234        if ($output_method == 'echo')
235                template_menu();
236        // What else could this do?
237        else
238                return $context;
239}
240
241// Show a logout link.
242function ssi_logout($redirect_to = '', $output_method = 'echo')
243{
244        global $context, $txt, $scripturl, $sc;
245
246        if ($redirect_to != '')
247                $_SESSION['logout_url'] = $redirect_to;
248
249        // Guests can't log out.
250        if ($context['user']['is_guest'])
251                return false;
252
253        echo '<a href="', $scripturl, '?action=logout;sesc=', $sc, '">', $txt[108], '</a>';
254}
255
256function ssi_displayPaging($count_comm, $begin_comm, $max_comm, $display)
257{
258    if($count_comm > $max_comm) {
259        echo '<b>Mergi la pagina:</b> ';
260        for ($i = 1; $i <= $count_comm; $i += $max_comm) {
261            if ($i != $begin_comm) {
262                echo '<a href="javascript:stay()" onclick="RemoteBox_Comments('. $i .', '. $max_comm .', true, \''. $display .'\');">
263                    ['. (int)(($i + $max_comm - 1) / $max_comm) . ']</a> ';
264            } else {
265                echo '<b>[' . (int)(($i + $max_comm - 1)/ $max_comm) . ']</b> ';
266            }
267        }
268    }
269}
270
271// Display an entire SMF topic as a comment thread.
272function ssi_commentThread($topicID, $display, $begin_comm, $max_comm = 10, $output_method = 'echo')
273{
274    global $context, $settings, $scripturl, $txt, $db_prefix, $ID_MEMBER;
275    global $user_info, $modSettings, $func;
276
277    // Get the number of comments
278    $request = db_query("SELECT numReplies FROM ia_smf_topics WHERE ID_TOPIC = " . db_escape($topicID));
279    $row = mysql_fetch_assoc($request);
280    $count_comm = (int)$row['numReplies'];
281    mysql_free_result($request);
282
283    // Get $max_comm posts, starting with $begin_comm. Newer ones will have higher IDs.
284    // Do this only if there is a 'show' request.
285    $posts = array();
286
287    if($display == 'show') {
288        $request = db_query("
289            SELECT
290                m.posterTime, m.subject, m.ID_TOPIC, m.ID_MEMBER, m.ID_MSG, m.ID_BOARD, b.name AS bName,
291                ia_user.username, ia_user.full_name, ia_user.rating_cache,
292                IFNULL(mem.realName, m.posterName) AS posterName, " . ($user_info['is_guest'] ? '1 AS isRead, 0 AS new_from' : '
293                IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, 0)) >= m.ID_MSG_MODIFIED AS isRead,
294                IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, -1)) + 1 AS new_from') . ", LEFT(m.body, 666013) AS body, m.smileysEnabled
295            FROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)
296                LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
297                LEFT JOIN ia_user ON (mem.memberName = ia_user.username)" . (!$user_info['is_guest'] ? "
298                LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = m.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
299                LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = m.ID_BOARD AND lmr.ID_MEMBER = $ID_MEMBER)" : '') . "
300            WHERE
301                m.ID_TOPIC = '" . mysql_escape_string($topicID) . "'
302                AND b.ID_BOARD = m.ID_BOARD" . (empty($exclude_boards) ? '' : "
303                AND b.ID_BOARD NOT IN (" . implode(', ', $exclude_boards) . ")") . "
304                AND $user_info[query_see_board]
305            ORDER BY m.ID_MSG
306            LIMIT " . db_quote($begin_comm) . ", " . db_quote($max_comm), __FILE__, __LINE__);
307        while ($row = mysql_fetch_assoc($request))
308        {
309            $row['body'] = parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']);
310
311            // Censor it!
312            censorText($row['subject']);
313            censorText($row['body']);
314
315            // Build the array.
316            $posts[] = array(
317                'board' => array(
318                    'id' => $row['ID_BOARD'],
319                    'name' => $row['bName'],
320                    'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
321                    'link' => '<a href="' . $scripturl . '?board=' . $row['ID_BOARD'] . '.0">' . $row['bName'] . '</a>'
322                ),
323                'topic' => $row['ID_TOPIC'],
324                'poster' => array(
325                    'id' => $row['ID_MEMBER'],
326                    'name' => $row['posterName'],
327                    'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
328                    'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>',
329                    'badge' => empty($row['ID_MEMBER']) ? $row['posterName'] : format_user_tiny($row['username'], $row['full_name'], $row['rating_cache']),
330                ),
331                'subject' => $row['subject'],
332                'short_subject' => shorten_subject($row['subject'], 25),
333                'preview' => $row['body'],
334                'time' => timeformat($row['posterTime']),
335                'timestamp' => forum_time(true, $row['posterTime']),
336                'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . ';topicseen#new',
337                'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . '#msg' . $row['ID_MSG'] . '">' . $row['subject'] . '</a>',
338                'new' => !empty($row['isRead']),
339                'new_from' => $row['new_from'],
340            );
341        }
342        mysql_free_result($request);
343    }
344
345    // Just return it.
346    if ($output_method != 'echo')
347        return $posts;
348
349    echo '
350        <div class="comments">';
351
352    $remotebox_display = ($display == 'show' ? 'hide' : 'show');
353    echo '
354        <a href="javascript:stay()" onclick="RemoteBox_Comments('. $begin_comm .', '. $max_comm .', false, \''. $remotebox_display .'\');"><h3>&#187; ';
355
356    if (0 == $count_comm){
357        echo 'Niciun comentariu inca...';
358    }
359    elseif (1 == $count_comm) {
360        echo 'Un comentariu';
361    }
362    else {
363        echo $count_comm, ' comentarii';
364    }
365
366    echo '</h3></a>';
367
368    if($display == 'show') {
369
370        // Front paging display
371        ssi_displayPaging($count_comm, $begin_comm, $max_comm, $display);
372
373        foreach ($posts as $post)
374            echo '
375                <div class="comment">
376                    <div class="header">
377                        <span class="timestamp">
378                            ', $post['time'], '
379                            ', $post['new'] ? '' : '<a href="' . $scripturl . '?topic=' . $post['topic'] . '.msg' . $post['new_from'] . ';topicseen#new"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>', '
380                        </span>
381                        ', $post['poster']['badge'], '
382                    </div>
383                    <div class="body">
384                        ', $post['preview'], '
385                    </div>
386                </div>';
387
388        // Back paging display
389        echo '<br>';
390        ssi_displayPaging($count_comm, $begin_comm, $max_comm, $display);
391    }
392
393    $new_post_url = $scripturl.'?action=post;topic='.$topicID;
394    if (0 == $count_comm) {
395        $new_post_caption = 'Fii primul care comenteaza!';
396    }
397    else {
398        echo '
399            <h3>Comenteaza si tu!</h3>';
400        $new_post_caption = 'Lasa un comentariu!';
401    }
402
403    echo '
404            <div class="toolbar">
405                <a href="', htmlentities($new_post_url), '">',
406                    htmlentities($new_post_caption),
407                '</a> Vrem sa aflam ce crezi!
408            </div>';
409
410    echo '
411        </div>';
412}
413
414//////
415// added by svalentin
416
417// Recent post list:   Subject by Poster        Date    Post preview
418function ssi_recentPostsFromTopic($topicID, $num_recent = 8, $exclude_boards = null, $output_method = 'echo')
419{
420        global $context, $settings, $scripturl, $txt, $db_prefix, $ID_MEMBER;
421        global $user_info, $modSettings, $func;
422
423        if ($exclude_boards === null && !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0)
424                $exclude_boards = array($modSettings['recycle_board']);
425        else
426                $exclude_boards = empty($exclude_boards) ? array() : $exclude_boards;
427
428        // Find all the posts.  Newer ones will have higher IDs.
429        $request = db_query("
430                SELECT
431                        m.posterTime, m.subject, m.ID_TOPIC, m.ID_MEMBER, m.ID_MSG, m.ID_BOARD, b.name AS bName,
432                        IFNULL(mem.realName, m.posterName) AS posterName, " . ($user_info['is_guest'] ? '1 AS isRead, 0 AS new_from' : '
433                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, 0)) >= m.ID_MSG_MODIFIED AS isRead,
434                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, -1)) + 1 AS new_from') . ", LEFT(m.body, 384) AS body, m.smileysEnabled
435                FROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)
436                        LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)" . (!$user_info['is_guest'] ? "
437                        LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = m.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
438                        LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = m.ID_BOARD AND lmr.ID_MEMBER = $ID_MEMBER)" : '') . "
439                WHERE
440                        m.ID_TOPIC = '" . mysql_escape_string($topicID) . "'
441                        AND b.ID_BOARD = m.ID_BOARD" . (empty($exclude_boards) ? '' : "
442                        AND b.ID_BOARD NOT IN (" . implode(', ', $exclude_boards) . ")") . "
443                        AND $user_info[query_see_board]
444                ORDER BY m.ID_MSG DESC
445                LIMIT $num_recent", __FILE__, __LINE__);
446        $posts = array();
447        while ($row = mysql_fetch_assoc($request))
448        {
449                $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']), array('<br />' => '&#10;')));
450                if ($func['strlen']($row['body']) > 128)
451                        $row['body'] = $func['substr']($row['body'], 0, 128) . '...';
452
453                // Censor it!
454                censorText($row['subject']);
455                censorText($row['body']);
456
457                // Build the array.
458                $posts[] = array(
459                        'board' => array(
460                                'id' => $row['ID_BOARD'],
461                                'name' => $row['bName'],
462                                'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
463                                'link' => '<a href="' . $scripturl . '?board=' . $row['ID_BOARD'] . '.0">' . $row['bName'] . '</a>'
464                        ),
465                        'topic' => $row['ID_TOPIC'],
466                        'poster' => array(
467                                'id' => $row['ID_MEMBER'],
468                                'name' => $row['posterName'],
469                                'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
470                                'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>'
471                        ),
472                        'subject' => $row['subject'],
473                        'short_subject' => shorten_subject($row['subject'], 25),
474                        'preview' => $row['body'],
475                        'time' => timeformat($row['posterTime']),
476                        'timestamp' => forum_time(true, $row['posterTime']),
477                        'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . ';topicseen#new',
478                        'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . '#msg' . $row['ID_MSG'] . '">' . $row['subject'] . '</a>',
479                        'new' => !empty($row['isRead']),
480                        'new_from' => $row['new_from'],
481                );
482        }
483        mysql_free_result($request);
484
485        // Just return it.
486        if ($output_method != 'echo' || empty($posts))
487                return $posts;
488
489        echo '
490                <table border="0" class="ssi_table">';
491        foreach ($posts as $post)
492                echo '
493                        <tr>
494                                <td valign="top">
495                                        <a href="', $post['href'], '">', $post['subject'], '</a>
496                                        ', $txt[525], ' ', $post['poster']['link'], '
497                                        ', $post['new'] ? '' : '<a href="' . $scripturl . '?topic=' . $post['topic'] . '.msg' . $post['new_from'] . ';topicseen#new"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>', '
498                                </td>
499                                <td align="right" nowrap="nowrap">
500                                        ', $post['time'], '
501                                </td>
502                                <td>
503                                        ', $post['preview'], '
504                                </td>
505                        </tr>';
506        echo '
507                </table>';
508}
509
510function ssi_recentTopicsFromBoard($boardID, $num_recent = 8, $exclude_boards = null, $output_method = 'echo')
511{
512        global $context, $settings, $scripturl, $txt, $db_prefix, $ID_MEMBER;
513        global $user_info, $modSettings, $func;
514
515        if ($exclude_boards === null && !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0)
516                $exclude_boards = array($modSettings['recycle_board']);
517        else
518                $exclude_boards = empty($exclude_boards) ? array() : $exclude_boards;
519
520        $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless');
521        $icon_sources = array();
522        foreach ($stable_icons as $icon)
523                $icon_sources[$icon] = 'images_url';
524
525        // Find all the posts in distinct topics.  Newer ones will have higher IDs.
526        $request = db_query("
527                SELECT
528                        m.posterTime, ms.subject, m.ID_TOPIC, m.ID_MEMBER, m.ID_MSG, b.ID_BOARD, b.name AS bName,
529                        IFNULL(mem.realName, m.posterName) AS posterName, " . ($user_info['is_guest'] ? '1 AS isRead, 0 AS new_from' : '
530                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, 0)) >= m.ID_MSG_MODIFIED AS isRead,
531                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, -1)) + 1 AS new_from') . ", LEFT(m.body, 384) AS body, m.smileysEnabled, m.icon
532                FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t, {$db_prefix}boards AS b, {$db_prefix}messages AS ms)
533                        LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)" . (!$user_info['is_guest'] ? "
534                        LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = t.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
535                        LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = b.ID_BOARD AND lmr.ID_MEMBER = $ID_MEMBER)" : '') . "
536                WHERE t.ID_LAST_MSG >= " . ($modSettings['maxMsgID'] - 35 * min($num_recent, 5)) . "
537                        AND t.ID_BOARD = " . $boardID . "
538                        AND t.ID_LAST_MSG = m.ID_MSG
539                        AND b.ID_BOARD = t.ID_BOARD" . (empty($exclude_boards) ? '' : "
540                        AND b.ID_BOARD NOT IN (" . implode(', ', $exclude_boards) . ")") . "
541                        AND $user_info[query_see_board]
542                        AND ms.ID_MSG = t.ID_FIRST_MSG
543                ORDER BY t.ID_LAST_MSG DESC
544                LIMIT $num_recent", __FILE__, __LINE__);
545        $posts = array();
546        while ($row = mysql_fetch_assoc($request))
547        {
548                $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']), array('<br />' => '&#10;')));
549                if ($func['strlen']($row['body']) > 128)
550                        $row['body'] = $func['substr']($row['body'], 0, 128) . '...';
551
552                // Censor the subject.
553                censorText($row['subject']);
554                censorText($row['body']);
555
556                if (empty($modSettings['messageIconChecks_disable']) && !isset($icon_sources[$row['icon']]))
557                        $icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.gif') ? 'images_url' : 'default_images_url';
558
559                // Build the array.
560                $posts[] = array(
561                        'board' => array(
562                                'id' => $row['ID_BOARD'],
563                                'name' => $row['bName'],
564                                'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
565                                'link' => '<a href="' . $scripturl . '?board=' . $row['ID_BOARD'] . '.0">' . $row['bName'] . '</a>'
566                        ),
567                        'topic' => $row['ID_TOPIC'],
568                        'poster' => array(
569                                'id' => $row['ID_MEMBER'],
570                                'name' => $row['posterName'],
571                                'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
572                                'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>'
573                        ),
574                        'subject' => $row['subject'],
575                        'short_subject' => shorten_subject($row['subject'], 25),
576                        'preview' => $row['body'],
577                        'time' => timeformat($row['posterTime']),
578                        'timestamp' => forum_time(true, $row['posterTime']),
579                        'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . ';topicseen#new',
580                        'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . '#new">' . $row['subject'] . '</a>',
581                        'new' => !empty($row['isRead']),
582                        'new_from' => $row['new_from'],
583                        'icon' => '<img src="' . $settings[$icon_sources[$row['icon']]] . '/post/' . $row['icon'] . '.gif" align="middle" alt="' . $row['icon'] . '" border="0" />',
584                );
585        }
586        mysql_free_result($request);
587
588        // Just return it.
589        if ($output_method != 'echo' || empty($posts))
590                return $posts;
591
592        echo '
593                <table border="0" class="ssi_table">';
594        foreach ($posts as $post)
595                echo '
596                        <tr>
597                                <td align="right" valign="top" nowrap="nowrap">
598                                        [', $post['board']['link'], ']
599                                </td>
600                                <td valign="top">
601                                        <a href="', $post['href'], '">', $post['subject'], '</a>
602                                        ', $txt[525], ' ', $post['poster']['link'], '
603                                        ', $post['new'] ? '' : '<a href="' . $scripturl . '?topic=' . $post['topic'] . '.msg' . $post['new_from'] . ';topicseen#new"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>', '
604                                </td>
605                                <td align="right" nowrap="nowrap">
606                                        ', $post['time'], '
607                                </td>
608                        </tr>';
609        echo '
610                </table>';
611}
612
613//
614//////
615
616
617// Recent post list:   [board] Subject by Poster        Date
618function ssi_recentPosts($num_recent = 8, $exclude_boards = null, $output_method = 'echo')
619{
620        global $context, $settings, $scripturl, $txt, $db_prefix, $ID_MEMBER;
621        global $user_info, $modSettings, $func;
622
623        if ($exclude_boards === null && !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0)
624                $exclude_boards = array($modSettings['recycle_board']);
625        else
626                $exclude_boards = empty($exclude_boards) ? array() : $exclude_boards;
627
628        // Find all the posts.  Newer ones will have higher IDs.
629        $request = db_query("
630                SELECT
631                        m.posterTime, m.subject, m.ID_TOPIC, m.ID_MEMBER, m.ID_MSG, m.ID_BOARD, b.name AS bName,
632                        IFNULL(mem.realName, m.posterName) AS posterName, " . ($user_info['is_guest'] ? '1 AS isRead, 0 AS new_from' : '
633                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, 0)) >= m.ID_MSG_MODIFIED AS isRead,
634                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, -1)) + 1 AS new_from') . ", LEFT(m.body, 384) AS body, m.smileysEnabled
635                FROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)
636                        LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)" . (!$user_info['is_guest'] ? "
637                        LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = m.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
638                        LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = m.ID_BOARD AND lmr.ID_MEMBER = $ID_MEMBER)" : '') . "
639                WHERE m.ID_MSG >= " . ($modSettings['maxMsgID'] - 25 * min($num_recent, 5)) . "
640                        AND b.ID_BOARD = m.ID_BOARD" . (empty($exclude_boards) ? '' : "
641                        AND b.ID_BOARD NOT IN (" . implode(', ', $exclude_boards) . ")") . "
642                        AND $user_info[query_see_board]
643                ORDER BY m.ID_MSG DESC
644                LIMIT $num_recent", __FILE__, __LINE__);
645        $posts = array();
646        while ($row = mysql_fetch_assoc($request))
647        {
648                $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']), array('<br />' => '&#10;')));
649                if ($func['strlen']($row['body']) > 128)
650                        $row['body'] = $func['substr']($row['body'], 0, 128) . '...';
651
652                // Censor it!
653                censorText($row['subject']);
654                censorText($row['body']);
655
656                // Build the array.
657                $posts[] = array(
658                        'board' => array(
659                                'id' => $row['ID_BOARD'],
660                                'name' => $row['bName'],
661                                'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
662                                'link' => '<a href="' . $scripturl . '?board=' . $row['ID_BOARD'] . '.0">' . $row['bName'] . '</a>'
663                        ),
664                        'topic' => $row['ID_TOPIC'],
665                        'poster' => array(
666                                'id' => $row['ID_MEMBER'],
667                                'name' => $row['posterName'],
668                                'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
669                                'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>'
670                        ),
671                        'subject' => $row['subject'],
672                        'short_subject' => shorten_subject($row['subject'], 25),
673                        'preview' => $row['body'],
674                        'time' => timeformat($row['posterTime']),
675                        'timestamp' => forum_time(true, $row['posterTime']),
676                        'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . ';topicseen#new',
677                        'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . '#msg' . $row['ID_MSG'] . '">' . $row['subject'] . '</a>',
678                        'new' => !empty($row['isRead']),
679                        'new_from' => $row['new_from'],
680                );
681        }
682        mysql_free_result($request);
683
684        // Just return it.
685        if ($output_method != 'echo' || empty($posts))
686                return $posts;
687
688        echo '
689                <table border="0" class="ssi_table">';
690        foreach ($posts as $post)
691                echo '
692                        <tr>
693                                <td align="right" valign="top" nowrap="nowrap">
694                                        [', $post['board']['link'], ']
695                                </td>
696                                <td valign="top">
697                                        <a href="', $post['href'], '">', $post['subject'], '</a>
698                                        ', $txt[525], ' ', $post['poster']['link'], '
699                                        ', $post['new'] ? '' : '<a href="' . $scripturl . '?topic=' . $post['topic'] . '.msg' . $post['new_from'] . ';topicseen#new"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>', '
700                                </td>
701                                <td align="right" nowrap="nowrap">
702                                        ', $post['time'], '
703                                </td>
704                        </tr>';
705        echo '
706                </table>';
707}
708
709// Recent topic list:   [board] Subject by Poster   Date
710function ssi_recentTopics($num_recent = 8, $exclude_boards = null, $output_method = 'echo')
711{
712        global $context, $settings, $scripturl, $txt, $db_prefix, $ID_MEMBER;
713        global $user_info, $modSettings, $func;
714
715        if ($exclude_boards === null && !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0)
716                $exclude_boards = array($modSettings['recycle_board']);
717        else
718                $exclude_boards = empty($exclude_boards) ? array() : $exclude_boards;
719
720        $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless');
721        $icon_sources = array();
722        foreach ($stable_icons as $icon)
723                $icon_sources[$icon] = 'images_url';
724
725        // Find all the posts in distinct topics.  Newer ones will have higher IDs.
726        $request = db_query("
727                SELECT
728                        m.posterTime, ms.subject, m.ID_TOPIC, m.ID_MEMBER, m.ID_MSG, b.ID_BOARD, b.name AS bName,
729                        IFNULL(mem.realName, m.posterName) AS posterName, " . ($user_info['is_guest'] ? '1 AS isRead, 0 AS new_from' : '
730                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, 0)) >= m.ID_MSG_MODIFIED AS isRead,
731                        IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, -1)) + 1 AS new_from') . ", LEFT(m.body, 384) AS body, m.smileysEnabled, m.icon
732                FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t, {$db_prefix}boards AS b, {$db_prefix}messages AS ms)
733                        LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)" . (!$user_info['is_guest'] ? "
734                        LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = t.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
735                        LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = b.ID_BOARD AND lmr.ID_MEMBER = $ID_MEMBER)" : '') . "
736                WHERE t.ID_LAST_MSG >= " . ($modSettings['maxMsgID'] - 35 * min($num_recent, 5)) . "
737                        AND t.ID_LAST_MSG = m.ID_MSG
738                        AND b.ID_BOARD = t.ID_BOARD" . (empty($exclude_boards) ? '' : "
739                        AND b.ID_BOARD NOT IN (" . implode(', ', $exclude_boards) . ")") . "
740                        AND $user_info[query_see_board]
741                        AND ms.ID_MSG = t.ID_FIRST_MSG
742                ORDER BY t.ID_LAST_MSG DESC
743                LIMIT $num_recent", __FILE__, __LINE__);
744        $posts = array();
745        while ($row = mysql_fetch_assoc($request))
746        {
747                $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']), array('<br />' => '&#10;')));
748                if ($func['strlen']($row['body']) > 128)
749                        $row['body'] = $func['substr']($row['body'], 0, 128) . '...';
750
751                // Censor the subject.
752                censorText($row['subject']);
753                censorText($row['body']);
754
755                if (empty($modSettings['messageIconChecks_disable']) && !isset($icon_sources[$row['icon']]))
756                        $icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.gif') ? 'images_url' : 'default_images_url';
757
758                // Build the array.
759                $posts[] = array(
760                        'board' => array(
761                                'id' => $row['ID_BOARD'],
762                                'name' => $row['bName'],
763                                'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
764                                'link' => '<a href="' . $scripturl . '?board=' . $row['ID_BOARD'] . '.0">' . $row['bName'] . '</a>'
765                        ),
766                        'topic' => $row['ID_TOPIC'],
767                        'poster' => array(
768                                'id' => $row['ID_MEMBER'],
769                                'name' => $row['posterName'],
770                                'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
771                                'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>'
772                        ),
773                        'subject' => $row['subject'],
774                        'short_subject' => shorten_subject($row['subject'], 25),
775                        'preview' => $row['body'],
776                        'time' => timeformat($row['posterTime']),
777                        'timestamp' => forum_time(true, $row['posterTime']),
778                        'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . ';topicseen#new',
779                        'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['ID_MSG'] . '#new">' . $row['subject'] . '</a>',
780                        'new' => !empty($row['isRead']),
781                        'new_from' => $row['new_from'],
782                        'icon' => '<img src="' . $settings[$icon_sources[$row['icon']]] . '/post/' . $row['icon'] . '.gif" align="middle" alt="' . $row['icon'] . '" border="0" />',
783                );
784        }
785        mysql_free_result($request);
786
787        // Just return it.
788        if ($output_method != 'echo' || empty($posts))
789                return $posts;
790
791        echo '
792                <table border="0" class="ssi_table">';
793        foreach ($posts as $post)
794                echo '
795                        <tr>
796                                <td align="right" valign="top" nowrap="nowrap">
797                                        [', $post['board']['link'], ']
798                                </td>
799                                <td valign="top">
800                                        <a href="', $post['href'], '">', $post['subject'], '</a>
801                                        ', $txt[525], ' ', $post['poster']['link'], '
802                                        ', $post['new'] ? '' : '<a href="' . $scripturl . '?topic=' . $post['topic'] . '.msg' . $post['new_from'] . ';topicseen#new"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>', '
803                                </td>
804                                <td align="right" nowrap="nowrap">
805                                        ', $post['time'], '
806                                </td>
807                        </tr>';
808        echo '
809                </table>';
810}
811
812// Show the top poster's name and profile link.
813function ssi_topPoster($topNumber = 1, $output_method = 'echo')
814{
815        global $db_prefix, $scripturl;
816
817        // Find the latest poster.
818        $request = db_query("
819                SELECT ID_MEMBER, realName, posts
820                FROM {$db_prefix}members
821                ORDER BY posts DESC
822                LIMIT $topNumber", __FILE__, __LINE__);
823        $return = array();
824        while ($row = mysql_fetch_assoc($request))
825                $return[] = array(
826                        'id' => $row['ID_MEMBER'],
827                        'name' => $row['realName'],
828                        'href' => $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
829                        'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['realName'] . '</a>',
830                        'posts' => $row['posts']
831                );
832        mysql_free_result($request);
833
834        // Just return all the top posters.
835        if ($output_method != 'echo')
836                return $return;
837
838        // Make a quick array to list the links in.
839        $temp_array = array();
840        foreach ($return as $member)
841                $temp_array[] = $member['link'];
842
843        echo implode(', ', $temp_array);
844}
845
846// Show boards by activity.
847function ssi_topBoards($num_top = 10, $output_method = 'echo')
848{
849        global $context, $settings, $db_prefix, $txt, $scripturl, $ID_MEMBER, $user_info, $modSettings;
850
851        // Find boards with lots of posts.
852        $request = db_query("
853                SELECT
854                        b.name, b.numTopics, b.numPosts, b.ID_BOARD," . (!$user_info['is_guest'] ? ' 1 AS isRead' : '
855                        (IFNULL(lb.ID_MSG, 0) >= b.ID_LAST_MSG) AS isRead') . "
856                FROM {$db_prefix}boards AS b
857                        LEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = b.ID_BOARD AND lb.ID_MEMBER = $ID_MEMBER)
858                WHERE $user_info[query_see_board]" . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? "
859                        AND b.ID_BOARD != " . (int) $modSettings['recycle_board'] : '') . "
860                ORDER BY b.numPosts DESC
861                LIMIT $num_top", __FILE__, __LINE__);
862        $boards = array();
863        while ($row = mysql_fetch_assoc($request))
864                $boards[] = array(
865                        'id' => $row['ID_BOARD'],
866                        'num_posts' => $row['numPosts'],
867                        'num_topics' => $row['numTopics'],
868                        'name' => $row['name'],
869                        'new' => empty($row['isRead']),
870                        'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
871                        'link' => '<a href="' . $scripturl . '?board=' . $row['ID_BOARD'] . '.0">' . $row['name'] . '</a>'
872                );
873        mysql_free_result($request);
874
875        // If we shouldn't output or have nothing to output, just jump out.
876        if ($output_method != 'echo' || empty($boards))
877                return $boards;
878
879        echo '
880                <table class="ssi_table">
881                        <tr>
882                                <th align="left">', $txt['smf82'], '</th>
883                                <th align="left">', $txt[330], '</th>
884                                <th align="left">', $txt[21], '</th>
885                        </tr>';
886        foreach ($boards as $board)
887                echo '
888                        <tr>
889                                <td>', $board['link'], $board['new'] ? ' <a href="' . $board['href'] . '"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>' : '', '</td>
890                                <td align="right">', $board['num_topics'], '</td>
891                                <td align="right">', $board['num_posts'], '</td>
892                        </tr>';
893        echo '
894                </table>';
895}
896
897// Shows the top topics.
898function ssi_topTopics($type = 'replies', $num_topics = 10, $output_method = 'echo')
899{
900        global $db_prefix, $txt, $scripturl, $ID_MEMBER, $user_info, $modSettings;
901
902        if ($modSettings['totalMessages'] > 100000)
903        {
904                $request = db_query("
905                        SELECT ID_TOPIC
906                        FROM {$db_prefix}topics
907                        WHERE num" . ($type != 'replies' ? 'Views' : 'Replies') . " != 0
908                        ORDER BY num" . ($type != 'replies' ? 'Views' : 'Replies') . " DESC
909                        LIMIT 100", __FILE__, __LINE__);
910                $topic_ids = array();
911                while ($row = mysql_fetch_assoc($request))
912                        $topic_ids[] = $row['ID_TOPIC'];
913                mysql_free_result($request);
914        }
915        else
916                $topic_ids = array();
917
918        $request = db_query("
919                SELECT m.subject, m.ID_TOPIC, t.numViews, t.numReplies
920                FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m, {$db_prefix}boards AS b)
921                WHERE m.ID_MSG = t.ID_FIRST_MSG
922                        AND t.ID_BOARD = b.ID_BOARD" . (!empty($topic_ids) ? "
923                        AND t.ID_TOPIC IN (" . implode(', ', $topic_ids) . ")" : '') . "
924                        AND $user_info[query_see_board]" . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? "
925                        AND b.ID_BOARD != $modSettings[recycle_board]" : '') . "
926                ORDER BY t.num" . ($type != 'replies' ? 'Views' : 'Replies') . " DESC
927                LIMIT $num_topics", __FILE__, __LINE__);
928        $topics = array();
929        while ($row = mysql_fetch_assoc($request))
930        {
931                censorText($row['subject']);
932
933                $topics[] = array(
934                        'id' => $row['ID_TOPIC'],
935                        'subject' => $row['subject'],
936                        'num_replies' => $row['numReplies'],
937                        'num_views' => $row['numViews'],
938                        'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0',
939                        'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0">' . $row['subject'] . '</a>',
940                );
941        }
942        mysql_free_result($request);
943
944        if ($output_method != 'echo' || empty($topics))
945                return $topics;
946
947        echo '
948                <table class="ssi_table">
949                        <tr>
950                                <th align="left"></th>
951                                <th align="left">', $txt[301], '</th>
952                                <th align="left">', $txt[110], '</th>
953                        </tr>';
954        foreach ($topics as $topic)
955                echo '
956                        <tr>
957                                <td align="left">
958                                        ', $topic['link'], '
959                                </td>
960                                <td align="right">', $topic['num_views'], '</td>
961                                <td align="right">', $topic['num_replies'], '</td>
962                        </tr>';
963        echo '
964                </table>';
965}
966
967// Shows the top topics, by replies.
968function ssi_topTopicsReplies($num_topics = 10, $output_method = 'echo')
969{
970        return ssi_topTopics('replies', $num_topics, $output_method);
971}
972
973// Shows the top topics, by views.
974function ssi_topTopicsViews($num_topics = 10, $output_method = 'echo')
975{
976        return ssi_topTopics('views', $num_topics, $output_method);
977}
978
979// Show a link to the latest member:  Please welcome, Someone, out latest member.
980function ssi_latestMember($output_method = 'echo')
981{
982        global $db_prefix, $txt, $scripturl, $context;
983
984        if ($output_method == 'echo')
985                echo '
986        ', $txt[201], ' ', $context['common_stats']['latest_member']['link'], '', $txt[581], '<br />';
987        else
988                return $context['common_stats']['latest_member'];
989}
990
991// Show some basic stats:  Total This: XXXX, etc.
992function ssi_boardStats($output_method = 'echo')
993{
994        global $db_prefix, $txt, $scripturl, $modSettings;
995
996        $totals = array(
997                'members' => $modSettings['totalMembers'],
998                'posts' => $modSettings['totalMessages'],
999                'topics' => $modSettings['totalTopics']
1000        );
1001
1002        $result = db_query("
1003                SELECT COUNT(*)
1004                FROM {$db_prefix}boards", __FILE__, __LINE__);
1005        list ($totals['boards']) = mysql_fetch_row($result);
1006        mysql_free_result($result);
1007
1008        $result = db_query("
1009                SELECT COUNT(*)
1010                FROM {$db_prefix}categories", __FILE__, __LINE__);
1011        list ($totals['categories']) = mysql_fetch_row($result);
1012        mysql_free_result($result);
1013
1014        if ($output_method != 'echo')
1015                return $totals;
1016
1017        echo '
1018                ', $txt[488], ': <a href="', $scripturl . '?action=mlist">', $totals['members'], '</a><br />
1019                ', $txt[489], ': ', $totals['posts'], '<br />
1020                ', $txt[490], ': ', $totals['topics'], ' <br />
1021                ', $txt[658], ': ', $totals['categories'], '<br />
1022                ', $txt[665], ': ', $totals['boards'];
1023}
1024
1025// Shows a list of online users:  YY Guests, ZZ Users and then a list...
1026function ssi_whosOnline($output_method = 'echo')
1027{
1028        global $scripturl, $db_prefix, $user_info, $txt;
1029
1030        // Load the users online right now.
1031        $result = db_query("
1032                SELECT
1033                        lo.ID_MEMBER, lo.logTime, mem.realName, mem.memberName, mem.showOnline,
1034                        mg.onlineColor, mg.ID_GROUP
1035                FROM {$db_prefix}log_online AS lo
1036                        LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = lo.ID_MEMBER)
1037                        LEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = IF(mem.ID_GROUP = 0, mem.ID_POST_GROUP, mem.ID_GROUP))", __FILE__, __LINE__);
1038
1039        $return['users'] = array();
1040        $return['guests'] = 0;
1041        $return['hidden'] = 0;
1042        $return['buddies'] = 0;
1043        $show_buddies = !empty($user_info['buddies']);
1044
1045        while ($row = mysql_fetch_assoc($result))
1046        {
1047                if (!isset($row['realName']))
1048                        $return['guests']++;
1049                elseif (!empty($row['showOnline']) || allowedTo('moderate_forum'))
1050                {
1051                        // Some basic color coding...
1052                        if (!empty($row['onlineColor']))
1053                                $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '" style="color: ' . $row['onlineColor'] . ';">' . $row['realName'] . '</a>';
1054                        else
1055                                $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['realName'] . '</a>';
1056
1057                        // Bold any buddies.
1058                        if ($show_buddies && in_array($row['ID_MEMBER'], $user_info['buddies']))
1059                        {
1060                                $return['buddies']++;
1061                                $link = '<b>' . $link . '</b>';
1062                        }
1063
1064                        $return['users'][$row['logTime'] . $row['memberName']] = array(
1065                                'id' => $row['ID_MEMBER'],
1066                                'username' => $row['memberName'],
1067                                'name' => $row['realName'],
1068                                'group' => $row['ID_GROUP'],
1069                                'href' => $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
1070                                'link' => $link,
1071                                'hidden' => empty($row['showOnline']),
1072                                'is_last' => false,
1073                        );
1074                }
1075                else
1076                        $return['hidden']++;
1077        }
1078        mysql_free_result($result);
1079
1080        if (!empty($return['users']))
1081        {
1082                krsort($return['users']);
1083                $userlist = array_keys($return['users']);
1084                $return['users'][$userlist[count($userlist) - 1]]['is_last'] = true;
1085        }
1086        $return['num_users'] = count($return['users']) + $return['hidden'];
1087        $return['total_users'] = $return['num_users'] + $return['guests'];
1088
1089        if ($output_method != 'echo')
1090                return $return;
1091
1092        echo '
1093                ', $return['guests'], ' ', $return['guests'] == 1 ? $txt['guest'] : $txt['guests'], ', ', $return['num_users'], ' ', $return['num_users'] == 1 ? $txt['user'] : $txt['users'];
1094
1095        // Hidden users, or buddies?
1096        if ($return['hidden'] > 0 || $show_buddies)
1097                echo '
1098                        (' . ($show_buddies ? ($return['buddies'] . ' ' . ($return['buddies'] == 1 ? $txt['buddy'] : $txt['buddies'])) : '') . ($show_buddies && $return['hidden'] ? ', ' : '') . (!$return['hidden'] ? '' : $return['hidden'] . ' ' . $txt['hidden']) . ')';
1099
1100        echo '<br />';
1101        foreach ($return['users'] as $user)
1102                echo $user['hidden'] ? '<i>' . $user['link'] . '</i>' : $user['link'], $user['is_last'] ? '' : ', ';
1103}
1104
1105// Just like whosOnline except it also logs the online presence.
1106function ssi_logOnline($output_method = 'echo')
1107{
1108        writeLog();
1109
1110        if ($output_method != 'echo')
1111                return ssi_whosOnline($output_method);
1112        else
1113                ssi_whosOnline($output_method);
1114}
1115
1116// Shows a login box.
1117function ssi_login($redirect_to = '', $output_method = 'echo')
1118{
1119        global $scripturl, $txt, $user_info, $context;
1120
1121        if ($redirect_to != '')
1122                $_SESSION['login_url'] = $redirect_to;
1123
1124        if ($output_method != 'echo' || !$user_info['is_guest'])
1125                return $user_info['is_guest'];
1126
1127        echo '
1128                <form action="', $scripturl, '?action=login2" method="post" accept-charset="', $context['character_set'], '">
1129                        <table border="0" cellspacing="1" cellpadding="0" class="ssi_table">
1130                                <tr>
1131                                        <td align="right"><label for="user">', $txt[35], ':</label>&nbsp;</td>
1132                                        <td><input type="text" id="user" name="user" size="9" value="', $user_info['username'], '" /></td>
1133                                </tr><tr>
1134                                        <td align="right"><label for="passwrd">', $txt[36], ':</label>&nbsp;</td>
1135                                        <td><input type="password" name="passwrd" id="passwrd" size="9" /></td>
1136                                </tr><tr>
1137                                        <td><input type="hidden" name="cookielength" value="-1" /></td>
1138                                        <td><input type="submit" value="', $txt[34], '" /></td>
1139                                </tr>
1140                        </table>
1141                </form>';
1142}
1143
1144// Show the most-voted-in poll.
1145function ssi_topPoll($output_method = 'echo')
1146{
1147        // Just use recentPoll, no need to duplicate code...
1148        return ssi_recentPoll($output_method, true);
1149}
1150
1151// Show the most recently posted poll.
1152function ssi_recentPoll($output_method = 'echo', $topPollInstead = false)
1153{
1154        global $db_prefix, $txt, $ID_MEMBER, $settings, $boardurl, $sc, $user_info;
1155        global $context;
1156
1157        $boardsAllowed = array_intersect(boardsAllowedTo('poll_view'), boardsAllowedTo('poll_vote'));
1158
1159        if (empty($boardsAllowed))
1160                return array();
1161
1162        $request = db_query("
1163                SELECT p.ID_POLL, p.question, t.ID_TOPIC, p.maxVotes
1164                FROM ({$db_prefix}polls AS p, {$db_prefix}boards AS b, {$db_prefix}topics AS t" . ($topPollInstead ? ", {$db_prefix}poll_choices AS pc" : '') . ")
1165                        LEFT JOIN {$db_prefix}log_polls AS lp ON (lp.ID_POLL = p.ID_POLL AND lp.ID_MEMBER = $ID_MEMBER)
1166                WHERE p.votingLocked = 0" . ($topPollInstead ? "
1167                        AND pc.ID_POLL = p.ID_POLL" : '') . "
1168                        AND lp.ID_CHOICE IS NULL
1169                        AND t.ID_POLL = p.ID_POLL
1170                        AND b.ID_BOARD = t.ID_BOARD
1171                        AND $user_info[query_see_board]" . (!in_array(0, $boardsAllowed) ? "
1172                        AND b.ID_BOARD IN (" . implode(', ', $boardsAllowed) . ")" : '') . "
1173                ORDER BY " . ($topPollInstead ? 'pc.votes' : 'p.ID_POLL') . " DESC
1174                LIMIT 1", __FILE__, __LINE__);
1175        $row = mysql_fetch_assoc($request);
1176        mysql_free_result($request);
1177
1178        // This user has voted on all the polls.
1179        if ($row === false)
1180                return array();
1181
1182        $request = db_query("
1183                SELECT COUNT(DISTINCT ID_MEMBER)
1184                FROM {$db_prefix}log_polls
1185                WHERE ID_POLL = $row[ID_POLL]", __FILE__, __LINE__);
1186        list ($total) = mysql_fetch_row($request);
1187        mysql_free_result($request);
1188
1189        $request = db_query("
1190                SELECT ID_CHOICE, label, votes
1191                FROM {$db_prefix}poll_choices
1192                WHERE ID_POLL = $row[ID_POLL]", __FILE__, __LINE__);
1193        $options = array();
1194        while ($rowChoice = mysql_fetch_assoc($request))
1195        {
1196                censorText($rowChoice['label']);
1197
1198                $options[$rowChoice['ID_CHOICE']] = array($rowChoice['label'], $rowChoice['votes']);
1199        }
1200        mysql_free_result($request);
1201
1202        $return = array(
1203                'id' => $row['ID_POLL'],
1204                'image' => 'poll',
1205                'question' => $row['question'],
1206                'total_votes' => $total,
1207                'is_locked' => false,
1208                'topic' => $row['ID_TOPIC'],
1209                'options' => array()
1210        );
1211
1212        // Calculate the percentages and bar lengths...
1213        $divisor = $return['total_votes'] == 0 ? 1 : $return['total_votes'];
1214        foreach ($options as $i => $option)
1215        {
1216                $bar = floor(($option[1] * 100) / $divisor);
1217                $barWide = $bar == 0 ? 1 : floor(($bar * 5) / 3);
1218                $return['options'][$i] = array(
1219                        'id' => 'options-' . $i,
1220                        'percent' => $bar,
1221                        'votes' => $option[1],
1222                        'bar' => '<span style="white-space: nowrap;"><img src="' . $settings['images_url'] . '/poll_left.gif" alt="" /><img src="' . $settings['images_url'] . '/poll_middle.gif" width="' . $barWide . '" height="12" alt="-" /><img src="' . $settings['images_url'] . '/poll_right.gif" alt="" /></span>',
1223                        'option' => parse_bbc($option[0]),
1224                        'vote_button' => '<input type="' . ($row['maxVotes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="check" />'
1225                );
1226        }
1227
1228        $return['allowed_warning'] = $row['maxVotes'] > 1 ? sprintf($txt['poll_options6'], $row['maxVotes']) : '';
1229
1230        if ($output_method != 'echo')
1231                return $return;
1232
1233        echo '
1234                <form action="', $boardurl, '/SSI.php?ssi_function=pollVote" method="post" accept-charset="', $context['character_set'], '">
1235                        <input type="hidden" name="poll" value="', $return['id'], '" />
1236                        <table border="0" cellspacing="1" cellpadding="0" class="ssi_table">
1237                                <tr>
1238                                        <td><b>', $return['question'], '</b></td>
1239                                </tr>
1240                                <tr>
1241                                        <td>', $return['allowed_warning'], '</td>
1242                                </tr>';
1243        foreach ($return['options'] as $option)
1244                echo '
1245                                <tr>
1246                                        <td><label for="', $option['id'], '">', $option['vote_button'], ' ', $option['option'], '</label></td>
1247                                </tr>';
1248        echo '
1249                                <tr>
1250                                        <td><input type="submit" value="', $txt['smf23'], '" /></td>
1251                                </tr>
1252                        </table>
1253                        <input type="hidden" name="sc" value="', $sc, '" />
1254                </form>';
1255}
1256
1257function ssi_showPoll($topic = null, $output_method = 'echo')
1258{
1259        global $db_prefix, $txt, $ID_MEMBER, $settings, $boardurl, $sc, $user_info;
1260        global $context;
1261
1262        $boardsAllowed = boardsAllowedTo('poll_view');
1263
1264        if (empty($boardsAllowed))
1265                return array();
1266
1267        if ($topic === null && isset($_REQUEST['ssi_topic']))
1268                $topic = (int) $_REQUEST['ssi_topic'];
1269        else
1270                $topic = (int) $topic;
1271
1272        $request = db_query("
1273                SELECT
1274                        p.ID_POLL, p.question, p.votingLocked, p.hideResults, p.expireTime, p.maxVotes, b.ID_BOARD
1275                FROM ({$db_prefix}topics AS t, {$db_prefix}polls AS p, {$db_prefix}boards AS b)
1276                WHERE p.ID_POLL = t.ID_POLL
1277                        AND t.ID_TOPIC = $topic
1278                        AND b.ID_BOARD = t.ID_BOARD
1279                        AND $user_info[query_see_board]" . (!in_array(0, $boardsAllowed) ? "
1280                        AND b.ID_BOARD IN (" . implode(', ', $boardsAllowed) . ")" : '') . "
1281                LIMIT 1", __FILE__, __LINE__);
1282
1283        // Either this topic has no poll, or the user cannot view it.
1284        if (mysql_num_rows($request) == 0)
1285                return array();
1286
1287        $row = mysql_fetch_assoc($request);
1288        mysql_free_result($request);
1289
1290        // Check if they can vote.
1291        if (!empty($row['expireTime']) && $row['expireTime'] < time())
1292                $allow_vote = false;
1293        elseif ($user_info['is_guest'] || !empty($row['votingLocked']) || !allowedTo('poll_vote', array($row['ID_BOARD'])))
1294                $allow_vote = false;
1295        else
1296        {
1297                $request = db_query("
1298                        SELECT ID_MEMBER
1299                        FROM {$db_prefix}log_polls
1300                        WHERE ID_POLL = $row[ID_POLL]
1301                                AND ID_MEMBER = $ID_MEMBER
1302                        LIMIT 1", __FILE__, __LINE__);
1303                $allow_vote = mysql_num_rows($request) == 0;
1304                mysql_free_result($request);
1305        }
1306
1307        $request = db_query("
1308                SELECT COUNT(DISTINCT ID_MEMBER)
1309                FROM {$db_prefix}log_polls
1310                WHERE ID_POLL = $row[ID_POLL]", __FILE__, __LINE__);
1311        list ($total) = mysql_fetch_row($request);
1312        mysql_free_result($request);
1313
1314        $request = db_query("
1315                SELECT ID_CHOICE, label, votes
1316                FROM {$db_prefix}poll_choices
1317                WHERE ID_POLL = $row[ID_POLL]", __FILE__, __LINE__);
1318        $options = array();
1319        $total_votes = 0;
1320        while ($rowChoice = mysql_fetch_assoc($request))
1321        {
1322                censorText($rowChoice['label']);
1323
1324                $options[$rowChoice['ID_CHOICE']] = array($rowChoice['label'], $rowChoice['votes']);
1325                $total_votes += $rowChoice['votes'];
1326        }
1327        mysql_free_result($request);
1328
1329        $return = array(
1330                'id' => $row['ID_POLL'],
1331                'image' => empty($pollinfo['votingLocked']) ? 'poll' : 'locked_poll',
1332                'question' => $row['question'],
1333                'total_votes' => $total,
1334                'is_locked' => !empty($pollinfo['votingLocked']),
1335                'allow_vote' => $allow_vote,
1336                'topic' => $topic
1337        );
1338
1339        // Calculate the percentages and bar lengths...
1340        $divisor = $total_votes == 0 ? 1 : $total_votes;
1341        foreach ($options as $i => $option)
1342        {
1343                $bar = floor(($option[1] * 100) / $divisor);
1344                $barWide = $bar == 0 ? 1 : floor(($bar * 5) / 3);
1345                $return['options'][$i] = array(
1346                        'id' => 'options-' . $i,
1347                        'percent' => $bar,
1348                        'votes' => $option[1],
1349                        'bar' => '<span style="white-space: nowrap;"><img src="' . $settings['images_url'] . '/poll_left.gif" alt="" /><img src="' . $settings['images_url'] . '/poll_middle.gif" width="' . $barWide . '" height="12" alt="-" /><img src="' . $settings['images_url'] . '/poll_right.gif" alt="" /></span>',
1350                        'option' => parse_bbc($option[0]),
1351                        'vote_button' => '<input type="' . ($row['maxVotes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="check" />'
1352                );
1353        }
1354
1355        $return['allowed_warning'] = $row['maxVotes'] > 1 ? sprintf($txt['poll_options6'], $row['maxVotes']) : '';
1356
1357        if ($output_method != 'echo')
1358                return $return;
1359
1360        if ($return['allow_vote'])
1361        {
1362                echo '
1363                        <form action="', $boardurl, '/SSI.php?ssi_function=pollVote" method="post" accept-charset="', $context['character_set'], '">
1364                                <input type="hidden" name="poll" value="', $return['id'], '" />
1365                                <table border="0" cellspacing="1" cellpadding="0" class="ssi_table">
1366                                        <tr>
1367                                                <td><b>', $return['question'], '</b></td>
1368                                        </tr>
1369                                        <tr>
1370                                                <td>', $return['allowed_warning'], '</td>
1371                                        </tr>';
1372                foreach ($return['options'] as $option)
1373                        echo '
1374                                        <tr>
1375                                                <td><label for="', $option['id'], '">', $option['vote_button'], ' ', $option['option'], '</label></td>
1376                                        </tr>';
1377                echo '
1378                                        <tr>
1379                                                <td><input type="submit" value="', $txt['smf23'], '" /></td>
1380                                        </tr>
1381                                </table>
1382                                <input type="hidden" name="sc" value="', $sc, '" />
1383                        </form>';
1384        }
1385        else
1386        {
1387                echo '
1388                                <table border="0" cellspacing="1" cellpadding="0" class="ssi_table">
1389                                        <tr>
1390                                                <td colspan="2"><b>', $return['question'], '</b></td>
1391                                        </tr>';
1392                foreach ($return['options'] as $option)
1393                        echo '
1394                                        <tr>
1395                                                <td align="right" valign="top">', $option['option'], '</td>
1396                                                <td align="left">', $option['bar'], ' ', $option['votes'], ' (', $option['percent'], '%)</td>
1397                                        </tr>';
1398                echo '
1399                                        <tr>
1400                                                <td colspan="2"><b>', $txt['smf24'], ': ', $return['total_votes'], '</b></td>
1401                                        </tr>
1402                                </table>';
1403        }
1404}
1405
1406// Takes care of voting - don't worry, this is done automatically.
1407function ssi_pollVote()
1408{
1409        global $db_prefix, $ID_MEMBER, $user_info, $sc;
1410
1411        if (!isset($_POST['sc']) || $_POST['sc'] != $sc || empty($_POST['options']) || !isset($_POST['poll']))
1412        {
1413                echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1414<html>
1415<head>
1416        <script language="JavaScript" type="text/javascript"><!-- // --><![CDATA[
1417                history.go(-1);
1418        // ]]></script>
1419</head>
1420<body>&laquo;</body>
1421</html>';
1422                return;
1423        }
1424
1425        // This can cause weird errors! (ie. copyright missing.)
1426        checkSession();
1427
1428        $_POST['poll'] = (int) $_POST['poll'];
1429
1430        // Check if they have already voted, or voting is locked.
1431        $request = db_query("
1432                SELECT IFNULL(lp.ID_CHOICE, -1) AS selected, p.votingLocked, p.expireTime, p.maxVotes, t.ID_TOPIC
1433                FROM ({$db_prefix}polls AS p, {$db_prefix}topics AS t, {$db_prefix}boards AS b)
1434                        LEFT JOIN {$db_prefix}log_polls AS lp ON (lp.ID_POLL = p.ID_POLL AND lp.ID_MEMBER = $ID_MEMBER)
1435                WHERE p.ID_POLL = $_POST[poll]
1436                        AND t.ID_POLL = $_POST[poll]
1437                        AND b.ID_BOARD = t.ID_BOARD
1438                        AND $user_info[query_see_board]
1439                LIMIT 1", __FILE__, __LINE__);
1440        if (mysql_num_rows($request) == 0)
1441                die;
1442        $row = mysql_fetch_assoc($request);
1443        mysql_free_result($request);
1444
1445        if (!empty($row['votingLocked']) || $row['selected'] != -1 || (!empty($row['expireTime']) && time() > $row['expireTime']))
1446                redirectexit('topic=' . $row['ID_TOPIC'] . '.0');
1447
1448        // Too many options checked?
1449        if (count($_REQUEST['options']) > $row['maxVotes'])
1450                redirectexit('topic=' . $row['ID_TOPIC'] . '.0');
1451
1452        $options = array();
1453        $setString = '';
1454        foreach ($_REQUEST['options'] as $id)
1455        {
1456                $id = (int) $id;
1457
1458                $options[] = $id;
1459                $setString .= "
1460                                ($_POST[poll], $ID_MEMBER, $id),";
1461        }
1462        $setString = substr($setString, 0, -1);
1463
1464        // Add their vote in to the tally.
1465        db_query("
1466                INSERT INTO {$db_prefix}log_polls
1467                        (ID_POLL, ID_MEMBER, ID_CHOICE)
1468                VALUES $setString", __FILE__, __LINE__);
1469        db_query("
1470                UPDATE {$db_prefix}poll_choices
1471                SET votes = votes + 1
1472                WHERE ID_POLL = $_POST[poll]
1473                        AND ID_CHOICE IN (" . implode(', ', $options) . ")
1474                LIMIT " . count($options), __FILE__, __LINE__);
1475
1476        redirectexit('topic=' . $row['ID_TOPIC'] . '.0');
1477}
1478
1479// Show a search box.
1480function ssi_quickSearch($output_method = 'echo')
1481{
1482        global $scripturl, $txt, $context;
1483
1484        if ($output_method != 'echo')
1485                return $scripturl . '?action=search';
1486
1487        echo '
1488                <form action="', $scripturl, '?action=search2" method="post" accept-charset="', $context['character_set'], '">
1489                        <input type="hidden" name="advanced" value="0" /><input type="text" name="search" size="30" /> <input type="submit" name="submit" value="', $txt[182], '" />
1490                </form>';
1491}
1492
1493// Show what would be the forum news.
1494function ssi_news($output_method = 'echo')
1495{
1496        global $context;
1497
1498        if ($output_method != 'echo')
1499                return $context['random_news_line'];
1500
1501        echo $context['random_news_line'];
1502}
1503
1504// Show today's birthdays.
1505function ssi_todaysBirthdays($output_method = 'echo')
1506{
1507        global $context, $scripturl;
1508
1509        if (!smf_loadCalendarInfo() || empty($context['calendar_birthdays']))
1510                return array();
1511
1512        if ($output_method != 'echo')
1513                return $context['calendar_birthdays'];
1514
1515        foreach ($context['calendar_birthdays'] as $member)
1516                echo '
1517                        <a href="', $scripturl, '?action=profile;u=', $member['id'], '">' . $member['name'] . (isset($member['age']) ? ' (' . $member['age'] . ')' : '') . '</a>' . (!$member['is_last'] ? ', ' : '');
1518}
1519
1520// Show today's holidays.
1521function ssi_todaysHolidays($output_method = 'echo')
1522{
1523        global $context;
1524
1525        if (!smf_loadCalendarInfo() || empty($context['calendar_holidays']))
1526                return array();
1527
1528        if ($output_method != 'echo')
1529                return $context['calendar_holidays'];
1530
1531        echo '
1532                ', implode(', ', $context['calendar_holidays']);
1533}
1534
1535// Show today's events.
1536function ssi_todaysEvents($output_method = 'echo')
1537{
1538        global $context;
1539
1540        if (!smf_loadCalendarInfo() || empty($context['calendar_events']))
1541                return array();
1542
1543        if ($output_method != 'echo')
1544                return $context['calendar_events'];
1545
1546        foreach ($context['calendar_events'] as $event)
1547        {
1548                if ($event['can_edit'])
1549                        echo '
1550        <a href="' . $event['modify_href'] . '" style="color: #FF0000;">*</a> ';
1551                echo '
1552        ' . $event['link'] . (!$event['is_last'] ? ', ' : '');
1553        }
1554}
1555
1556// Show all calendar entires for today. (birthdays, holodays, and events.)
1557function ssi_todaysCalendar($output_method = 'echo')
1558{
1559        global $context, $modSettings, $txt, $scripturl;
1560
1561        if (!smf_loadCalendarInfo())
1562                return array();
1563
1564        if ($output_method != 'echo')
1565                return array(
1566                        'birthdays' => $context['calendar_birthdays'],
1567                        'holidays' => $context['calendar_holidays'],
1568                        'events' => $context['calendar_events']
1569                );
1570
1571        if (!empty($context['calendar_holidays']))
1572                echo '
1573                        <span style="color: #' . $modSettings['cal_holidaycolor'] . ';">' . $txt['calendar5'] . ' ' . implode(', ', $context['calendar_holidays']) . '<br /></span>';
1574        if (!empty($context['calendar_birthdays']))
1575        {
1576                echo '
1577                        <span style="color: #' . $modSettings['cal_bdaycolor'] . ';">' . $txt['calendar3b'] . '</span> ';
1578                foreach ($context['calendar_birthdays'] as $member)
1579                        echo '
1580                        <a href="', $scripturl, '?action=profile;u=', $member['id'], '">', $member['name'], isset($member['age']) ? ' (' . $member['age'] . ')' : '', '</a>', !$member['is_last'] ? ', ' : '';
1581                echo '
1582                        <br />';
1583        }
1584        if (!empty($context['calendar_events']))
1585        {
1586                echo '
1587                        <span style="color: #' . $modSettings['cal_eventcolor'] . ';">' . $txt['calendar4b'] . '</span> ';
1588                foreach ($context['calendar_events'] as $event)
1589                {
1590                        if ($event['can_edit'])
1591                                echo '
1592                        <a href="' . $event['modify_href'] . '" style="color: #FF0000;">*</a> ';
1593                        echo '
1594                        ' . $event['link'] . (!$event['is_last'] ? ', ' : '');
1595                }
1596        }
1597}
1598
1599// Show the latest news, with a template... by board.
1600function ssi_boardNews($board = null, $limit = null, $start = null, $length = null, $output_method = 'echo')
1601{
1602        global $scripturl, $db_prefix, $txt, $settings, $modSettings, $context;
1603        global $func;
1604
1605        loadLanguage('Stats');
1606
1607        // Must be integers....
1608        if ($limit === null)
1609                $limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 5;
1610        else
1611                $limit = (int) $limit;
1612
1613        if ($start === null)
1614                $start = isset($_GET['start']) ? (int) $_GET['start'] : 0;
1615        else
1616                $start = (int) $start;
1617
1618        if ($board !== null)
1619                $board = (int) $board;
1620        elseif (isset($_GET['board']))
1621                $board = (int) $_GET['board'];
1622
1623        if ($length === null)
1624                $length = isset($_GET['length']) ? (int) $_GET['length'] : 0;
1625        else
1626                $length = (int) $length;
1627
1628        $limit = max(0, $limit);
1629        $start = max(0, $start);
1630
1631        // Make sure guests can see this board.
1632        $request = db_query("
1633                SELECT ID_BOARD
1634                FROM {$db_prefix}boards
1635                WHERE " . ($board === null ? '' : "ID_BOARD = $board
1636                        AND ") . "FIND_IN_SET(-1, memberGroups)
1637                LIMIT 1", __FILE__, __LINE__);
1638        if (mysql_num_rows($request) == 0)
1639        {
1640                if ($output_method == 'echo')
1641                        die($txt['smf_news_error2']);
1642                else
1643                        return array();
1644        }
1645        list ($board) = mysql_fetch_row($request);
1646        mysql_free_result($request);
1647
1648        // Load the message icons - the usual suspects.
1649        $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless');
1650        $icon_sources = array();
1651        foreach ($stable_icons as $icon)
1652                $icon_sources[$icon] = 'images_url';
1653
1654        // Find the post ids.
1655        $request = db_query("
1656                SELECT ID_FIRST_MSG
1657                FROM {$db_prefix}topics
1658                WHERE ID_BOARD = $board
1659                ORDER BY ID_FIRST_MSG DESC
1660                LIMIT $start, $limit", __FILE__, __LINE__);
1661        $posts = array();
1662        while ($row = mysql_fetch_assoc($request))
1663                $posts[] = $row['ID_FIRST_MSG'];
1664        mysql_free_result($request);
1665
1666        if (empty($posts))
1667                return array();
1668
1669        // Find the posts.
1670        $request = db_query("
1671                SELECT
1672                        m.icon, m.subject, m.body, IFNULL(mem.realName, m.posterName) AS posterName, m.posterTime,
1673                        t.numReplies, t.ID_TOPIC, m.ID_MEMBER, m.smileysEnabled, m.ID_MSG, t.locked
1674                FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m)
1675                        LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
1676                WHERE t.ID_FIRST_MSG IN (" . implode(', ', $posts) . ")
1677                        AND m.ID_MSG = t.ID_FIRST_MSG
1678                ORDER BY t.ID_FIRST_MSG DESC
1679                LIMIT " . count($posts), __FILE__, __LINE__);
1680        $return = array();
1681        while ($row = mysql_fetch_assoc($request))
1682        {
1683                // If we want to limit the length of the post.
1684                if (!empty($length) && $func['strlen']($row['body']) > $length)
1685                {
1686                        $row['body'] = $func['substr']($row['body'], 0, $length);
1687
1688                        // The first space or line break. (<br />, etc.)
1689                        $cutoff = max(strrpos($row['body'], ' '), strrpos($row['body'], '<'));
1690
1691                        if ($cutoff !== false)
1692                                $row['body'] = $func['substr']($row['body'], 0, $cutoff);
1693                        $row['body'] .= '...';
1694                }
1695
1696                $row['body'] = parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']);
1697
1698                // Check that this message icon is there...
1699                if (empty($modSettings['messageIconChecks_disable']) && !isset($icon_sources[$row['icon']]))
1700                        $icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.gif') ? 'images_url' : 'default_images_url';
1701
1702                censorText($row['subject']);
1703                censorText($row['body']);
1704
1705                $return[] = array(
1706                        'id' => $row['ID_TOPIC'],
1707                        'message_id' => $row['ID_MSG'],
1708                        'icon' => '<img src="' . $settings[$icon_sources[$row['icon']]] . '/post/' . $row['icon'] . '.gif" align="middle" alt="' . $row['icon'] . '" border="0" />',
1709                        'subject' => $row['subject'],
1710                        'time' => timeformat($row['posterTime']),
1711                        'timestamp' => forum_time(true, $row['posterTime']),
1712                        'body' => $row['body'],
1713                        'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0',
1714                        'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0">' . $row['numReplies'] . ' ' . ($row['numReplies'] == 1 ? $txt['smf_news_1'] : $txt['smf_news_2']) . '</a>',
1715                        'replies' => $row['numReplies'],
1716                        'comment_href' => !empty($row['locked']) ? '' : $scripturl . '?action=post;topic=' . $row['ID_TOPIC'] . '.' . $row['numReplies'] . ';num_replies=' . $row['numReplies'],
1717                        'comment_link' => !empty($row['locked']) ? '' : '<a href="' . $scripturl . '?action=post;topic=' . $row['ID_TOPIC'] . '.' . $row['numReplies'] . ';num_replies=' . $row['numReplies'] . '">' . $txt['smf_news_3'] . '</a>',
1718                        'new_comment' => !empty($row['locked']) ? '' : '<a href="' . $scripturl . '?action=post;topic=' . $row['ID_TOPIC'] . '.' . $row['numReplies'] . '">' . $txt['smf_news_3'] . '</a>',
1719                        'poster' => array(
1720                                'id' => $row['ID_MEMBER'],
1721                                'name' => $row['posterName'],
1722                                'href' => !empty($row['ID_MEMBER']) ? $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] : '',
1723                                'link' => !empty($row['ID_MEMBER']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>' : $row['posterName']
1724                        ),
1725                        'locked' => !empty($row['locked']),
1726                        'is_last' => false
1727                );
1728        }
1729        mysql_free_result($request);
1730
1731        if (empty($return))
1732                return $return;
1733
1734        $return[count($return) - 1]['is_last'] = true;
1735
1736        if ($output_method != 'echo')
1737                return $return;
1738
1739        foreach ($return as $news)
1740        {
1741                echo '
1742                        <div>
1743                                <a href="', $news['href'], '">', $news['icon'], '</a> <b>', $news['subject'], '</b>
1744                                <div class="smaller">', $news['time'], ' ', $txt[525], ' ', $news['poster']['link'], '</div>
1745
1746                                <div class="post" style="padding: 2ex 0;">', $news['body'], '</div>
1747
1748                                ', $news['link'], $news['locked'] ? '' : ' | ' . $news['comment_link'], '
1749                        </div>';
1750
1751                if (!$news['is_last'])
1752                        echo '
1753                        <hr style="margin: 2ex 0;" width="100%" />';
1754        }
1755}
1756
1757// Show the most recent events.
1758function ssi_recentEvents($max_events = 7, $output_method = 'echo')
1759{
1760        global $db_prefix, $user_info, $scripturl, $modSettings, $txt, $sc, $ID_MEMBER;
1761
1762        // Find all events which are happening in the near future that the member can see.
1763        $request = db_query("
1764                SELECT
1765                        cal.ID_EVENT, cal.startDate, cal.endDate, cal.title, cal.ID_MEMBER, cal.ID_TOPIC,
1766                        cal.ID_BOARD, t.ID_FIRST_MSG
1767                FROM {$db_prefix}calendar AS cal
1768                        LEFT JOIN {$db_prefix}boards AS b ON (b.ID_BOARD = cal.ID_BOARD)
1769                        LEFT JOIN {$db_prefix}topics AS t ON (t.ID_TOPIC = cal.ID_TOPIC)
1770                WHERE cal.endDate >= '" . strftime('%Y-%m-%d', forum_time(false)) . "'
1771                        AND (cal.ID_BOARD = 0 OR $user_info[query_see_board])
1772                ORDER BY cal.startDate
1773                LIMIT $max_events", __FILE__, __LINE__);
1774        $return = array();
1775        $duplicates = array();
1776        while ($row = mysql_fetch_assoc($request))
1777        {
1778                // Check if we've already come by an event linked to this same topic with the same title... and don't display it if we have.
1779                if (!empty($duplicates[$row['title'] . $row['ID_TOPIC']]))
1780                        continue;
1781
1782                // Censor the title.
1783                censorText($row['title']);
1784
1785                if ($row['startDate'] < strftime('%Y-%m-%d', forum_time(false)))
1786                        $date = strftime('%Y-%m-%d', forum_time(false));
1787                else
1788                        $date = $row['startDate'];
1789
1790                $return[$date][] = array(
1791                        'id' => $row['ID_EVENT'],
1792                        'title' => $row['title'],
1793                        'can_edit' => allowedTo('calendar_edit_any') || ($row['ID_MEMBER'] == $ID_MEMBER && allowedTo('calendar_edit_own')),
1794                        'modify_href' => $scripturl . '?action=' . ($row['ID_BOARD'] == 0 ? 'calendar;sa=post;' : 'post;msg=' . $row['ID_FIRST_MSG'] . ';topic=' . $row['ID_TOPIC'] . '.0;calendar;') . 'eventid=' . $row['ID_EVENT'] . ';sesc=' . $sc,
1795                        'href' => $row['ID_BOARD'] == 0 ? '' : $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0',
1796                        'link' => $row['ID_BOARD'] == 0 ? $row['title'] : '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0">' . $row['title'] . '</a>',
1797                        'start_date' => $row['startDate'],
1798                        'end_date' => $row['endDate'],
1799                        'is_last' => false
1800                );
1801
1802                // Let's not show this one again, huh?
1803                $duplicates[$row['title'] . $row['ID_TOPIC']] = true;
1804        }
1805        mysql_free_result($request);
1806
1807        foreach ($return as $mday => $array)
1808                $return[$mday][count($array) - 1]['is_last'] = true;
1809
1810        if ($output_method != 'echo')
1811                return $return;
1812
1813        // Well the output method is echo.
1814    echo '<div class="calendar">';
1815    echo '<div class="header">';
1816        foreach ($return as $mday => $array)
1817    {
1818        echo '<div class="date">'.strftime("%A, %d %b %Y", strtotime($mday)).'</div>';
1819                foreach ($array as $event)
1820                {
1821            echo '<div class="event">';
1822                        if ($event['can_edit']) {
1823                                echo '<a href="' . $event['modify_href'] . '" style="color: #FF0000;">&raquo;</a> ';
1824            } else {
1825                echo '&raquo';
1826            }
1827                        echo '' . $event['link'] . (!$event['is_last'] ? ', ' : '');
1828            echo '</div>';
1829                }
1830    }
1831    echo '</div>';
1832}
1833
1834// Load the calendar information. (internal...)
1835function smf_loadCalendarInfo()
1836{
1837        global $modSettings, $context, $user_info, $scripturl, $sc, $ID_MEMBER;
1838
1839        // Get the current forum time and check whether the statistics are up to date.
1840        if (!isset($modSettings['cal_today_updated']) || $modSettings['cal_today_updated'] != strftime('%Y%m%d', forum_time(false)))
1841                updateStats('calendar');
1842
1843        // Load the holidays for today...
1844        if (isset($modSettings['cal_today_holiday']))
1845                $holidays = unserialize($modSettings['cal_today_holiday']);
1846        // ... the birthdays for today...
1847        if (isset($modSettings['cal_today_birthday']))
1848                $bday = unserialize($modSettings['cal_today_birthday']);
1849        // ... and the events for today.
1850        if (isset($modSettings['cal_today_event']))
1851                $events = unserialize($modSettings['cal_today_event']);
1852
1853        // No events, birthdays, or holidays... don't show anything.
1854        if (empty($holidays) && empty($bday) && empty($events))
1855                return false;
1856
1857        // This shouldn't be less than one!
1858        if (empty($modSettings['cal_days_for_index']) || $modSettings['cal_days_for_index'] < 1)
1859                $days_for_index = 86400;
1860        else
1861                $days_for_index = $modSettings['cal_days_for_index'] * 86400;
1862
1863        $context['calendar_only_today'] = $modSettings['cal_days_for_index'] == 1;
1864
1865        // Get the current member time/date.
1866        $now = forum_time();
1867
1868        // This is used to show the "how-do-I-edit" help.
1869        $context['calendar_can_edit'] = allowedTo('calendar_edit_any');
1870
1871        // Holidays between now and now + days.
1872        $context['calendar_holidays'] = array();
1873        for ($i = $now; $i < $now + $days_for_index; $i += 86400)
1874        {
1875                if (isset($holidays[strftime('%Y-%m-%d', $i)]))
1876                        $context['calendar_holidays'] = array_merge($context['calendar_holidays'], $holidays[strftime('%Y-%m-%d', $i)]);
1877        }
1878
1879        // Happy Birthday, guys and gals!
1880        $context['calendar_birthdays'] = array();
1881        for ($i = $now; $i < $now + $days_for_index; $i += 86400)
1882        {
1883                if (isset($bday[strftime('%Y-%m-%d', $i)]))
1884                {
1885                        foreach ($bday[strftime('%Y-%m-%d', $i)] as $index => $dummy)
1886                                $bday[strftime('%Y-%m-%d', $i)][$index]['is_today'] = (strftime('%Y-%m-%d', $i)) == strftime('%Y-%m-%d', forum_time());
1887                        $context['calendar_birthdays'] = array_merge($context['calendar_birthdays'], $bday[strftime('%Y-%m-%d', $i)]);
1888                }
1889        }
1890
1891        $context['calendar_events'] = array();
1892        $duplicates = array();
1893        for ($i = $now; $i < $now + $days_for_index; $i += 86400)
1894        {
1895                if (isset($events[strftime('%Y-%m-%d', $i)]))
1896                        foreach ($events[strftime('%Y-%m-%d', $i)] as $ev => $event)
1897                        {
1898                                if (empty($event['topic']) || (count(array_intersect($user_info['groups'], $event['allowed_groups'])) != 0 || allowedTo('admin_forum')))
1899                                {
1900                                        if (isset($duplicates[$events[strftime('%Y-%m-%d', $i)][$ev]['topic'] . $events[strftime('%Y-%m-%d', $i)][$ev]['title']]))
1901                                        {
1902                                                unset($events[strftime('%Y-%m-%d', $i)][$ev]);
1903                                                continue;
1904                                        }
1905
1906                                        $this_event = &$events[strftime('%Y-%m-%d', $i)][$ev];
1907                                        $this_event['href'] = $this_event['topic'] == 0 ? '' : $scripturl . '?topic=' . $this_event['topic'] . '.0';
1908                                        $this_event['link'] = $this_event['topic'] == 0 ? $this_event['title'] : '<a href="' . $this_event['href'] . '">' . $this_event['title'] . '</a>';
1909                                        $this_event['modify_href'] = $scripturl . '?action=' . ($this_event['topic'] == 0 ? 'calendar;sa=post;' : 'post;msg=' . $this_event['msg'] . ';topic=' . $this_event['topic'] . '.0;calendar;') . 'eventid=' . $this_event['id'] . ';sesc=' . $sc;
1910                                        $this_event['can_edit'] = allowedTo('calendar_edit_any') || ($this_event['poster'] == $ID_MEMBER && allowedTo('calendar_edit_own'));
1911                                        $this_event['is_today'] = (strftime('%Y-%m-%d', $i)) == strftime('%Y-%m-%d', forum_time());
1912                                        $this_event['date'] = strftime('%Y-%m-%d', $i);
1913
1914                                        $duplicates[$this_event['topic'] . $this_event['title']] = true;
1915                                }
1916                                else
1917                                        unset($events[strftime('%Y-%m-%d', $i)][$ev]);
1918                        }
1919
1920                if (isset($events[strftime('%Y-%m-%d', $i)]))
1921                        $context['calendar_events'] = array_merge($context['calendar_events'], $events[strftime('%Y-%m-%d', $i)]);
1922        }
1923
1924        for ($i = 0, $n = count($context['calendar_birthdays']); $i < $n; $i++)
1925                $context['calendar_birthdays'][$i]['is_last'] = !isset($context['calendar_birthdays'][$i + 1]);
1926        for ($i = 0, $n = count($context['calendar_events']); $i < $n; $i++)
1927                $context['calendar_events'][$i]['is_last'] = !isset($context['calendar_events'][$i + 1]);
1928
1929        return !empty($context['calendar_holidays']) || !empty($context['calendar_birthdays']) || !empty($context['calendar_events']);
1930}
1931
1932// Check the passed ID_MEMBER/password.  If $is_username is true, treats $id as a username.
1933function ssi_checkPassword($id = null, $password = null, $is_username = false)
1934{
1935        global $db_prefix, $sourcedir;
1936
1937        // If $id is null, this was most likely called from a query string and should do nothing.
1938        if ($id === null)
1939                return;
1940
1941        $request = db_query("
1942                SELECT passwd, memberName, is_activated
1943                FROM {$db_prefix}members
1944                WHERE " . ($is_username ? 'memberName' : 'ID_MEMBER') . " = '$id'
1945                LIMIT 1", __FILE__, __LINE__);
1946        list ($pass, $user, $active) = mysql_fetch_row($request);
1947        mysql_free_result($request);
1948
1949        return sha1(strtolower($user) . $password) == $pass && $active == 1;
1950}
1951
1952?>
Note: See TracBrowser for help on using the repository browser.