PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/other/punbb-modified-forum/include/functions.php

https://bitbucket.org/Balancer/projects-balancer
PHP | 1090 lines | 668 code | 223 blank | 199 comment | 159 complexity | 22f298b3c083300f371e91da4824991d MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /***********************************************************************
  3. Copyright (C) 2002-2005 Rickard Andersson (rickard@punbb.org)
  4. This file is part of PunBB.
  5. PunBB is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published
  7. by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. PunBB is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  16. MA 02111-1307 USA
  17. ************************************************************************/
  18. require_once('inc/browsers.php');
  19. require_once('bors-end.php');
  20. //
  21. // Cookie stuff!
  22. //
  23. function check_cookie(&$pun_user)
  24. {
  25. global $db, $pun_config, $cookie_seed;
  26. $now = time();
  27. $expire = $now + 31536000; // The cookie expires after a year
  28. // We assume it's a guest
  29. $cookie = array('user_id' => 1, 'password_hash' => 'Guest');
  30. require_once('obsolete/users.php');
  31. $me = new User();
  32. // echo "Check cookie: me=".($me->data('id'));
  33. if($me->data('id') > 1)
  34. {
  35. // Check if there's a user with the user ID and password hash from the cookie
  36. $q = "SELECT u.*, g.*, o.logged, o.idle
  37. FROM {$db->prefix}users AS u
  38. INNER JOIN {$db->prefix}groups AS g ON u.group_id=g.g_id
  39. LEFT JOIN {$db->prefix}online AS o ON o.user_id=u.id
  40. WHERE u.id=".intval($me->data('id'));
  41. $result = $db->query($q)
  42. or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
  43. $pun_user = $db->fetch_assoc($result);
  44. if(!$pun_user)
  45. {
  46. set_default_user();
  47. return;
  48. }
  49. // Set a default language if the user selected language no longer exists
  50. if (!@file_exists(PUN_ROOT."lang/{$pun_user['language']}/common.php"))
  51. $pun_user['language'] = $pun_config['o_default_lang'];
  52. // Set a default style if the user selected style no longer exists
  53. if (!@file_exists(PUN_ROOT.'style/'.$pun_user['style'].'.css'))
  54. $pun_user['style'] = $pun_config['o_default_style'];
  55. if (!$pun_user['disp_topics'])
  56. $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
  57. if (!$pun_user['disp_posts'])
  58. $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
  59. if ($pun_user['save_pass'] == '0')
  60. $expire = 0;
  61. list($os, $browser) = get_browser_info($_SERVER['HTTP_USER_AGENT']);
  62. // Define this if you want this visit to affect the online list and the users last visit data
  63. if (!defined('PUN_QUIET_VISIT'))
  64. {
  65. // Update the online list
  66. if (!$pun_user['logged'])
  67. $db->query("INSERT INTO {$db->prefix}online (user_id, ident, logged, useragent, os, browser) VALUES ('{$pun_user['id']}', '".$db->escape($pun_user['username'])."', '$now', '".addslashes($_SERVER['HTTP_USER_AGENT'])."', '$os', '$browser')")
  68. or error('Unable to insert into online list [77]: '.$pun_user['id'], __FILE__, __LINE__, $db->error());
  69. else
  70. {
  71. // Special case: We've timed out, but no other user has browsed the forums since we timed out
  72. if ($pun_user['logged'] < ($now-$pun_config['o_timeout_visit']))
  73. {
  74. $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id'])
  75. or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
  76. $pun_user['last_visit'] = $pun_user['logged'];
  77. }
  78. $idle_sql = ($pun_user['idle'] == '1') ? ', idle=0' : '';
  79. $db->query('UPDATE '.$db->prefix.'online SET logged='.$now.$idle_sql.' WHERE user_id='.$pun_user['id']) or error('Unable to update online list', __FILE__, __LINE__, $db->error());
  80. }
  81. }
  82. $pun_user['is_guest'] = false;
  83. }
  84. else
  85. set_default_user();
  86. }
  87. //
  88. // Fill $pun_user with default values (for guests)
  89. //
  90. function set_default_user()
  91. {
  92. global $db, $pun_user, $pun_config;
  93. $remote_addr = get_remote_address();
  94. // Fetch guest user
  95. $result = $db->query("
  96. SELECT u.*, g.*, o.logged
  97. FROM {$db->prefix}users AS u
  98. INNER JOIN {$db->prefix}groups AS g ON u.group_id=g.g_id
  99. LEFT JOIN {$db->prefix}online AS o ON o.ident='{$remote_addr}'
  100. WHERE u.id=1") or error('Unable to fetch guest information for '.$remote_addr, __FILE__, __LINE__, $db->error());
  101. if (!$db->num_rows($result))
  102. pun_exit('Unable to fetch guest information for '.$remote_addr.'. The table \''.$db->prefix.'users\' must contain an entry with id = 1 that represents anonymous users.');
  103. $pun_user = $db->fetch_assoc($result);
  104. list($os, $browser) = get_browser_info($_SERVER['HTTP_USER_AGENT'], false);
  105. // Update online list
  106. if (!$pun_user['logged'])
  107. $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged, os, browser, useragent) VALUES(1, \''.$db->escape($remote_addr).'\', '.time().", '$os', '$browser', '".addslashes($_SERVER['HTTP_USER_AGENT'])."')")
  108. or error('Unable to insert into online list [117]', __FILE__, __LINE__, $db->error());
  109. else
  110. $db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Unable to update online list', __FILE__, __LINE__, $db->error());
  111. $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
  112. $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
  113. $pun_user['timezone'] = $pun_config['o_server_timezone'];
  114. $pun_user['language'] = $pun_config['o_default_lang'];
  115. $pun_user['style'] = $pun_config['o_default_style'];
  116. $pun_user['is_guest'] = true;
  117. }
  118. //
  119. // Check whether the connecting user is banned (and delete any expired bans while we're at it)
  120. //
  121. function check_bans()
  122. {
  123. global $db, $pun_config, $lang_common, $pun_user, $pun_bans;
  124. // Admins aren't affected
  125. if ($pun_user['g_id'] == PUN_ADMIN || !$pun_bans)
  126. return;
  127. // 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
  128. $user_ip = get_remote_address().'.';
  129. $bans_altered = false;
  130. foreach ($pun_bans as $cur_ban)
  131. {
  132. // Has this ban expired?
  133. if ($cur_ban['expire'] != '' && $cur_ban['expire'] <= time())
  134. {
  135. $db->query('DELETE FROM '.$db->prefix.'bans WHERE id='.$cur_ban['id']) or error('Unable to delete expired ban', __FILE__, __LINE__, $db->error());
  136. $bans_altered = true;
  137. continue;
  138. }
  139. if ($cur_ban['username'] != '' && !strcasecmp($pun_user['username'], $cur_ban['username']))
  140. {
  141. $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'')
  142. or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
  143. 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);
  144. debug_hidden_log('__ban_test', 'ban1');
  145. }
  146. if ($cur_ban['ip'] != '')
  147. {
  148. $cur_ban_ips = explode(' ', $cur_ban['ip']);
  149. for ($i = 0; $i < count($cur_ban_ips); ++$i)
  150. {
  151. $cur_ban_ips[$i] = $cur_ban_ips[$i].'.';
  152. if (substr($user_ip, 0, strlen($cur_ban_ips[$i])) == $cur_ban_ips[$i])
  153. {
  154. $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'')
  155. or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
  156. 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);
  157. debug_hidden_log('__ban_test', 'ban2');
  158. }
  159. }
  160. }
  161. }
  162. // If we removed any expired bans during our run-through, we need to regenerate the bans cache
  163. if ($bans_altered)
  164. {
  165. require_once PUN_ROOT.'include/cache.php';
  166. generate_bans_cache();
  167. }
  168. }
  169. //
  170. // Generate the "navigator" that appears at the top of every page
  171. //
  172. function generate_navlinks()
  173. {
  174. global $pun_config, $lang_common, $pun_user;
  175. // Index and Userlist should always be displayed
  176. $links[] = "<li id=\"navindex\"><a href=\"{$pun_config['root_uri']}/index.php\">".$lang_common['Index'].'</a>';
  177. $links[] = "<li id=\"navuserlist\"><a href=\"{$pun_config['root_uri']}/userlist.php\">".$lang_common['User list'].'</a>';
  178. if ($pun_config['o_rules'] == '1')
  179. $links[] = "<li id=\"navrules\"><a href=\"{$pun_config['root_uri']}/misc.php?action=rules\">".$lang_common['Rules'].'</a>';
  180. $search_url = 'http://www.balancer.ru/tools/search/';
  181. if(!empty($GLOBALS['forum_id']))
  182. $search_url .= '?f%5B%5D='.intval($GLOBALS['forum_id']);
  183. if ($pun_user['is_guest'])
  184. {
  185. if ($pun_user['g_search'] == '1')
  186. $links[] = "<li id=\"navsearch\"><a href=\"{$search_url}\">".$lang_common['Search'].'</a>';
  187. $links[] = "<li id=\"navregister\"><a href=\"{$pun_config['root_uri']}/register.php\">".$lang_common['Register'].'</a>';
  188. $links[] = "<li id=\"navlogin\"><a href=\"{$pun_config['root_uri']}/login.php\">".$lang_common['Login'].'</a>';
  189. $info = $lang_common['Not logged in'];
  190. }
  191. else
  192. {
  193. if ($pun_user['g_id'] > PUN_MOD)
  194. {
  195. if ($pun_user['g_search'] == '1')
  196. $links[] = "<li id=\"navsearch\"><a href=\"{$search_url}\">".$lang_common['Search'].'</a>';
  197. $links[] = "<li id=\"navprofile\"><a href=\"{$pun_config['root_uri']}/profile.php?id={$pun_user['id']}\">".$lang_common['Profile'].'</a>';
  198. $links[] = "<li id=\"navlogout\"><a href=\"{$pun_config['root_uri']}/login.php?action=out&amp;id={$pun_user['id']}\">".$lang_common['Logout'].'</a>';
  199. }
  200. else
  201. {
  202. $links[] = "<li id=\"navsearch\"><a href=\"{$search_url}\">".$lang_common['Search'].'</a>';
  203. $links[] = "<li id=\"navprofile\"><a href=\"{$pun_config['root_uri']}/profile.php?id={$pun_user['id']}\">".$lang_common['Profile'].'</a>';
  204. $links[] = "<li id=\"navadmin\"><a href=\"{$pun_config['root_uri']}/admin_index.php\">".$lang_common['Admin'].'</a>';
  205. $links[] = "<li id=\"navlogout\"><a href=\"{$pun_config['root_uri']}/login.php?action=out&amp;id={$pun_user['id']}\">".$lang_common['Logout'].'</a>';
  206. }
  207. }
  208. // Are there any additional navlinks we should insert into the array before imploding it?
  209. if ($pun_config['o_additional_navlinks'] != '')
  210. {
  211. if (preg_match_all('#([0-9]+)\s*=\s*(.*?)\n#s', $pun_config['o_additional_navlinks']."\n", $extra_links))
  212. {
  213. // Insert any additional links into the $links array (at the correct index)
  214. for ($i = 0; $i < count($extra_links[1]); ++$i)
  215. array_splice($links, $extra_links[1][$i], 0, array('<li id="navextra'.($i + 1).'">'.$extra_links[2][$i]));
  216. }
  217. }
  218. $ret = '<ul>'."\n\t\t\t\t".implode($lang_common['Link separator'].'</li>'."\n\t\t\t\t", $links).'</li>'."\n\t\t\t".'</ul>';
  219. $ret .= "<ul><li><b>Группы форумов:</b></li>";
  220. $ret .= "<li><a href=\"http://www.balancer.ru/forum/\">Все вместе</a></li>";
  221. $db = new driver_mysql(config('punbb.database', 'AB_FORUMS'));
  222. foreach($db->get_array("SELECT * FROM categories WHERE base_uri != '' ORDER BY disp_position") as $c)
  223. $ret .= "<li><a href=\"{$c['base_uri']}\">{$c['cat_name']}</a></li>";
  224. $db->close();
  225. return "$ret</ul>";
  226. }
  227. //
  228. // Display the profile navigation menu
  229. //
  230. function generate_profile_menu($page = '')
  231. {
  232. global $lang_profile, $pun_config, $pun_user, $id;
  233. ?>
  234. <div id="profile" class="block2col">
  235. <div class="blockmenu">
  236. <h2><span><?php echo $lang_profile['Profile menu'] ?></span></h2>
  237. <div class="box">
  238. <div class="inbox">
  239. <ul>
  240. <li<?php if ($page == 'essentials') echo ' class="isactive"'; ?>><a href="<?php echo $pun_config['root_uri'];?>/profile.php?section=essentials&amp;id=<?php echo $id;/*"*/?>"><?php echo $lang_profile['Section essentials'] ?></a></li>
  241. <li<?php if ($page == 'personal') echo ' class="isactive"'; ?>><a href="<?php echo $pun_config['root_uri'];?>/profile.php?section=personal&amp;id=<?php echo $id;/*"*/?>"><?php echo $lang_profile['Section personal'] ?></a></li>
  242. <li<?php if ($page == 'messaging') echo ' class="isactive"'; ?>><a href="<?php echo $pun_config['root_uri'];?>/profile.php?section=messaging&amp;id=<?php echo $id;/*"*/?>"><?php echo $lang_profile['Section messaging'] ?></a></li>
  243. <li<?php if ($page == 'personality') echo ' class="isactive"'; ?>><a href="<?php echo $pun_config['root_uri'];?>/profile.php?section=personality&amp;id=<?php echo $id;/*"*/?>"><?php echo $lang_profile['Section personality'] ?></a></li>
  244. <li<?php if ($page == 'display') echo ' class="isactive"'; ?>><a href="<?php echo $pun_config['root_uri'];?>/profile.php?section=display&amp;id=<?php echo $id;/*"*/?>"><?php echo $lang_profile['Section display'] ?></a></li>
  245. <li<?php if ($page == 'privacy') echo ' class="isactive"'; ?>><a href="<?php echo $pun_config['root_uri'];?>/profile.php?section=privacy&amp;id=<?php echo $id;/*"*/?>"><?php echo $lang_profile['Section privacy'] ?></a></li>
  246. <?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="<?php echo $pun_config['root_uri'];?>/profile.php?section=admin&amp;id=<?php echo $id ?>"><?php echo $lang_profile['Section admin'] ?></a></li>
  247. <?php endif;/*"*/?> </ul>
  248. </div>
  249. </div>
  250. </div>
  251. <?php
  252. }
  253. //
  254. // Update posts, topics, last_post, last_post_id and last_poster for a forum (redirect topics are not included)
  255. //
  256. function update_forum($forum_id)
  257. {
  258. global $db;
  259. $result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE moved_to IS NULL AND forum_id='.$forum_id)
  260. or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
  261. list($num_topics, $num_posts) = $db->fetch_row($result);
  262. $num_posts = $num_posts + $num_topics; // $num_posts is only the sum of all replies (we have to add the topic posts)
  263. $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('Unable to fetch last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
  264. if ($db->num_rows($result)) // There are topics in the forum
  265. {
  266. list($last_post, $last_post_id, $last_poster) = $db->fetch_row($result);
  267. $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('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
  268. }
  269. else // There are no topics
  270. $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('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
  271. }
  272. //
  273. // Delete a topic and all of it's posts
  274. //
  275. function delete_topic($topic_id)
  276. {
  277. global $db;
  278. // Delete the topic and any redirect topics
  279. $db->query('DELETE FROM '.$db->prefix.'topics WHERE id='.$topic_id.' OR moved_to='.$topic_id) or error('Unable to delete topic', __FILE__, __LINE__, $db->error());
  280. // Create a list of the post ID's in this topic
  281. $post_ids = '';
  282. $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
  283. while ($row = $db->fetch_row($result))
  284. $post_ids .= ($post_ids != '') ? ','.$row[0] : $row[0];
  285. // Make sure we have a list of post ID's
  286. if ($post_ids != '')
  287. {
  288. strip_search_index($post_ids);
  289. // Delete posts in topic
  290. $cms_db = new driver_mysql('AB_FORUMS');
  291. $posts = join(",", $cms_db->get_array("SELECT id FROM posts WHERE topic_id=$topic_id"));
  292. $db->query('DELETE FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to delete posts', __FILE__, __LINE__, $db->error());
  293. // $db->query("DELETE FROM {$db->prefix}messages WHERE id IN ($posts)")
  294. // or error('Unable to delete posts', __FILE__, __LINE__, $db->error());
  295. $cms_db->close();
  296. }
  297. // Delete any subscriptions for this topic
  298. $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id='.$topic_id) or error('Unable to delete subscriptions', __FILE__, __LINE__, $db->error());
  299. }
  300. //
  301. // Delete a single post
  302. //
  303. function delete_post($post_id, $topic_id)
  304. {
  305. global $db;
  306. $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id.' ORDER BY id DESC LIMIT 2') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
  307. list($last_id, ,) = $db->fetch_row($result);
  308. list($second_last_id, $second_poster, $second_posted) = $db->fetch_row($result);
  309. // Delete the post
  310. $db->query('DELETE FROM '.$db->prefix.'posts WHERE id='.$post_id) or error('Unable to delete post', __FILE__, __LINE__, $db->error());
  311. // $db->query('DELETE FROM '.$db->prefix.'messages WHERE id='.$post_id) or error('Unable to delete post', __FILE__, __LINE__, $db->error());
  312. strip_search_index($post_id);
  313. // Count number of replies in the topic
  314. $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to fetch post count for topic', __FILE__, __LINE__, $db->error());
  315. $num_replies = $db->result($result, 0) - 1;
  316. // If the message we deleted is the most recent in the topic (at the end of the topic)
  317. if ($last_id == $post_id)
  318. {
  319. // If there is a $second_last_id there is more than 1 reply to the topic
  320. if (!empty($second_last_id))
  321. $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('Unable to update topic', __FILE__, __LINE__, $db->error());
  322. else
  323. // We deleted the only reply, so now last_post/last_post_id/last_poster is posted/id/poster from the topic itself
  324. $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('Unable to update topic', __FILE__, __LINE__, $db->error());
  325. }
  326. else
  327. // Otherwise we just decrement the reply counter
  328. $db->query('UPDATE '.$db->prefix.'topics SET num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
  329. $topic = object_load('balancer_board_topic', $topic_id);
  330. $topic->recalculate();
  331. }
  332. //
  333. // Replace censored words in $text
  334. //
  335. function censor_words($text)
  336. {
  337. global $db;
  338. static $search_for, $replace_with;
  339. // If not already built in a previous call, build an array of censor words and their replacement text
  340. if (!isset($search_for))
  341. {
  342. $result = $db->query('SELECT search_for, replace_with FROM '.$db->prefix.'censoring') or error('Unable to fetch censor word list', __FILE__, __LINE__, $db->error());
  343. $num_words = $db->num_rows($result);
  344. $search_for = array();
  345. for ($i = 0; $i < $num_words; ++$i)
  346. {
  347. list($search_for[$i], $replace_with[$i]) = $db->fetch_row($result);
  348. $search_for[$i] = '/\b('.str_replace('\*', '\w*?', preg_quote($search_for[$i], '/')).')\b/i';
  349. }
  350. }
  351. if (!empty($search_for))
  352. $text = substr(preg_replace($search_for, $replace_with, ' '.$text.' '), 1, -1);
  353. return $text;
  354. }
  355. //
  356. // Determines the correct title for $user
  357. // $user must contain the elements 'username', 'title', 'posts', 'g_id' and 'g_user_title'
  358. //
  359. function get_title($user)
  360. {
  361. global $db, $pun_config, $pun_bans, $lang_common;
  362. static $ban_list, $pun_ranks;
  363. // If not already built in a previous call, build an array of lowercase banned usernames
  364. if (empty($ban_list))
  365. {
  366. $ban_list = array();
  367. if(!empty($pun_bans))
  368. foreach ($pun_bans as $cur_ban)
  369. $ban_list[] = strtolower($cur_ban['username']);
  370. }
  371. // If not already loaded in a previous call, load the cached ranks
  372. if ($pun_config['o_ranks'] == '1' && empty($pun_ranks))
  373. {
  374. @include PUN_ROOT.'cache/cache_ranks.php';
  375. if (!defined('PUN_RANKS_LOADED'))
  376. {
  377. require_once PUN_ROOT.'include/cache.php';
  378. generate_ranks_cache();
  379. require PUN_ROOT.'cache/cache_ranks.php';
  380. }
  381. }
  382. if(empty($GLOBALS['bors_data']['cache']['punbb_group'][$user['group_id']]))
  383. {
  384. $cdb = new DataBase('AB_FORUMS');
  385. $group = $cdb->get("SELECT * FROM groups WHERE g_id = ".intval($user['group_id']));
  386. $GLOBALS['bors_data']['cache']['punbb_group'][$user['group_id']] = serialize($group);
  387. // $cdb->close();
  388. }
  389. else
  390. $group = unserialize($GLOBALS['bors_data']['cache']['punbb_group'][$user['group_id']]);
  391. // If the user has a custom title
  392. if ($user['title'] != '')
  393. $user_title = pun_htmlspecialchars($user['title']);
  394. // If the user is banned
  395. else if (in_array(strtolower($user['username']), $ban_list))
  396. $user_title = $lang_common['Banned'];
  397. // If the user group has a default user title
  398. else if ($group['g_user_title'] != '')
  399. $user_title = pun_htmlspecialchars($group['g_user_title']);
  400. // If the user is a guest
  401. else if ($group['g_id'] == PUN_GUEST)
  402. $user_title = $lang_common['Guest'];
  403. else
  404. {
  405. // Are there any ranks?
  406. if ($pun_config['o_ranks'] == '1' && !empty($pun_ranks))
  407. {
  408. @reset($pun_ranks);
  409. while (list(, $cur_rank) = @each($pun_ranks))
  410. {
  411. if (intval($user['num_posts']) >= $cur_rank['min_posts'])
  412. $user_title = pun_htmlspecialchars($cur_rank['rank']);
  413. }
  414. }
  415. // If the user didn't "reach" any rank (or if ranks are disabled), we assign the default
  416. if (!isset($user_title))
  417. $user_title = $lang_common['Member'];
  418. }
  419. return $user_title;
  420. }
  421. //
  422. // Generate a string with numbered links (for multipage scripts)
  423. //
  424. function paginate($num_pages, $cur_page, $link_to)
  425. {
  426. $pages = array();
  427. $link_to_all = false;
  428. // If $cur_page == -1, we link to all pages (used in viewforum.php)
  429. if ($cur_page == -1)
  430. {
  431. $cur_page = 1;
  432. $link_to_all = true;
  433. }
  434. if ($num_pages <= 1)
  435. $pages = array('<strong>1</strong>');
  436. else
  437. {
  438. if ($cur_page > 3)
  439. {
  440. $pages[] = '<a href="'.$link_to.'&amp;p=1">1</a>';
  441. if ($cur_page != 4)
  442. $pages[] = '&hellip;';
  443. }
  444. // Don't ask me how the following works. It just does, OK? :-)
  445. for ($current = $cur_page - 2, $stop = $cur_page + 3; $current < $stop; ++$current)
  446. {
  447. if ($current < 1 || $current > $num_pages)
  448. continue;
  449. else if ($current != $cur_page || $link_to_all)
  450. $pages[] = '<a href="'.$link_to.'&amp;p='.$current.'">'.$current.'</a>';
  451. else
  452. $pages[] = '<strong>'.$current.'</strong>';
  453. }
  454. if ($cur_page <= ($num_pages-3))
  455. {
  456. if ($cur_page != ($num_pages-3))
  457. $pages[] = '&hellip;';
  458. $pages[] = '<a href="'.$link_to.'&amp;p='.$num_pages.'">'.$num_pages.'</a>';
  459. }
  460. }
  461. return implode('&nbsp;', $pages);
  462. }
  463. //
  464. // Display a message
  465. //
  466. function message($message, $no_back_link = false)
  467. {
  468. global $db, $lang_common, $pun_config, $pun_start, $tpl_main;
  469. if (!defined('PUN_HEADER'))
  470. {
  471. global $pun_user;
  472. $page_title = pun_htmlspecialchars("{$lang_common['Info']} / {$pun_config['o_board_title']}");
  473. require PUN_ROOT.'header.php';
  474. }
  475. ?>
  476. <div id="msg" class="block">
  477. <h2><span><?php echo $lang_common['Info'] ?></span></h2>
  478. <div class="box">
  479. <div class="inbox">
  480. <p><?php echo $message ?></p>
  481. <?php if (!$no_back_link): ?> <p><a href="javascript: history.go(-1)"><?php echo $lang_common['Go back'] ?></a></p>
  482. <?php endif; ?> </div>
  483. </div>
  484. </div>
  485. <?php
  486. require PUN_ROOT.'footer.php';
  487. }
  488. //
  489. // Format a time string according to $time_format and timezones
  490. //
  491. function format_time($timestamp, $date_only = false)
  492. {
  493. global $pun_config, $lang_common, $pun_user;
  494. if ($timestamp == '')
  495. return $lang_common['Never'];
  496. $diff = ($pun_user['timezone'] - $pun_config['o_server_timezone']) * 3600;
  497. $timestamp += $diff;
  498. $now = time();
  499. $date = date($pun_config['o_date_format'], $timestamp);
  500. $today = date($pun_config['o_date_format'], $now+$diff);
  501. $yesterday = date($pun_config['o_date_format'], $now+$diff-86400);
  502. if ($date == $today)
  503. $date = $lang_common['Today'];
  504. else if ($date == $yesterday)
  505. $date = $lang_common['Yesterday'];
  506. if (!$date_only)
  507. return $date.' '.date($pun_config['o_time_format'], $timestamp);
  508. else
  509. return $date;
  510. }
  511. //
  512. // If we are running pre PHP 4.3.0, we add our own implementation of file_get_contents
  513. //
  514. if (!function_exists('file_get_contents'))
  515. {
  516. function file_get_contents($filename, $use_include_path = 0)
  517. {
  518. $data = '';
  519. if ($fh = fopen($filename, 'rb', $use_include_path))
  520. {
  521. $data = fread($fh, filesize($filename));
  522. fclose($fh);
  523. }
  524. return $data;
  525. }
  526. }
  527. //
  528. // Make sure that HTTP_REFERER matches $pun_config['o_base_url']/$script
  529. //
  530. function confirm_referrer($script)
  531. {
  532. global $pun_config, $lang_common;
  533. // 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'] : ''))))
  534. // message($lang_common['Bad referrer']);
  535. }
  536. //
  537. // Generate a random password of length $len
  538. //
  539. function random_pass($len)
  540. {
  541. $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  542. $password = '';
  543. for ($i = 0; $i < $len; ++$i)
  544. $password .= substr($chars, (mt_rand() % strlen($chars)), 1);
  545. return $password;
  546. }
  547. //
  548. // Compute a hash of $str
  549. // Uses sha1() if available. If not, SHA1 through mhash() if available. If not, fall back on md5().
  550. //
  551. function pun_hash($password, $name)
  552. {
  553. return sha1(bors_lower($name) . $password);
  554. if (function_exists('sha1')) // Only in PHP 4.3.0+
  555. return sha1($str);
  556. else if (function_exists('mhash')) // Only if Mhash library is loaded
  557. return bin2hex(mhash(MHASH_SHA1, $str));
  558. else
  559. return md5($str);
  560. }
  561. //
  562. // Try to determine the correct remote IP-address
  563. //
  564. function get_remote_address()
  565. {
  566. return $_SERVER['REMOTE_ADDR'];
  567. }
  568. //
  569. // Equivalent to htmlspecialchars(), but allows &#[0-9]+ (for unicode)
  570. //
  571. function pun_htmlspecialchars($str)
  572. {
  573. $str = preg_replace('/&(?!#[0-9]+;)/s', '&amp;', $str);
  574. $str = str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $str);
  575. return $str;
  576. }
  577. //
  578. // Equivalent to strlen(), but counts &#[0-9]+ as one character (for unicode)
  579. //
  580. function pun_strlen($str)
  581. {
  582. return bors_strlen(preg_replace('/&#([0-9]+);/', '!', $str));
  583. }
  584. //
  585. // Convert \r\n and \r to \n
  586. //
  587. function pun_linebreaks($str)
  588. {
  589. return str_replace("\r", "\n", str_replace("\r\n", "\n", $str));
  590. }
  591. //
  592. // A more aggressive version of trim()
  593. //
  594. function pun_trim($str)
  595. {
  596. global $lang_common;
  597. if (strpos($lang_common['lang_encoding'], '8859') !== false)
  598. {
  599. $fishy_chars = array(chr(0x81), chr(0x8D), chr(0x8F), chr(0x90), chr(0x9D), chr(0xA0));
  600. return trim(str_replace($fishy_chars, ' ', $str));
  601. }
  602. else
  603. return trim($str);
  604. }
  605. //
  606. // Display a message when board is in maintenance mode
  607. //
  608. function maintenance_message()
  609. {
  610. global $db, $pun_config, $lang_common, $pun_user;
  611. // Deal with newlines, tabs and multiple spaces
  612. $pattern = array("\t", ' ', ' ');
  613. $replace = array('&nbsp; &nbsp; ', '&nbsp; ', ' &nbsp;');
  614. $message = str_replace($pattern, $replace, $pun_config['o_maintenance_message']);
  615. // Load the maintenance template
  616. $tpl_maint = trim(file_get_contents(PUN_ROOT.'include/template/maintenance.tpl'));
  617. // START SUBST - <pun_content_direction>
  618. $tpl_maint = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_maint);
  619. // END SUBST - <pun_content_direction>
  620. // START SUBST - <pun_char_encoding>
  621. $tpl_maint = str_replace('<pun_char_encoding>', $lang_common['lang_encoding'], $tpl_maint);
  622. // END SUBST - <pun_char_encoding>
  623. // START SUBST - <pun_head>
  624. ob_start();
  625. ?>
  626. <title><?php echo pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Maintenance'] ?></title>
  627. <link rel="stylesheet" type="text/css" href="<?php echo $pun_config['root_uri'];?>/style/imports/colors.css" />
  628. <link rel="stylesheet" type="text/css" href="<?php echo $pun_config['root_uri'];?>/style/imports/fixes.css" />
  629. <link rel="stylesheet" type="text/css" href="<?php echo $pun_config['root_uri'];?>/style/<?php echo $pun_user['style'].'.css' ?>" />
  630. <?php
  631. $tpl_temp = trim(ob_get_contents());
  632. $tpl_maint = str_replace('<pun_head>', $tpl_temp, $tpl_maint);
  633. ob_end_clean();
  634. // END SUBST - <pun_head>
  635. // START SUBST - <pun_maint_heading>
  636. $tpl_maint = str_replace('<pun_maint_heading>', $lang_common['Maintenance'], $tpl_maint);
  637. // END SUBST - <pun_maint_heading>
  638. // START SUBST - <pun_maint_message>
  639. $tpl_maint = str_replace('<pun_maint_message>', $message, $tpl_maint);
  640. // END SUBST - <pun_maint_message>
  641. // End the transaction
  642. $db->end_transaction();
  643. // START SUBST - <pun_include "*">
  644. while (preg_match('#<pun_include "([^/\\\\]*?)">#', $tpl_maint, $cur_include))
  645. {
  646. if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1]))
  647. error('Unable to process user include &lt;pun_include "'.htmlspecialchars($cur_include[1]).'"&gt; from template maintenance.tpl. There is no such file in folder /include/user/');
  648. ob_start();
  649. include PUN_ROOT.'include/user/'.$cur_include[1];
  650. $tpl_temp = ob_get_contents();
  651. $tpl_maint = str_replace($cur_include[0], $tpl_temp, $tpl_maint);
  652. ob_end_clean();
  653. }
  654. // END SUBST - <pun_include "*">
  655. // Close the db connection (and free up any result data)
  656. $db->close();
  657. pun_exit($tpl_maint);
  658. }
  659. //
  660. // Display $message and redirect user to $destination_url
  661. // "
  662. function redirect($destination_url, $message)
  663. {
  664. global $db, $pun_config, $lang_common, $pun_user;
  665. if ($destination_url == '')
  666. $destination_url = 'index.php';
  667. // Load the redirect template
  668. $tpl_redir = trim(file_get_contents(PUN_ROOT.'include/template/redirect.tpl'));
  669. // START SUBST - <pun_content_direction>
  670. $tpl_redir = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_redir);
  671. // END SUBST - <pun_content_direction>
  672. // START SUBST - <pun_char_encoding>
  673. $tpl_redir = str_replace('<pun_char_encoding>', $lang_common['lang_encoding'], $tpl_redir);
  674. // END SUBST - <pun_char_encoding>
  675. // START SUBST - <pun_head>
  676. ob_start();
  677. ?>
  678. <meta http-equiv="refresh" content="<?php echo $pun_config['o_redirect_delay'] ?>;URL=<?php echo str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $destination_url) ?>" />
  679. <title><?php echo pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Redirecting'] ?></title>
  680. <link rel="stylesheet" type="text/css" href="<?php echo $pun_config['root_uri'];?>/style/imports/colors.css" />
  681. <link rel="stylesheet" type="text/css" href="<?php echo $pun_config['root_uri'];?>/style/imports/fixes.css" />
  682. <link rel="stylesheet" type="text/css" href="<?php echo $pun_config['root_uri'];?>/style/<?php echo $pun_user['style'].'.css' ?>" />
  683. <?php /*"*/
  684. $tpl_temp = trim(ob_get_contents());
  685. $tpl_redir = str_replace('<pun_head>', $tpl_temp, $tpl_redir);
  686. ob_end_clean();
  687. // END SUBST - <pun_head>
  688. // START SUBST - <pun_redir_heading>
  689. $tpl_redir = str_replace('<pun_redir_heading>', $lang_common['Redirecting'], $tpl_redir);
  690. // END SUBST - <pun_redir_heading>
  691. // START SUBST - <pun_redir_text>
  692. $tpl_temp = $message.'<br /><br />'.'<a href="'.$destination_url.'">'.$lang_common['Click redirect'].'</a>';
  693. $tpl_redir = str_replace('<pun_redir_text>', $tpl_temp, $tpl_redir);
  694. // END SUBST - <pun_redir_text>
  695. // START SUBST - <pun_footer>
  696. ob_start();
  697. // End the transaction
  698. $db->end_transaction();
  699. // Display executed queries (if enabled)
  700. if (defined('PUN_SHOW_QUERIES'))
  701. display_saved_queries();
  702. $tpl_temp = trim(ob_get_contents());
  703. $tpl_redir = str_replace('<pun_footer>', $tpl_temp, $tpl_redir);
  704. ob_end_clean();
  705. // END SUBST - <pun_footer>
  706. // START SUBST - <pun_include "*">
  707. while (preg_match('#<pun_include "([^/\\\\]*?)">#', $tpl_redir, $cur_include))
  708. {
  709. if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1]))
  710. error('Unable to process user include &lt;pun_include "'.htmlspecialchars($cur_include[1]).'"&gt; from template redirect.tpl. There is no such file in folder /include/user/');
  711. ob_start();
  712. include PUN_ROOT.'include/user/'.$cur_include[1];
  713. $tpl_temp = ob_get_contents();
  714. $tpl_redir = str_replace($cur_include[0], $tpl_temp, $tpl_redir);
  715. ob_end_clean();
  716. }
  717. // END SUBST - <pun_include "*">
  718. // Close the db connection (and free up any result data)
  719. $db->close();
  720. // If the delay is 0 seconds, we might as well skip the redirect all together
  721. // if ($pun_config['o_redirect_delay'] == '0')
  722. // header('Location: '.str_replace('&amp;', '&', $destination_url));
  723. pun_exit($tpl_redir, $pun_config['o_redirect_delay'] ? false : $destination_url);
  724. }
  725. //
  726. // Display a simple error message
  727. //
  728. function error($message, $file, $line, $db_error = false)
  729. {
  730. global $pun_config;
  731. // Set a default title if the script failed before $pun_config could be populated
  732. if (empty($pun_config))
  733. $pun_config['o_board_title'] = 'PunBB';
  734. // Empty output buffer and stop buffering
  735. @ob_end_clean();
  736. // "Restart" output buffering if we are using ob_gzhandler (since the gzip header is already sent)
  737. if (!empty($pun_config['o_gzip']) && extension_loaded('zlib') && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false || strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== false))
  738. ob_start('ob_gzhandler');
  739. ?>
  740. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  741. <html dir="ltr">
  742. <head>
  743. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  744. <title><?php echo pun_htmlspecialchars($pun_config['o_board_title']) ?> / Error</title>
  745. <style type="text/css">
  746. <!--
  747. BODY {MARGIN: 10% 20% auto 20%; font: 10px Verdana, Arial, Helvetica, sans-serif}
  748. #errorbox {BORDER: 1px solid #B84623}
  749. H2 {MARGIN: 0; COLOR: #FFFFFF; BACKGROUND-COLOR: #B84623; FONT-SIZE: 1.1em; PADDING: 5px 4px}
  750. #errorbox DIV {PADDING: 6px 5px; BACKGROUND-COLOR: #F1F1F1}
  751. -->
  752. </style>
  753. </head>
  754. <body>
  755. <div id="errorbox">
  756. <h2>An error was encountered</h2>
  757. <div>
  758. <?php
  759. if (defined('PUN_DEBUG'))
  760. {
  761. echo "\t\t".'<strong>File:</strong> '.$file.'<br />'."\n\t\t".'<strong>Line:</strong> '.$line.'<br /><br />'."\n\t\t".'<strong>PunBB reported</strong>: '.$message."\n";
  762. if ($db_error)
  763. {
  764. echo "\t\t".'<br /><br /><strong>Database reported:</strong> '.pun_htmlspecialchars($db_error['error_msg']).(($db_error['error_no']) ? ' (Errno: '.$db_error['error_no'].')' : '')."\n";
  765. if ($db_error['error_sql'] != '')
  766. echo "\t\t".'<br /><br /><strong>Failed query:</strong> '.pun_htmlspecialchars($db_error['error_sql'])."\n";
  767. echo "Если проблема постоянна и к форуму нет доступа, попробуйте заглянуть
  768. за подробностями на <a href=\"http://balancer.endofinternet.net/mybb/forum-2.html\">Запасной форум</a>
  769. или на <a href=\"http://bal.livejournal.com/\">bal.livejournal.com</a>";
  770. }
  771. }
  772. else
  773. echo "\t\t".'Error: <strong>'.$message.'.</strong>'."\n";
  774. ?>
  775. </div>
  776. </div>
  777. </body>
  778. </html>
  779. <?php
  780. // If a database connection was established (before this error) we close it
  781. if ($db_error)
  782. $GLOBALS['db']->close();
  783. exit;
  784. }
  785. // DEBUG FUNCTIONS BELOW
  786. //
  787. // Display executed queries (if enabled)
  788. //
  789. function display_saved_queries()
  790. {
  791. global $db, $lang_common;
  792. // Get the queries so that we can print them out
  793. $saved_queries = $db->get_saved_queries();
  794. ?>
  795. <div id="debug" class="blocktable">
  796. <h2><span><?php echo $lang_common['Debug table'] ?></span></h2>
  797. <div class="box">
  798. <div class="inbox">
  799. <table cellspacing="0">
  800. <thead>
  801. <tr>
  802. <th class="tcl" scope="col">Time (s)</th>
  803. <th class="tcr" scope="col">Query</th>
  804. </tr>
  805. </thead>
  806. <tbody>
  807. <?php
  808. $query_time_total = 0.0;
  809. while (list(, $cur_query) = @each($saved_queries))
  810. {
  811. $query_time_total += $cur_query[1];
  812. ?>
  813. <tr>
  814. <td class="tcl"><?php echo ($cur_query[1] != 0) ? $cur_query[1] : '&nbsp;' ?></td>
  815. <td class="tcr"><?php echo pun_htmlspecialchars($cur_query[0]) ?></td>
  816. </tr>
  817. <?php
  818. }
  819. ?>
  820. <tr>
  821. <td class="tcl" colspan="2">Total query time: <?php echo $query_time_total ?> s</td>
  822. </tr>
  823. </tbody>
  824. </table>
  825. </div>
  826. </div>
  827. </div>
  828. <?php
  829. }
  830. //
  831. // Unset any variables instantiated as a result of register_globals being enabled
  832. //
  833. function unregister_globals()
  834. {
  835. // Prevent script.php?GLOBALS[foo]=bar
  836. if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']))
  837. exit('I\'ll have a steak sandwich and... a steak sandwich.');
  838. // Variables that shouldn't be unset
  839. $no_unset = array('GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
  840. // Remove elements in $GLOBALS that are present in any of the superglobals
  841. $input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());
  842. foreach ($input as $k => $v)
  843. {
  844. if (!in_array($k, $no_unset) && isset($GLOBALS[$k]))
  845. unset($GLOBALS[$k]);
  846. }
  847. }
  848. include_once("pun_bal.php");
  849. function parse_signature($s)
  850. {
  851. return pun_lcml($s);
  852. }
  853. function pun_exit($message = 0, $redirect = false)
  854. {
  855. bors()->changed_save();
  856. // If the delay is 0 seconds, we might as well skip the redirect all together
  857. if($redirect)
  858. header('Location: '.str_replace('&amp;', '&', $redirect));
  859. $message = bors_punbb_end($message);
  860. exit($message);
  861. }