source: branches/rsr.v5.1/web/punbb/include/functions.php @ 1

Last change on this file since 1 was 1, checked in by dj3c1t, 12 years ago

import initial

File size: 35.9 KB
Line 
1<?php
2/***********************************************************************
3
4  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)
5
6  This file is part of PunBB.
7
8  PunBB is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published
10  by the Free Software Foundation; either version 2 of the License,
11  or (at your option) any later version.
12
13  PunBB is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  MA  02111-1307  USA
22
23************************************************************************/
24
25//
26// Cookie stuff!
27//
28function check_cookie(&$pun_user)
29{
30        global $db, $pun_config, $cookie_name, $cookie_seed;
31
32        $now = time();
33        $expire = $now + 31536000;      // The cookie expires after a year
34
35        // We assume it's a guest
36        $cookie = array('user_id' => 1, 'password_hash' => 'Invité');
37
38        // If a cookie is set, we get the user_id and password hash from it
39        if (isset($_COOKIE[$cookie_name]))
40                list($cookie['user_id'], $cookie['password_hash']) = @unserialize($_COOKIE[$cookie_name]);
41
42        if ($cookie['user_id'] > 1)
43        {
44                // Check if there's a user with the user ID and password hash from the cookie
45        $_query = 'SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE u.id='.intval($cookie['user_id']);
46                $result = $db->query($_query) or error('Impossible de retrouver les informations utilisateur', __FILE__, __LINE__, $db->error());
47                $pun_user = $db->fetch_assoc($result);
48
49                // If user authorisation failed
50                if (!isset($pun_user['id']) || md5($cookie_seed.$pun_user['password']) !== $cookie['password_hash'])
51                {
52                        pun_setcookie(0, random_pass(8), $expire);
53                        set_default_user();
54
55                        return;
56                }
57
58                // Set a default language if the user selected language no longer exists
59                if (!$pun_user['language'] || !@file_exists(PUN_ROOT.'lang/'.$pun_user['language']))
60                        $pun_user['language'] = $pun_config['o_default_lang'];
61
62                // Set a default style if the user selected style no longer exists
63                if (!@file_exists(PUN_ROOT.'style/'.$pun_user['style'].'.css'))
64                        $pun_user['style'] = $pun_config['o_default_style'];
65
66                if (!$pun_user['disp_topics'])
67                        $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
68                if (!$pun_user['disp_posts'])
69                        $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
70
71                if ($pun_user['save_pass'] == '0')
72                        $expire = 0;
73
74                // Define this if you want this visit to affect the online list and the users last visit data
75                if (!defined('PUN_QUIET_VISIT'))
76                {
77                        // Update the online list
78                        if (!$pun_user['logged'])
79                                $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$now.')') or error('Impossbile d\'insérer dans la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
80                        else
81                        {
82                                // Special case: We've timed out, but no other user has browsed the forums since we timed out
83                                if ($pun_user['logged'] < ($now-$pun_config['o_timeout_visit']))
84                                {
85                                        $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Impossible de mettre à jour les données de visite de l\'utilisateur', __FILE__, __LINE__, $db->error());
86                                        $pun_user['last_visit'] = $pun_user['logged'];
87                                }
88
89                                $idle_sql = ($pun_user['idle'] == '1') ? ', idle=0' : '';
90                                $db->query('UPDATE '.$db->prefix.'online SET logged='.$now.$idle_sql.' WHERE user_id='.$pun_user['id']) or error('Impossible de mettre à jour la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
91                        }
92                }
93
94                $pun_user['is_guest'] = false;
95        }
96        else
97                set_default_user();
98}
99
100
101//
102// Fill $pun_user with default values (for guests)
103//
104function set_default_user()
105{
106        global $db, $pun_user, $pun_config;
107
108        $remote_addr = get_remote_address();
109
110        // Fetch guest user
111        $result = $db->query('SELECT u.*, g.*, o.logged FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.ident=\''.$remote_addr.'\' WHERE u.id=1') or error('Impossible de retrouver les informations d\'invité', __FILE__, __LINE__, $db->error());
112        if (!$db->num_rows($result))
113                exit('Impossible de retrouver les informations invité. La table \''.$db->prefix.'users\' doit contenir une entrée avec un id = 1 qui représente les utilisateurs anonymes.');
114
115        $pun_user = $db->fetch_assoc($result);
116
117        // Update online list
118        if (!$pun_user['logged'])
119                $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.time().')') or error('Impossbile d\'insérer dans la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
120        else
121                $db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Impossible de mettre à jour la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
122
123        $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
124        $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
125        $pun_user['timezone'] = $pun_config['o_server_timezone'];
126        $pun_user['language'] = $pun_config['o_default_lang'];
127        $pun_user['style'] = $pun_config['o_default_style'];
128        $pun_user['is_guest'] = true;
129
130}
131
132
133//
134// Set a cookie, PunBB style!
135//
136function pun_setcookie($user_id, $password_hash, $expire)
137{
138        global $cookie_name, $cookie_path, $cookie_domain, $cookie_secure, $cookie_seed;
139
140        // Enable sending of a P3P header by removing // from the following line (try this if login is failing in IE6)
141//      @header('P3P: CP="CUR ADM"');
142
143        setcookie($cookie_name, serialize(array($user_id, md5($cookie_seed.$password_hash))), $expire, $cookie_path, $cookie_domain, $cookie_secure);
144}
145
146
147//
148// Check whether the connecting user is banned (and delete any expired bans while we're at it)
149//
150function check_bans()
151{
152        global $db, $pun_config, $lang_common, $pun_user, $pun_bans;
153
154        // Admins aren't affected
155        if ($pun_user['g_id'] == PUN_ADMIN || !$pun_bans)
156                return;
157
158        // Add a dot at the end of the IP address to prevent banned address 192.168.0.5 from matching e.g. 192.168.0.50
159        $user_ip = get_remote_address().'.';
160        $bans_altered = false;
161
162        foreach ($pun_bans as $cur_ban)
163        {
164                // Has this ban expired?
165                if ($cur_ban['expire'] != '' && $cur_ban['expire'] <= time())
166                {
167                        $db->query('DELETE FROM '.$db->prefix.'bans WHERE id='.$cur_ban['id']) or error('Impossible de supprimé le bannissement expiré', __FILE__, __LINE__, $db->error());
168                        $bans_altered = true;
169                        continue;
170                }
171
172                if ($cur_ban['username'] != '' && !strcasecmp($pun_user['username'], $cur_ban['username']))
173                {
174                        $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'') or error('Impossible de supprimer de la liste des utilisateur en ligne', __FILE__, __LINE__, $db->error());
175                        message($lang_common['Ban message'].' '.(($cur_ban['expire'] != '') ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : '').(($cur_ban['message'] != '') ? $lang_common['Ban message 3'].'<br /><br /><strong>'.pun_htmlspecialchars($cur_ban['message']).'</strong><br /><br />' : '<br /><br />').$lang_common['Ban message 4'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
176                }
177
178                if ($cur_ban['ip'] != '')
179                {
180                        $cur_ban_ips = explode(' ', $cur_ban['ip']);
181
182                        for ($i = 0; $i < count($cur_ban_ips); ++$i)
183                        {
184                                $cur_ban_ips[$i] = $cur_ban_ips[$i].'.';
185
186                                if (substr($user_ip, 0, strlen($cur_ban_ips[$i])) == $cur_ban_ips[$i])
187                                {
188                                        $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'') or error('Impossible de supprimer de la liste des utilisateur en ligne', __FILE__, __LINE__, $db->error());
189                                        message($lang_common['Ban message'].' '.(($cur_ban['expire'] != '') ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : '').(($cur_ban['message'] != '') ? $lang_common['Ban message 3'].'<br /><br /><strong>'.pun_htmlspecialchars($cur_ban['message']).'</strong><br /><br />' : '<br /><br />').$lang_common['Ban message 4'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
190                                }
191                        }
192                }
193        }
194
195        // If we removed any expired bans during our run-through, we need to regenerate the bans cache
196        if ($bans_altered)
197        {
198                require_once PUN_ROOT.'include/cache.php';
199                generate_bans_cache();
200        }
201}
202
203
204//
205// Update "Users online"
206//
207function update_users_online()
208{
209        global $db, $pun_config, $pun_user;
210
211        $now = time();
212
213        // Fetch all online list entries that are older than "o_timeout_online"
214        $result = $db->query('SELECT * FROM '.$db->prefix.'online WHERE logged<'.($now-$pun_config['o_timeout_online'])) or error('Impossible de retrouver les anciennes entrées de la liste des utilisateurs', __FILE__, __LINE__, $db->error());
215        while ($cur_user = $db->fetch_assoc($result))
216        {
217                // If the entry is a guest, delete it
218                if ($cur_user['user_id'] == '1')
219                        $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($cur_user['ident']).'\'') or error('Impossible de supprimer de la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
220                else
221                {
222                        // If the entry is older than "o_timeout_visit", update last_visit for the user in question, then delete him/her from the online list
223                        if ($cur_user['logged'] < ($now-$pun_config['o_timeout_visit']))
224                        {
225                                $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$cur_user['logged'].' WHERE id='.$cur_user['user_id']) or error('Impossible de mettre à jour les données de visite de l\'utilisateur', __FILE__, __LINE__, $db->error());
226                                $db->query('DELETE FROM '.$db->prefix.'online WHERE user_id='.$cur_user['user_id']) or error('Impossible de supprimer de la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
227                        }
228                        else if ($cur_user['idle'] == '0')
229                                $db->query('UPDATE '.$db->prefix.'online SET idle=1 WHERE user_id='.$cur_user['user_id']) or error('Impossible d\'insérer à la liste des utilisateurs en ligne', __FILE__, __LINE__, $db->error());
230                }
231        }
232}
233
234
235//
236// Generate the "navigator" that appears at the top of every page
237//
238function generate_navlinks()
239{
240        global $pun_config, $lang_common, $pun_user;
241
242        // Index and Userlist should always be displayed
243        $links[] = '<li id="navindex"><a href="index.php">'.$lang_common['Index'].'</a>';
244        $links[] = '<li id="navuserlist"><a href="userlist.php">'.$lang_common['User list'].'</a>';
245
246        if ($pun_config['o_rules'] == '1')
247                $links[] = '<li id="navrules"><a href="misc.php?action=rules">'.$lang_common['Rules'].'</a>';
248
249        if ($pun_user['is_guest'])
250        {
251                if ($pun_user['g_search'] == '1')
252                        $links[] = '<li id="navsearch"><a href="search.php">'.$lang_common['Search'].'</a>';
253
254                $links[] = '<li id="navregister"><a href="register.php">'.$lang_common['Register'].'</a>';
255                $links[] = '<li id="navlogin"><a href="login.php">'.$lang_common['Login'].'</a>';
256
257                $info = $lang_common['Not logged in'];
258        }
259        else
260        {
261                if ($pun_user['g_id'] > PUN_MOD)
262                {
263                        if ($pun_user['g_search'] == '1')
264                                $links[] = '<li id="navsearch"><a href="search.php">'.$lang_common['Search'].'</a>';
265
266                        $links[] = '<li id="navprofile"><a href="profile.php?id='.$pun_user['id'].'">'.$lang_common['Profile'].'</a>';
267                        $links[] = '<li id="navlogout"><a href="login.php?action=out&amp;id='.$pun_user['id'].'">'.$lang_common['Logout'].'</a>';
268                }
269                else
270                {
271                        $links[] = '<li id="navsearch"><a href="search.php">'.$lang_common['Search'].'</a>';
272                        $links[] = '<li id="navprofile"><a href="profile.php?id='.$pun_user['id'].'">'.$lang_common['Profile'].'</a>';
273                        $links[] = '<li id="navadmin"><a href="admin_index.php">'.$lang_common['Admin'].'</a>';
274                        $links[] = '<li id="navlogout"><a href="login.php?action=out&amp;id='.$pun_user['id'].'">'.$lang_common['Logout'].'</a>';
275                }
276        }
277
278        // Are there any additional navlinks we should insert into the array before imploding it?
279        if ($pun_config['o_additional_navlinks'] != '')
280        {
281                if (preg_match_all('#([0-9]+)\s*=\s*(.*?)\n#s', $pun_config['o_additional_navlinks']."\n", $extra_links))
282                {
283                        // Insert any additional links into the $links array (at the correct index)
284                        for ($i = 0; $i < count($extra_links[1]); ++$i)
285                                array_splice($links, $extra_links[1][$i], 0, array('<li id="navextra'.($i + 1).'">'.$extra_links[2][$i]));
286                }
287        }
288
289        return '<ul>'."\n\t\t\t\t".implode($lang_common['Link separator'].'</li>'."\n\t\t\t\t", $links).'</li>'."\n\t\t\t".'</ul>';
290}
291
292
293//
294// Display the profile navigation menu
295//
296function generate_profile_menu($page = '')
297{
298        global $lang_profile, $pun_config, $pun_user, $id;
299
300?>
301<div id="profile" class="block2col">
302        <div class="blockmenu">
303                <h2><span><?php echo $lang_profile['Profile menu'] ?></span></h2>
304                <div class="box">
305                        <div class="inbox">
306                                <ul>
307                                        <li<?php if ($page == 'essentials') echo ' class="isactive"'; ?>><a href="profile.php?section=essentials&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section essentials'] ?></a></li>
308                                        <li<?php if ($page == 'personal') echo ' class="isactive"'; ?>><a href="profile.php?section=personal&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section personal'] ?></a></li>
309                                        <li<?php if ($page == 'messaging') echo ' class="isactive"'; ?>><a href="profile.php?section=messaging&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section messaging'] ?></a></li>
310                                        <li<?php if ($page == 'personality') echo ' class="isactive"'; ?>><a href="profile.php?section=personality&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section personality'] ?></a></li>
311                                        <li<?php if ($page == 'display') echo ' class="isactive"'; ?>><a href="profile.php?section=display&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section display'] ?></a></li>
312                                        <li<?php if ($page == 'privacy') echo ' class="isactive"'; ?>><a href="profile.php?section=privacy&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section privacy'] ?></a></li>
313<?php if ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_id'] == PUN_MOD && $pun_config['p_mod_ban_users'] == '1')): ?>                                        <li<?php if ($page == 'admin') echo ' class="isactive"'; ?>><a href="profile.php?section=admin&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section admin'] ?></a></li>
314<?php endif; ?>                         </ul>
315                        </div>
316                </div>
317        </div>
318<?php
319
320}
321
322
323//
324// Update posts, topics, last_post, last_post_id and last_poster for a forum (redirect topics are not included)
325//
326function update_forum($forum_id)
327{
328        global $db;
329
330        $result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE moved_to IS NULL AND forum_id='.$forum_id) or error('Impossible de retrouver le total de discussions du forum', __FILE__, __LINE__, $db->error());
331        list($num_topics, $num_posts) = $db->fetch_row($result);
332
333        $num_posts = $num_posts + $num_topics;          // $num_posts is only the sum of all replies (we have to add the topic posts)
334
335        $result = $db->query('SELECT last_post, last_post_id, last_poster FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id.' AND moved_to IS NULL ORDER BY last_post DESC LIMIT 1') or error('Impossible de retrouver last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
336        if ($db->num_rows($result))             // There are topics in the forum
337        {
338                list($last_post, $last_post_id, $last_poster) = $db->fetch_row($result);
339
340                $db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post='.$last_post.', last_post_id='.$last_post_id.', last_poster=\''.$db->escape($last_poster).'\' WHERE id='.$forum_id) or error('Impossible de mettre à jour last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
341        }
342        else    // There are no topics
343                $db->query('UPDATE '.$db->prefix.'forums SET num_topics=0, num_posts=0, last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Impossible de mettre à jour last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
344}
345
346
347//
348// Delete a topic and all of it's posts
349//
350function delete_topic($topic_id)
351{
352        global $db;
353
354        // Delete the topic and any redirect topics
355        $db->query('DELETE FROM '.$db->prefix.'topics WHERE id='.$topic_id.' OR moved_to='.$topic_id) or error('Impossible de supprimer le sujet', __FILE__, __LINE__, $db->error());
356
357        // Create a list of the post ID's in this topic
358        $post_ids = '';
359        $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Impossible de retrouver les messages', __FILE__, __LINE__, $db->error());
360        while ($row = $db->fetch_row($result))
361                $post_ids .= ($post_ids != '') ? ','.$row[0] : $row[0];
362
363        // Make sure we have a list of post ID's
364        if ($post_ids != '')
365        {
366                strip_search_index($post_ids);
367
368                // Delete posts in topic
369                $db->query('DELETE FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Impossible de supprimer les messages', __FILE__, __LINE__, $db->error());
370        }
371
372        // Delete any subscriptions for this topic
373        $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id='.$topic_id) or error('Impossible de supprimer l\'abonnement', __FILE__, __LINE__, $db->error());
374}
375
376
377//
378// Delete a single post
379//
380function delete_post($post_id, $topic_id)
381{
382        global $db;
383
384        $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id.' ORDER BY id DESC LIMIT 2') or error('Impossible de retrouver les informations du message', __FILE__, __LINE__, $db->error());
385        list($last_id, ,) = $db->fetch_row($result);
386        list($second_last_id, $second_poster, $second_posted) = $db->fetch_row($result);
387
388        // Delete the post
389        $db->query('DELETE FROM '.$db->prefix.'posts WHERE id='.$post_id) or error('Impossible de supprimer le message', __FILE__, __LINE__, $db->error());
390
391        strip_search_index($post_id);
392
393        // Count number of replies in the topic
394        $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Impossible de retrouver le total de messages pour la discussion', __FILE__, __LINE__, $db->error());
395        $num_replies = $db->result($result, 0) - 1;
396
397        // If the message we deleted is the most recent in the topic (at the end of the topic)
398        if ($last_id == $post_id)
399        {
400                // If there is a $second_last_id there is more than 1 reply to the topic
401                if (!empty($second_last_id))
402                        $db->query('UPDATE '.$db->prefix.'topics SET last_post='.$second_posted.', last_post_id='.$second_last_id.', last_poster=\''.$db->escape($second_poster).'\', num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Impossible de mettre à jour la discussion', __FILE__, __LINE__, $db->error());
403                else
404                        // We deleted the only reply, so now last_post/last_post_id/last_poster is posted/id/poster from the topic itself
405                        $db->query('UPDATE '.$db->prefix.'topics SET last_post=posted, last_post_id=id, last_poster=poster, num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Impossible de mettre à jour la discussion', __FILE__, __LINE__, $db->error());
406        }
407        else
408                // Otherwise we just decrement the reply counter
409                $db->query('UPDATE '.$db->prefix.'topics SET num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Impossible de mettre à jour la discussion', __FILE__, __LINE__, $db->error());
410}
411
412
413//
414// Replace censored words in $text
415//
416function censor_words($text)
417{
418        global $db;
419        static $search_for, $replace_with;
420
421        // If not already built in a previous call, build an array of censor words and their replacement text
422        if (!isset($search_for))
423        {
424                $result = $db->query('SELECT search_for, replace_with FROM '.$db->prefix.'censoring') or error('Impossible de retrouver la liste des mots à censurer', __FILE__, __LINE__, $db->error());
425                $num_words = $db->num_rows($result);
426
427                $search_for = array();
428                for ($i = 0; $i < $num_words; ++$i)
429                {
430                        list($search_for[$i], $replace_with[$i]) = $db->fetch_row($result);
431                        $search_for[$i] = '/\b('.str_replace('\*', '\w*?', preg_quote($search_for[$i], '/')).')\b/i';
432                }
433        }
434
435        if (!empty($search_for))
436                $text = substr(preg_replace($search_for, $replace_with, ' '.$text.' '), 1, -1);
437
438        return $text;
439}
440
441
442//
443// Determines the correct title for $user
444// $user must contain the elements 'username', 'title', 'posts', 'g_id' and 'g_user_title'
445//
446function get_title($user)
447{
448        global $db, $pun_config, $pun_bans, $lang_common;
449        static $ban_list, $pun_ranks;
450
451        // If not already built in a previous call, build an array of lowercase banned usernames
452        if (empty($ban_list))
453        {
454                $ban_list = array();
455
456                foreach ($pun_bans as $cur_ban)
457                        $ban_list[] = strtolower($cur_ban['username']);
458        }
459
460        // If not already loaded in a previous call, load the cached ranks
461        if ($pun_config['o_ranks'] == '1' && empty($pun_ranks))
462        {
463                @include PUN_ROOT.'cache/cache_ranks.php';
464                if (!defined('PUN_RANKS_LOADED'))
465                {
466                        require_once PUN_ROOT.'include/cache.php';
467                        generate_ranks_cache();
468                        require PUN_ROOT.'cache/cache_ranks.php';
469                }
470        }
471
472        // If the user has a custom title
473        if ($user['title'] != '')
474                $user_title = pun_htmlspecialchars($user['title']);
475        // If the user is banned
476        else if (in_array(strtolower($user['username']), $ban_list))
477                $user_title = $lang_common['Banned'];
478        // If the user group has a default user title
479        else if ($user['g_user_title'] != '')
480                $user_title = pun_htmlspecialchars($user['g_user_title']);
481        // If the user is a guest
482        else if ($user['g_id'] == PUN_GUEST)
483                $user_title = $lang_common['Guest'];
484        else
485        {
486                // Are there any ranks?
487                if ($pun_config['o_ranks'] == '1' && !empty($pun_ranks))
488                {
489                        @reset($pun_ranks);
490                        while (list(, $cur_rank) = @each($pun_ranks))
491                        {
492                                if (intval($user['num_posts']) >= $cur_rank['min_posts'])
493                                        $user_title = pun_htmlspecialchars($cur_rank['rank']);
494                        }
495                }
496
497                // If the user didn't "reach" any rank (or if ranks are disabled), we assign the default
498                if (!isset($user_title))
499                        $user_title = $lang_common['Member'];
500        }
501
502        return $user_title;
503}
504
505
506//
507// Generate a string with numbered links (for multipage scripts)
508//
509function paginate($num_pages, $cur_page, $link_to)
510{
511        $pages = array();
512        $link_to_all = false;
513
514        // If $cur_page == -1, we link to all pages (used in viewforum.php)
515        if ($cur_page == -1)
516        {
517                $cur_page = 1;
518                $link_to_all = true;
519        }
520
521        if ($num_pages <= 1)
522                $pages = array('<strong>1</strong>');
523        else
524        {
525                if ($cur_page > 3)
526                {
527                        $pages[] = '<a href="'.$link_to.'&amp;p=1">1</a>';
528
529                        if ($cur_page != 4)
530                                $pages[] = '&hellip;';
531                }
532
533                // Don't ask me how the following works. It just does, OK? :-)
534                for ($current = $cur_page - 2, $stop = $cur_page + 3; $current < $stop; ++$current)
535                {
536                        if ($current < 1 || $current > $num_pages)
537                                continue;
538                        else if ($current != $cur_page || $link_to_all)
539                                $pages[] = '<a href="'.$link_to.'&amp;p='.$current.'">'.$current.'</a>';
540                        else
541                                $pages[] = '<strong>'.$current.'</strong>';
542                }
543
544                if ($cur_page <= ($num_pages-3))
545                {
546                        if ($cur_page != ($num_pages-3))
547                                $pages[] = '&hellip;';
548
549                        $pages[] = '<a href="'.$link_to.'&amp;p='.$num_pages.'">'.$num_pages.'</a>';
550                }
551        }
552
553        return implode('&#160;', $pages);
554}
555
556
557//
558// Display a message
559//
560function message($message, $no_back_link = false)
561{
562
563        global $db, $lang_common, $pun_config, $pun_start, $tpl_main, $env;
564
565        if (!defined('PUN_HEADER'))
566        {
567                global $pun_user;
568
569                $page_title = pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Info'];
570                require PUN_ROOT.'header.php';
571        }
572
573?>
574
575<div id="msg" class="block">
576        <h2><span><?php echo $lang_common['Info'] ?></span></h2>
577        <div class="box">
578                <div class="inbox">
579                <p><?php echo $message ?></p>
580<?php if (!$no_back_link): ?>           <p><a href="javascript: history.go(-1)"><?php echo $lang_common['Go back'] ?></a></p>
581<?php endif; ?>         </div>
582        </div>
583</div>
584<?php
585
586        require PUN_ROOT.'footer.php';
587}
588
589
590//
591// Format a time string according to $time_format and timezones
592//
593function format_time($timestamp, $date_only = false)
594{
595        global $pun_config, $lang_common, $pun_user;
596
597        if ($timestamp == '')
598                return $lang_common['Never'];
599
600        $diff = ($pun_user['timezone'] - $pun_config['o_server_timezone']) * 3600;
601        $timestamp += $diff;
602        $now = time();
603
604        $date = date($pun_config['o_date_format'], $timestamp);
605        $today = date($pun_config['o_date_format'], $now+$diff);
606        $yesterday = date($pun_config['o_date_format'], $now+$diff-86400);
607
608        if ($date == $today)
609                $date = $lang_common['Today'];
610        else if ($date == $yesterday)
611                $date = $lang_common['Yesterday'];
612
613        if (!$date_only)
614                return $date.' '.date($pun_config['o_time_format'], $timestamp);
615        else
616                return $date;
617}
618
619
620//
621// If we are running pre PHP 4.3.0, we add our own implementation of file_get_contents
622//
623if (!function_exists('file_get_contents'))
624{
625        function file_get_contents($filename, $use_include_path = 0)
626        {
627                $data = '';
628
629                if ($fh = fopen($filename, 'rb', $use_include_path))
630                {
631                        $data = fread($fh, filesize($filename));
632                        fclose($fh);
633                }
634
635                return $data;
636        }
637}
638
639
640//
641// Make sure that HTTP_REFERER matches $pun_config['o_base_url']/$script
642//
643function confirm_referrer($script)
644{
645        global $pun_config, $lang_common;
646
647        if (!preg_match('#^'.preg_quote(str_replace('www.', '', $pun_config['o_base_url']).'/'.$script, '#').'#i', str_replace('www.', '', (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''))))
648                message($lang_common['Bad referrer']);
649}
650
651
652//
653// Generate a random password of length $len
654//
655function random_pass($len)
656{
657        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
658
659        $password = '';
660        for ($i = 0; $i < $len; ++$i)
661                $password .= substr($chars, (mt_rand() % strlen($chars)), 1);
662
663        return $password;
664}
665
666
667//
668// Compute a hash of $str
669// Uses sha1() if available. If not, SHA1 through mhash() if available. If not, fall back on md5().
670//
671function pun_hash($str)
672{
673        if (function_exists('sha1'))    // Only in PHP 4.3.0+
674                return sha1($str);
675        else if (function_exists('mhash'))      // Only if Mhash library is loaded
676                return bin2hex(mhash(MHASH_SHA1, $str));
677        else
678                return md5($str);
679}
680
681
682//
683// Try to determine the correct remote IP-address
684//
685function get_remote_address()
686{
687        return $_SERVER['REMOTE_ADDR'];
688}
689
690
691//
692// Equivalent to htmlspecialchars(), but allows &#[0-9]+ (for unicode)
693//
694function pun_htmlspecialchars($str)
695{
696        $str = preg_replace('/&(?!#[0-9]+;)/s', '&amp;', $str);
697        $str = str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $str);
698
699        return $str;
700}
701
702
703//
704// Equivalent to strlen(), but counts &#[0-9]+ as one character (for unicode)
705//
706function pun_strlen($str)
707{
708        return strlen(preg_replace('/&#([0-9]+);/', '!', $str));
709}
710
711
712//
713// Convert \r\n and \r to \n
714//
715function pun_linebreaks($str)
716{
717        return str_replace("\r", "\n", str_replace("\r\n", "\n", $str));
718}
719
720
721//
722// A more aggressive version of trim()
723//
724function pun_trim($str)
725{
726        global $lang_common;
727
728        if (strpos($lang_common['lang_encoding'], '8859') !== false)
729        {
730                $fishy_chars = array(chr(0x81), chr(0x8D), chr(0x8F), chr(0x90), chr(0x9D), chr(0xA0));
731                return trim(str_replace($fishy_chars, ' ', $str));
732        }
733        else
734                return trim($str);
735}
736
737
738//
739// Display a message when board is in maintenance mode
740//
741function maintenance_message()
742{
743        global $db, $pun_config, $lang_common, $pun_user;
744
745        // Deal with newlines, tabs and multiple spaces
746        $pattern = array("\t", '  ', '  ');
747        $replace = array('&#160; &#160; ', '&#160; ', ' &#160;');
748        $message = str_replace($pattern, $replace, $pun_config['o_maintenance_message']);
749
750
751        // Load the maintenance template
752        $tpl_maint = trim(file_get_contents(PUN_ROOT.'include/template/maintenance.tpl'));
753
754
755        // START SUBST - <pun_content_direction>
756        $tpl_maint = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_maint);
757        // END SUBST - <pun_content_direction>
758
759
760        // START SUBST - <pun_char_encoding>
761        $tpl_maint = str_replace('<pun_char_encoding>', $lang_common['lang_encoding'], $tpl_maint);
762        // END SUBST - <pun_char_encoding>
763
764
765        // START SUBST - <pun_head>
766        ob_start();
767
768?>
769<title><?php echo pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Maintenance'] ?></title>
770<link rel="stylesheet" type="text/css" href="style/<?php echo $pun_user['style'].'.css' ?>" />
771<?php
772
773        $tpl_temp = trim(ob_get_contents());
774        $tpl_maint = str_replace('<pun_head>', $tpl_temp, $tpl_maint);
775        ob_end_clean();
776        // END SUBST - <pun_head>
777
778
779        // START SUBST - <pun_maint_heading>
780        $tpl_maint = str_replace('<pun_maint_heading>', $lang_common['Maintenance'], $tpl_maint);
781        // END SUBST - <pun_maint_heading>
782
783
784        // START SUBST - <pun_maint_message>
785        $tpl_maint = str_replace('<pun_maint_message>', $message, $tpl_maint);
786        // END SUBST - <pun_maint_message>
787
788
789        // End the transaction
790        $db->end_transaction();
791
792
793        // START SUBST - <pun_include "*">
794        while (preg_match('#<pun_include "([^/\\\\]*?)">#', $tpl_maint, $cur_include))
795        {
796                if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1]))
797                   error('Impossible de procéder à l\'inclusion utilisateur &lt;pun_include "'.htmlspecialchars($cur_include[1]).'"&gt; depuis le template main.tpl. Il n\'y a pas de fichier dans le répertoire /include/user/');
798
799                ob_start();
800                include PUN_ROOT.'include/user/'.$cur_include[1];
801                $tpl_temp = ob_get_contents();
802                $tpl_redir = str_replace($cur_include[0], $tpl_temp, $tpl_redir);
803            ob_end_clean();
804        }
805        // END SUBST - <pun_include "*">
806
807
808        // Close the db connection (and free up any result data)
809        $db->close();
810
811        exit($tpl_maint);
812}
813
814
815//
816// Display $message and redirect user to $destination_url
817//
818function redirect($destination_url, $message)
819{
820        global $db, $pun_config, $lang_common, $pun_user;
821
822        if ($destination_url == '')
823                $destination_url = 'index.php';
824
825        // If the delay is 0 seconds, we might as well skip the redirect all together
826        if ($pun_config['o_redirect_delay'] == '0')
827                header('Location: '.str_replace('&amp;', '&', $destination_url));
828
829
830        // Load the redirect template
831        $tpl_redir = trim(file_get_contents(PUN_ROOT.'include/template/redirect.tpl'));
832
833
834        // START SUBST - <pun_content_direction>
835        $tpl_redir = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_redir);
836        // END SUBST - <pun_content_direction>
837
838
839        // START SUBST - <pun_char_encoding>
840        $tpl_redir = str_replace('<pun_char_encoding>', $lang_common['lang_encoding'], $tpl_redir);
841        // END SUBST - <pun_char_encoding>
842
843
844        // START SUBST - <pun_head>
845        ob_start();
846
847?>
848<meta http-equiv="refresh" content="<?php echo $pun_config['o_redirect_delay'] ?>;URL=<?php echo str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $destination_url) ?>" />
849<title><?php echo pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Redirecting'] ?></title>
850<link rel="stylesheet" type="text/css" href="style/<?php echo $pun_user['style'].'.css' ?>" />
851<?php
852
853        $tpl_temp = trim(ob_get_contents());
854        $tpl_redir = str_replace('<pun_head>', $tpl_temp, $tpl_redir);
855        ob_end_clean();
856        // END SUBST - <pun_head>
857
858
859        // START SUBST - <pun_redir_heading>
860        $tpl_redir = str_replace('<pun_redir_heading>', $lang_common['Redirecting'], $tpl_redir);
861        // END SUBST - <pun_redir_heading>
862
863
864        // START SUBST - <pun_redir_text>
865        $tpl_temp = $message.'<br /><br />'.'<a href="'.$destination_url.'">'.$lang_common['Click redirect'].'</a>';
866        $tpl_redir = str_replace('<pun_redir_text>', $tpl_temp, $tpl_redir);
867        // END SUBST - <pun_redir_text>
868
869
870        // START SUBST - <pun_footer>
871        ob_start();
872
873        // End the transaction
874        $db->end_transaction();
875
876        // Display executed queries (if enabled)
877        if (defined('PUN_SHOW_QUERIES'))
878                display_saved_queries();
879
880        $tpl_temp = trim(ob_get_contents());
881        $tpl_redir = str_replace('<pun_footer>', $tpl_temp, $tpl_redir);
882        ob_end_clean();
883        // END SUBST - <pun_footer>
884
885
886        // START SUBST - <pun_include "*">
887        while (preg_match('<pun_include "(.*?)">', $tpl_redir, $cur_include))
888        {
889                ob_start();
890                include PUN_ROOT.$cur_include[1];
891                $tpl_temp = ob_get_contents();
892                $tpl_redir = str_replace('<'.$cur_include[0].'>', $tpl_temp, $tpl_redir);
893            ob_end_clean();
894        }
895        // END SUBST - <pun_include "*">
896
897
898        // Close the db connection (and free up any result data)
899        $db->close();
900
901        exit($tpl_redir);
902}
903
904
905//
906// Display a simple error message
907//
908function error($message, $file, $line, $db_error = false)
909{
910        global $pun_config;
911
912        // Set a default title if the script failed before $pun_config could be populated
913        if (empty($pun_config))
914                $pun_config['o_board_title'] = 'PunBB';
915
916        // Empty output buffer and stop buffering
917        @ob_end_clean();
918
919        // "Restart" output buffering if we are using ob_gzhandler (since the gzip header is already sent)
920        if (!empty($pun_config['o_gzip']) && extension_loaded('zlib') && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false || strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== false))
921                ob_start('ob_gzhandler');
922
923?>
924<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
925<html dir="ltr">
926<head>
927<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $lang_common["lang_encoding"] ?>" />
928<title><?php echo pun_htmlspecialchars($pun_config['o_board_title']) ?> / Error</title>
929<style type="text/css">
930<!--
931BODY {MARGIN: 10% 20% auto 20%; font: 10px Verdana, Arial, Helvetica, sans-serif}
932#errorbox {BORDER: 1px solid #B84623}
933H2 {MARGIN: 0; COLOR: #FFFFFF; BACKGROUND-COLOR: #B84623; FONT-SIZE: 1.1em; PADDING: 5px 4px}
934#errorbox DIV {PADDING: 6px 5px; BACKGROUND-COLOR: #F1F1F1}
935-->
936</style>
937</head>
938<body>
939
940<div id="errorbox">
941        <h2>Une erreur s'est produite</h2>
942        <div>
943<?php
944
945        if (defined('PUN_DEBUG'))
946        {
947                echo "\t\t".'<strong>Fichier :</strong> '.$file.'<br />'."\n\t\t".'<strong>Ligne :</strong> '.$line.'<br /><br />'."\n\t\t".'<strong>PunBB a rapporté :</strong> '.$message."\n";
948
949                if ($db_error)
950                {
951                        echo "\t\t".'<br /><br /><strong>La base de données a rapporté :</strong> '.pun_htmlspecialchars($db_error['error_msg']).(($db_error['error_no']) ? ' (Errno: '.$db_error['error_no'].')' : '')."\n";
952
953                        if ($db_error['error_sql'] != '')
954                                echo "\t\t".'<br /><br /><strong>Requête échouée :</strong> '.pun_htmlspecialchars($db_error['error_sql'])."\n";
955                }
956        }
957        else
958                echo "\t\t".'Erreur : <strong>'.$message.'.</strong>'."\n";
959
960?>
961        </div>
962</div>
963
964</body>
965</html>
966<?php
967
968        // If a database connection was established (before this error) we close it
969        if ($db_error)
970                $GLOBALS['db']->close();
971
972        exit;
973}
974
975// DEBUG FUNCTIONS BELOW
976
977//
978// Display executed queries (if enabled)
979//
980function display_saved_queries()
981{
982        global $db, $lang_common;
983
984        // Get the queries so that we can print them out
985        $saved_queries = $db->get_saved_queries();
986
987?>
988
989<div id="debug" class="blocktable">
990        <h2><span><?php echo $lang_common['Debug table'] ?></span></h2>
991        <div class="box">
992                <div class="inbox">
993                        <table cellspacing="0">
994                        <thead>
995                                <tr>
996                                        <th class="tcl" scope="col">Temps (s)</th>
997                                        <th class="tcr" scope="col">Requête</th>
998                                </tr>
999                        </thead>
1000                        <tbody>
1001<?php
1002
1003        $query_time_total = 0.0;
1004        while (list(, $cur_query) = @each($saved_queries))
1005        {
1006                $query_time_total += $cur_query[1];
1007
1008?>
1009                                <tr>
1010                                        <td class="tcl"><?php echo ($cur_query[1] != 0) ? $cur_query[1] : '&#160;' ?></td>
1011                                        <td class="tcr"><?php echo pun_htmlspecialchars($cur_query[0]) ?></td>
1012                                </tr>
1013<?php
1014
1015        }
1016
1017?>
1018                                <tr>
1019                                        <td class="tcl" colspan="2">Temps total requête : <?php echo $query_time_total ?> s</td>
1020                                </tr>
1021                        </tbody>
1022                        </table>
1023                </div>
1024        </div>
1025</div>
1026<?php
1027
1028}
1029
1030
1031//
1032// Unset any variables instantiated as a result of register_globals being enabled
1033//
1034function unregister_globals()
1035{
1036        // Prevent script.php?GLOBALS[foo]=bar
1037        if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']))
1038                exit('I\'ll have a steak sandwich and... a steak sandwich.');
1039       
1040        // Variables that shouldn't be unset
1041        $no_unset = array('GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
1042       
1043        // Remove elements in $GLOBALS that are present in any of the superglobals
1044        $input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());
1045        foreach ($input as $k => $v)
1046        {
1047                if (!in_array($k, $no_unset) && isset($GLOBALS[$k]))
1048                        unset($GLOBALS[$k]);
1049        }
1050}
1051
1052
1053//
1054// Dump contents of variable(s)
1055//
1056function dump()
1057{
1058        echo '<pre>';
1059
1060        $num_args = func_num_args();
1061
1062        for ($i = 0; $i < $num_args; ++$i)
1063        {
1064                print_r(func_get_arg($i));
1065                echo "\n\n";
1066        }
1067
1068        echo '</pre>';
1069        exit;
1070}
Note: See TracBrowser for help on using the repository browser.