PageRenderTime 30ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/upload/includes/functions.php

http://torrentpier2.googlecode.com/
PHP | 2954 lines | 2350 code | 343 blank | 261 comment | 394 complexity | 549746820059d5ae3ae502a7fff17e21 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. if (!defined('BB_ROOT')) die(basename(__FILE__));
  3. function get_path_from_id ($id, $ext_id, $base_path, $first_div, $sec_div)
  4. {
  5. global $bb_cfg;
  6. $ext = isset($bb_cfg['file_id_ext'][$ext_id]) ? $bb_cfg['file_id_ext'][$ext_id] : '';
  7. return ($base_path ? "$base_path/" : '') . floor($id/$first_div) .'/'. ($id % $sec_div) .'/'. $id . ($ext ? ".$ext" : '');
  8. }
  9. function get_avatar_path ($id, $ext_id, $base_path = '')
  10. {
  11. return get_path_from_id($id, $ext_id, $base_path, 5000000, 100);
  12. }
  13. function delete_avatar ($user_id, $avatar_ext_id)
  14. {
  15. global $bb_cfg;
  16. $avatar_file = ($avatar_ext_id) ? get_avatar_path($user_id, $avatar_ext_id, $bb_cfg['avatars']['upload_path']) : '';
  17. return ($avatar_file && file_exists($avatar_file)) ? @unlink($avatar_file) : false;
  18. }
  19. function get_attach_path ($id)
  20. {
  21. global $bb_cfg;
  22. return get_path_from_id($id, '', $bb_cfg['attach']['upload_path'], 1000000, 100);
  23. }
  24. function get_tracks ($type)
  25. {
  26. static $pattern = '#^a:\d+:{[i:;\d]+}$#';
  27. switch ($type)
  28. {
  29. case 'topic':
  30. $c_name = COOKIE_TOPIC;
  31. break;
  32. case 'forum':
  33. $c_name = COOKIE_FORUM;
  34. break;
  35. case 'pm':
  36. $c_name = COOKIE_PM;
  37. break;
  38. default:
  39. trigger_error(__FUNCTION__ .": invalid type '$type'", E_USER_ERROR);
  40. }
  41. $tracks = !empty($_COOKIE[$c_name]) ? @unserialize($_COOKIE[$c_name]) : false;
  42. return ($tracks) ? $tracks : array();
  43. }
  44. function set_tracks ($cookie_name, &$tracking_ary, $tracks = null, $val = TIMENOW)
  45. {
  46. global $tracking_topics, $tracking_forums, $user;
  47. if (IS_GUEST) return;
  48. $prev_tracking_ary = $tracking_ary;
  49. if ($tracks)
  50. {
  51. if (!is_array($tracks))
  52. {
  53. $tracks = array($tracks => $val);
  54. }
  55. foreach ($tracks as $key => $val)
  56. {
  57. $key = (int) $key;
  58. $val++;
  59. $curr_track_val = !empty($tracking_ary[$key]) ? $tracking_ary[$key] : 0;
  60. if ($val > max($curr_track_val, $user->data['user_lastvisit']))
  61. {
  62. $tracking_ary[$key] = $val;
  63. }
  64. elseif ($curr_track_val < $user->data['user_lastvisit'])
  65. {
  66. unset($tracking_ary[$key]);
  67. }
  68. }
  69. }
  70. $overflow = count($tracking_topics) + count($tracking_forums) - COOKIE_MAX_TRACKS;
  71. if ($overflow > 0)
  72. {
  73. arsort($tracking_ary);
  74. for ($i=0; $i < $overflow; $i++)
  75. {
  76. array_pop($tracking_ary);
  77. }
  78. }
  79. if (array_diff($tracking_ary, $prev_tracking_ary))
  80. {
  81. bb_setcookie($cookie_name, serialize($tracking_ary));
  82. }
  83. }
  84. function get_last_read ($topic_id = 0, $forum_id = 0)
  85. {
  86. global $tracking_topics, $tracking_forums, $user;
  87. $t = isset($tracking_topics[$topic_id]) ? $tracking_topics[$topic_id] : 0;
  88. $f = isset($tracking_forums[$forum_id]) ? $tracking_forums[$forum_id] : 0;
  89. return max($t, $f, $user->data['user_lastvisit']);
  90. }
  91. function is_unread ($ref, $topic_id = 0, $forum_id = 0)
  92. {
  93. return (!IS_GUEST && $ref > get_last_read($topic_id, $forum_id));
  94. }
  95. //
  96. // Ads
  97. //
  98. class ads_common
  99. {
  100. var $ad_blocks = array();
  101. var $active_ads = array();
  102. /**
  103. * Constructor
  104. */
  105. function ads_common ()
  106. {
  107. global $bb_cfg;
  108. $this->ad_blocks =& $bb_cfg['ad_blocks'];
  109. $this->active_ads = !empty($bb_cfg['active_ads']) ? unserialize($bb_cfg['active_ads']) : array();
  110. }
  111. /**
  112. * Get ads to show for each block
  113. */
  114. function get ($block_types)
  115. {
  116. $ads = array();
  117. if ($this->active_ads)
  118. {
  119. $block_ids = $this->get_block_ids($block_types);
  120. if ($ad_ids = $this->get_ad_ids($block_ids))
  121. {
  122. $ad_html = $this->get_ads_html();
  123. foreach ($ad_ids as $block_id => $ad_id)
  124. {
  125. $ads[$block_id] =& $ad_html[$ad_id];
  126. }
  127. }
  128. }
  129. return $ads;
  130. }
  131. /**
  132. * Get ads html
  133. */
  134. function get_ads_html ()
  135. {
  136. global $datastore;
  137. if (!$ads_html = $datastore->get('ads'))
  138. {
  139. $datastore->update('ads');
  140. $ads_html = $datastore->get('ads');
  141. }
  142. return $ads_html;
  143. }
  144. /**
  145. * Get block_ids for specified block_types
  146. */
  147. function get_block_ids ($block_types)
  148. {
  149. $block_ids = array();
  150. foreach ($block_types as $block_type)
  151. {
  152. if ($blocks =& $this->ad_blocks[$block_type])
  153. {
  154. $block_ids = array_merge($block_ids, array_keys($blocks));
  155. }
  156. }
  157. return $block_ids;
  158. }
  159. /**
  160. * Get ad_ids for specified blocks
  161. */
  162. function get_ad_ids ($block_ids)
  163. {
  164. $ad_ids = array();
  165. foreach ($block_ids as $block_id)
  166. {
  167. if ($ads =& $this->active_ads[$block_id])
  168. {
  169. shuffle($ads);
  170. $ad_ids[$block_id] = $ads[0];
  171. }
  172. }
  173. return $ad_ids;
  174. }
  175. }
  176. //
  177. // Auth
  178. //
  179. define('AUTH_LIST_ALL', 0);
  180. // forum's ACL types (bb_forums: auth_view, auth_read... values)
  181. define('AUTH_REG', 1);
  182. define('AUTH_ACL', 2);
  183. define('AUTH_ADMIN', 5);
  184. // forum_perm bitfields - backward compatible with auth($type)
  185. define('AUTH_ALL', 0);
  186. define('AUTH_VIEW', 1);
  187. define('AUTH_READ', 2);
  188. define('AUTH_MOD', 3);
  189. define('AUTH_POST', 4);
  190. define('AUTH_REPLY', 5);
  191. define('AUTH_EDIT', 6);
  192. define('AUTH_DELETE', 7);
  193. define('AUTH_STICKY', 8);
  194. define('AUTH_ANNOUNCE', 9);
  195. define('AUTH_VOTE', 10);
  196. define('AUTH_POLLCREATE', 11);
  197. define('AUTH_ATTACH', 12);
  198. define('AUTH_DOWNLOAD', 13);
  199. define('BF_AUTH_MOD', bit2dec(AUTH_MOD));
  200. // When defining user permissions, take into account:
  201. define('UG_PERM_BOTH', 1); // both user and group
  202. define('UG_PERM_USER_ONLY', 2); // only personal user permissions
  203. define('UG_PERM_GROUP_ONLY', 3); // only group permissions
  204. $bf['forum_perm'] = array(
  205. 'auth_view' => AUTH_VIEW,
  206. 'auth_read' => AUTH_READ,
  207. 'auth_mod' => AUTH_MOD,
  208. 'auth_post' => AUTH_POST,
  209. 'auth_reply' => AUTH_REPLY,
  210. 'auth_edit' => AUTH_EDIT,
  211. 'auth_delete' => AUTH_DELETE,
  212. 'auth_sticky' => AUTH_STICKY,
  213. 'auth_announce' => AUTH_ANNOUNCE,
  214. 'auth_vote' => AUTH_VOTE,
  215. 'auth_pollcreate' => AUTH_POLLCREATE,
  216. 'auth_attachments' => AUTH_ATTACH,
  217. 'auth_download' => AUTH_DOWNLOAD,
  218. );
  219. $bf['user_opt'] = array(
  220. 'viewemail' => 0, // ?????????? e-mail
  221. 'allow_sig' => 1, // ?????? ?? ???????
  222. 'allow_avatar' => 2, // ?????? ?? ??????
  223. 'allow_pm' => 3, // ?????? ?? ???????? ??
  224. 'allow_viewonline' => 4, // ???????? ?????????? ????????????
  225. 'notify' => 5, // ???????? ?? ??????? ? ????????????? ?????
  226. 'notify_pm' => 6, // ???????? ? ????? ??
  227. 'allow_passkey' => 7, // ?????? ?? ?????????? passkey, ?? ?? ?????? ?? ?????????? ?????????
  228. 'hide_porn_forums' => 8, // ???????? pron ??????
  229. 'allow_gallery' => 9, // ?????????????? (?????? ????????????? ???????)
  230. 'hide_ads' => 10, // ?????? ?? ????? ???????
  231. 'allow_topic' => 11, // ?????? ?? ???????? ????? ???
  232. 'allow_post' => 12, // ?????? ?? ???????? ?????????
  233. 'allow_post_edit' => 13, // ?????? ?? ?????????????? ?????????
  234. 'allow_dls' => 14, // ?????? ?? ?????? ??????? ??????? ? ???????
  235. );
  236. function bit2dec ($bit_num)
  237. {
  238. if (is_array($bit_num))
  239. {
  240. $dec = 0;
  241. foreach ($bit_num as $bit)
  242. {
  243. $dec |= (1 << $bit);
  244. }
  245. return $dec;
  246. }
  247. return (1 << $bit_num);
  248. }
  249. function bf_bit2dec ($bf_array_name, $key)
  250. {
  251. global $bf;
  252. if (!isset($bf[$bf_array_name][$key]))
  253. {
  254. trigger_error(__FUNCTION__ .": bitfield '$key' not found", E_USER_ERROR);
  255. }
  256. return (1 << $bf[$bf_array_name][$key]);
  257. }
  258. function bf ($int, $bf_array_name, $key)
  259. {
  260. return (bf_bit2dec($bf_array_name, $key) & (int) $int);
  261. }
  262. function setbit (&$int, $bit_num, $on)
  263. {
  264. return ($on) ? $int |= (1 << $bit_num) : $int &= ~(1 << $bit_num);
  265. }
  266. /*
  267. $type's accepted (pre-pend with AUTH_):
  268. VIEW, READ, POST, REPLY, EDIT, DELETE, STICKY, ANNOUNCE, VOTE, POLLCREATE
  269. Possible options ($type/forum_id combinations):
  270. * If you include a type and forum_id then a specific lookup will be done and
  271. the single result returned
  272. * If you set type to AUTH_ALL and specify a forum_id an array of all auth types
  273. will be returned
  274. * If you provide a forum_id a specific lookup on that forum will be done
  275. * If you set forum_id to AUTH_LIST_ALL and specify a type an array listing the
  276. results for all forums will be returned
  277. * If you set forum_id to AUTH_LIST_ALL and type to AUTH_ALL a multidimensional
  278. array containing the auth permissions for all types and all forums for that
  279. user is returned
  280. All results are returned as associative arrays, even when a single auth type is
  281. specified.
  282. If available you can send an array (either one or two dimensional) containing the
  283. forum auth levels, this will prevent the auth function having to do its own
  284. lookup
  285. */
  286. function auth ($type, $forum_id, $ug_data, $f_access = array(), $group_perm = UG_PERM_BOTH)
  287. {
  288. global $lang, $bf, $datastore;
  289. $is_guest = true;
  290. $is_admin = false;
  291. $auth = $auth_fields = $u_access = array();
  292. $add_auth_type_desc = ($forum_id != AUTH_LIST_ALL);
  293. //
  294. // Get $auth_fields
  295. //
  296. if ($type == AUTH_ALL)
  297. {
  298. $auth_fields = array_keys($bf['forum_perm']);
  299. }
  300. else if ($auth_type = array_search($type, $bf['forum_perm']))
  301. {
  302. $auth_fields = array($auth_type);
  303. }
  304. if (empty($auth_fields))
  305. {
  306. trigger_error(__FUNCTION__ .'(): empty $auth_fields', E_USER_ERROR);
  307. }
  308. //
  309. // Get $f_access
  310. //
  311. // If f_access has been passed, or auth is needed to return an array of forums
  312. // then we need to pull the auth information on the given forum (or all forums)
  313. if (empty($f_access))
  314. {
  315. if (!$forums = $datastore->get('cat_forums'))
  316. {
  317. $datastore->update('cat_forums');
  318. $forums = $datastore->get('cat_forums');
  319. }
  320. if ($forum_id == AUTH_LIST_ALL)
  321. {
  322. $f_access = $forums['f'];
  323. }
  324. else if (isset($forums['f'][$forum_id]))
  325. {
  326. $f_access[$forum_id] = $forums['f'][$forum_id];
  327. }
  328. }
  329. else if (isset($f_access['forum_id']))
  330. {
  331. // Change passed $f_access format for later using in foreach()
  332. $f_access = array($f_access['forum_id'] => $f_access);
  333. }
  334. if (empty($f_access))
  335. {
  336. trigger_error(__FUNCTION__ .'(): empty $f_access', E_USER_ERROR);
  337. }
  338. //
  339. // Get user or group permissions
  340. //
  341. $forum_match_sql = ($forum_id != AUTH_LIST_ALL) ? "AND aa.forum_id = ". (int) $forum_id : '';
  342. // GROUP mode
  343. if (!empty($ug_data['group_id']))
  344. {
  345. $is_guest = false;
  346. $is_admin = false;
  347. $sql = "SELECT aa.forum_id, aa.forum_perm
  348. FROM ". BB_AUTH_ACCESS ." aa
  349. WHERE aa.group_id = ". (int) $ug_data['group_id'] ."
  350. $forum_match_sql";
  351. foreach (DB()->fetch_rowset($sql) as $row)
  352. {
  353. $u_access[$row['forum_id']] = $row['forum_perm'];
  354. }
  355. }
  356. // USER mode
  357. else if (!empty($ug_data['user_id']))
  358. {
  359. $is_guest = empty($ug_data['session_logged_in']);
  360. $is_admin = (!$is_guest && $ug_data['user_level'] == ADMIN);
  361. if ($group_perm != UG_PERM_BOTH)
  362. {
  363. $group_single_user = ($group_perm == UG_PERM_USER_ONLY) ? 1 : 0;
  364. $sql = "
  365. SELECT
  366. aa.forum_id, BIT_OR(aa.forum_perm) AS forum_perm
  367. FROM
  368. ". BB_USER_GROUP ." ug,
  369. ". BB_GROUPS ." g,
  370. ". BB_AUTH_ACCESS ." aa
  371. WHERE
  372. ug.user_id = ". (int) $ug_data['user_id'] ."
  373. AND ug.user_pending = 0
  374. AND g.group_id = ug.group_id
  375. AND g.group_single_user = $group_single_user
  376. AND aa.group_id = g.group_id
  377. $forum_match_sql
  378. GROUP BY aa.forum_id
  379. ";
  380. foreach (DB()->fetch_rowset($sql) as $row)
  381. {
  382. $u_access[$row['forum_id']] = $row['forum_perm'];
  383. }
  384. }
  385. else
  386. {
  387. if (!$is_guest && !$is_admin)
  388. {
  389. $sql = "SELECT SQL_CACHE aa.forum_id, aa.forum_perm
  390. FROM ". BB_AUTH_ACCESS_SNAP ." aa
  391. WHERE aa.user_id = ". (int) $ug_data['user_id'] ."
  392. $forum_match_sql";
  393. foreach (DB()->fetch_rowset($sql) as $row)
  394. {
  395. $u_access[$row['forum_id']] = $row['forum_perm'];
  396. }
  397. }
  398. }
  399. }
  400. // If the user is logged on and the forum type is either ALL or REG then the user has access
  401. //
  402. // If the type if ACL, MOD or ADMIN then we need to see if the user has specific permissions
  403. // to do whatever it is they want to do ... to do this we pull relevant information for the
  404. // user (and any groups they belong to)
  405. //
  406. // Now we compare the users access level against the forums. We assume here that a moderator
  407. // and admin automatically have access to an ACL forum, similarly we assume admins meet an
  408. // auth requirement of MOD
  409. //
  410. foreach ($f_access as $f_id => $f_data)
  411. {
  412. $auth[$f_id]['auth_mod'] = auth_check('forum_perm', 'auth_mod', $u_access, $f_id, $is_admin);
  413. foreach ($auth_fields as $auth_type)
  414. {
  415. if (!isset($f_data[$auth_type]))
  416. {
  417. continue;
  418. }
  419. switch ($f_data[$auth_type])
  420. {
  421. case AUTH_ALL:
  422. $auth[$f_id][$auth_type] = true;
  423. break;
  424. case AUTH_REG:
  425. $auth[$f_id][$auth_type] = !$is_guest;
  426. break;
  427. case AUTH_ACL:
  428. $auth[$f_id][$auth_type] = (auth_check('forum_perm', $auth_type, $u_access, $f_id, $is_admin) || $auth[$f_id]['auth_mod']);
  429. break;
  430. case AUTH_MOD:
  431. $auth[$f_id][$auth_type] = $auth[$f_id]['auth_mod'];
  432. break;
  433. case AUTH_ADMIN:
  434. $auth[$f_id][$auth_type] = $is_admin;
  435. break;
  436. default:
  437. $auth[$f_id][$auth_type] = false;
  438. }
  439. if ($add_auth_type_desc)
  440. {
  441. $auth[$f_id][$auth_type .'_type'] =& $lang['AUTH_TYPES'][$f_data[$auth_type]];
  442. }
  443. }
  444. }
  445. return ($forum_id == AUTH_LIST_ALL) ? $auth : $auth[$forum_id];
  446. }
  447. function auth_check ($bf_ary, $bf_key, $perm_ary, $perm_key, $is_admin = false)
  448. {
  449. if ($is_admin) return true;
  450. if (!isset($perm_ary[$perm_key])) return false;
  451. return bf($perm_ary[$perm_key], $bf_ary, $bf_key);
  452. }
  453. class Date_Delta
  454. {
  455. var $auto_granularity = array(
  456. 60 => 'seconds', // set granularity to "seconds" if delta less then 1 minute
  457. 10800 => 'minutes', // 3 hours
  458. 259200 => 'hours', // 3 days
  459. 31363200 => 'mday', // 12 months
  460. 311040000 => 'mon', // 10 years
  461. );
  462. var $intervals = array();
  463. var $format = '';
  464. // Creates new object.
  465. function Date_Delta()
  466. {
  467. global $lang;
  468. $this->intervals = $lang['DELTA_TIME']['INTERVALS'];
  469. $this->format = $lang['DELTA_TIME']['FORMAT'];
  470. }
  471. // Makes the spellable phrase.
  472. function spellDelta($first, $last, $from = 'auto')
  473. {
  474. if ($last < $first)
  475. {
  476. $old_first = $first;
  477. $first = $last;
  478. $last = $old_first;
  479. }
  480. if ($from == 'auto')
  481. {
  482. $from = 'year';
  483. $diff = $last - $first;
  484. foreach ($this->auto_granularity as $seconds_count => $granule)
  485. {
  486. if ($diff < $seconds_count)
  487. {
  488. $from = $granule;
  489. break;
  490. }
  491. }
  492. }
  493. // Solve data delta.
  494. $delta = $this->getDelta($first, $last);
  495. if (!$delta) return false;
  496. // Make spellable phrase.
  497. $parts = array();
  498. $intervals = $GLOBALS['lang']['DELTA_TIME']['INTERVALS'];
  499. foreach (array_reverse($delta) as $k => $n)
  500. {
  501. if (!$n)
  502. {
  503. if ($k == $from)
  504. {
  505. if (!$parts)
  506. {
  507. $parts[] = declension($n, $this->intervals[$k], $this->format);
  508. }
  509. break;
  510. }
  511. continue;
  512. }
  513. $parts[] = declension($n, $this->intervals[$k], $this->format);
  514. if ($k == $from) break;
  515. }
  516. return join(' ', $parts);
  517. }
  518. // returns the associative array with date deltas.
  519. function getDelta($first, $last)
  520. {
  521. if ($last < $first) return false;
  522. // Solve H:M:S part.
  523. $hms = ($last - $first) % (3600 * 24);
  524. $delta['seconds'] = $hms % 60;
  525. $delta['minutes'] = floor($hms/60) % 60;
  526. $delta['hours'] = floor($hms/3600) % 60;
  527. // Now work only with date, delta time = 0.
  528. $last -= $hms;
  529. $f = getdate($first);
  530. $l = getdate($last); // the same daytime as $first!
  531. $dYear = $dMon = $dDay = 0;
  532. // Delta day. Is negative, month overlapping.
  533. $dDay += $l['mday'] - $f['mday'];
  534. if ($dDay < 0) {
  535. $monlen = $this->monthLength(date('Y', $first), date('m', $first));
  536. $dDay += $monlen;
  537. $dMon--;
  538. }
  539. $delta['mday'] = $dDay;
  540. // Delta month. If negative, year overlapping.
  541. $dMon += $l['mon'] - $f['mon'];
  542. if ($dMon < 0) {
  543. $dMon += 12;
  544. $dYear --;
  545. }
  546. $delta['mon'] = $dMon;
  547. // Delta year.
  548. $dYear += $l['year'] - $f['year'];
  549. $delta['year'] = $dYear;
  550. return $delta;
  551. }
  552. // Returns the length (in days) of the specified month.
  553. function monthLength($year, $mon)
  554. {
  555. $l = 28;
  556. while (checkdate($mon, $l+1, $year)) $l++;
  557. return $l;
  558. }
  559. }
  560. function delta_time ($timestamp_1, $timestamp_2 = TIMENOW, $granularity = 'auto')
  561. {
  562. return $GLOBALS['DeltaTime']->spellDelta($timestamp_1, $timestamp_2, $granularity);
  563. }
  564. function get_select ($select, $selected = null, $return_as = 'html', $first_opt = '&raquo;&raquo; ??????? ')
  565. {
  566. $select_ary = array();
  567. switch ($select)
  568. {
  569. case 'groups':
  570. $sql = "SELECT group_id, group_name FROM ". BB_GROUPS ." WHERE group_single_user = 0 ORDER BY group_name";
  571. foreach (DB()->fetch_rowset($sql) as $row)
  572. {
  573. $select_ary[$row['group_name']] = $row['group_id'];
  574. }
  575. $select_name = 'g';
  576. break;
  577. case 'forum_tpl':
  578. $sql = "SELECT tpl_id, tpl_name FROM ". BB_TOPIC_TPL ." ORDER BY tpl_name";
  579. $select_ary[$first_opt] = 0;
  580. foreach (DB()->fetch_rowset($sql) as $row)
  581. {
  582. $select_ary[$row['tpl_name']] = $row['tpl_id'];
  583. }
  584. $select_name = 'forum_tpl_select';
  585. break;
  586. }
  587. return ($return_as == 'html') ? build_select($select_name, $select_ary, $selected) : $select_ary;
  588. }
  589. class html_common
  590. {
  591. var $options = '';
  592. var $attr = array();
  593. var $cur_attr = null;
  594. var $max_length = HTML_SELECT_MAX_LENGTH;
  595. var $selected = array();
  596. function build_select ($name, $params, $selected = null, $max_length = HTML_SELECT_MAX_LENGTH, $multiple_size = null, $js = '')
  597. {
  598. if (empty($params)) return '';
  599. $this->options = '';
  600. $this->selected = array_flip((array) $selected);
  601. $this->max_length = $max_length;
  602. $this->attr = array();
  603. $this->cur_attr =& $this->attr;
  604. if (isset($params['__attributes']))
  605. {
  606. $this->attr = $params['__attributes'];
  607. unset($params['__attributes']);
  608. }
  609. $this->_build_select_rec($params);
  610. $select_params = ($js) ? " $js" : '';
  611. $select_params .= ($multiple_size) ? ' multiple="multiple" size="'. $multiple_size .'"' : '';
  612. $select_params .= ' name="'. htmlCHR($name) .'"';
  613. $select_params .= ' id="'. htmlCHR($name) .'"';
  614. return "\n<select $select_params>\n". $this->options ."</select>\n";
  615. }
  616. function _build_select_rec ($params)
  617. {
  618. foreach ($params as $opt_name => $opt_val)
  619. {
  620. $opt_name = rtrim($opt_name);
  621. if (is_array($opt_val))
  622. {
  623. $this->cur_attr =& $this->cur_attr[$opt_name];
  624. $label = htmlCHR(str_short($opt_name, $this->max_length));
  625. $this->options .= "\t<optgroup label=\"&nbsp;". $label ."\">\n";
  626. $this->_build_select_rec($opt_val);
  627. $this->options .= "\t</optgroup>\n";
  628. $this->cur_attr =& $this->attr;
  629. }
  630. else
  631. {
  632. $text = htmlCHR(str_short($opt_name, $this->max_length));
  633. $value = ' value="'. htmlCHR($opt_val) .'"';
  634. $class = isset($this->cur_attr[$opt_name]['class']) ? ' class="'. $this->cur_attr[$opt_name]['class'] .'"' : '';
  635. $style = isset($this->cur_attr[$opt_name]['style']) ? ' style="'. $this->cur_attr[$opt_name]['style'] .'"' : '';
  636. $selected = isset($this->selected[$opt_val]) ? HTML_SELECTED : '';
  637. $disabled = isset($this->cur_attr[$opt_name]['disabled']) ? HTML_DISABLED : '';
  638. $this->options .= "\t\t<option". $class . $style . $selected . $disabled . $value .'>&nbsp;'. $text ."&nbsp;</option>\n";
  639. }
  640. }
  641. }
  642. function array2html ($array, $ul = 'ul', $li = 'li')
  643. {
  644. $this->out = '';
  645. $this->_array2html_rec($array, $ul, $li);
  646. return "<$ul class=\"tree-root\">{$this->out}</$ul>";
  647. }
  648. function _array2html_rec ($array, $ul, $li)
  649. {
  650. foreach ($array as $k => $v)
  651. {
  652. if (is_array($v))
  653. {
  654. $this->out .= "<$li><span class=\"b\">$k</span><$ul>";
  655. $this->_array2html_rec($v, $ul, $li);
  656. $this->out .= "</$ul></$li>";
  657. }
  658. else
  659. {
  660. $this->out .= "<$li><span>$v</span></$li>";
  661. }
  662. }
  663. }
  664. // all arguments should be already htmlspecialchar()d (if needed)
  665. function build_checkbox ($name, $title, $checked = false, $disabled = false, $class = null, $id = null, $value = 1)
  666. {
  667. $name = ' name="'. $name .'" ';
  668. $value = ' value="'. $value .'" ';
  669. $title = ($class) ? '<span class="'. $class .'">'. $title .'</span>' : $title;
  670. $id = ($id) ? " id=\"$id\" " : '';
  671. $checked = ($checked) ? HTML_CHECKED : '';
  672. $disabled = ($disabled) ? HTML_DISABLED : '';
  673. return '<label><input type="checkbox" '. $id . $name . $value . $checked . $disabled .' />&nbsp;'. $title .'&nbsp;</label>';
  674. }
  675. # function build_option ($opt_name, $opt_val, $selected = null, $max_length = false)
  676. # {
  677. # return "\t\t<option value=\"". htmlCHR($opt_val) .'"'. (($selected) ? ' selected="selected"' : '') .'>'. htmlCHR(str_short($opt_name, $max_length)) ."</option>\n";
  678. # }
  679. # function build_optgroup ($label, $contents, $max_length = false)
  680. # {
  681. # return "\t<optgroup label=\"&nbsp;". htmlCHR(str_short($label, $max_length)) ."\">\n". $contents ."\t</optgroup>\n";
  682. # }
  683. }
  684. function build_select ($name, $params, $selected = null, $max_length = HTML_SELECT_MAX_LENGTH, $multiple_size = null, $js = '')
  685. {
  686. global $html;
  687. return $html->build_select($name, $params, $selected, $max_length, $multiple_size, $js);
  688. }
  689. function build_checkbox ($name, $title, $checked = false, $disabled = false, $class = null, $id = null, $value = 1)
  690. {
  691. global $html;
  692. return $html->build_checkbox($name, $title, $checked, $disabled, $class, $id, $value);
  693. }
  694. function replace_quote ($str, $double = true, $single = true)
  695. {
  696. if ($double) $str = str_replace('"', '&quot;', $str);
  697. if ($single) $str = str_replace("'", '&#039;', $str);
  698. return $str;
  699. }
  700. /**
  701. * Build simple hidden fields from array
  702. */
  703. function build_hidden_fields ($fields_ary)
  704. {
  705. $out = "\n";
  706. foreach ($fields_ary as $name => $val)
  707. {
  708. if (is_array($val))
  709. {
  710. foreach ($val as $ary_key => $ary_val)
  711. {
  712. $out .= '<input type="hidden" name="'. $name .'['. $ary_key .']" value="'. $ary_val ."\" />\n";
  713. }
  714. }
  715. else
  716. {
  717. $out .= '<input type="hidden" name="'. $name .'" value="'. $val ."\" />\n";
  718. }
  719. }
  720. return $out;
  721. }
  722. /**
  723. * Choost russian word declension based on numeric [from dklab.ru]
  724. * Example for $expressions: array("?????", "??????", "???????")
  725. */
  726. function declension ($int, $expressions, $format = '%1$s %2$s')
  727. {
  728. if (!is_array($expressions))
  729. {
  730. $expressions = $GLOBALS['lang']['DECLENSION'][strtoupper($expressions)];
  731. }
  732. if (count($expressions) < 3)
  733. {
  734. $expressions[2] = $expressions[1];
  735. }
  736. $count = intval($int) % 100;
  737. if ($count >= 5 && $count <= 20)
  738. {
  739. $result = $expressions['2'];
  740. }
  741. else
  742. {
  743. $count = $count % 10;
  744. if ($count == 1)
  745. {
  746. $result = $expressions['0'];
  747. }
  748. elseif ($count >= 2 && $count <= 4)
  749. {
  750. $result = $expressions['1'];
  751. }
  752. else
  753. {
  754. $result = $expressions['2'];
  755. }
  756. }
  757. return ($format) ? sprintf($format, $int, $result) : $result;
  758. }
  759. // http://forum.dklab.ru/php/advises/UrlreplaceargChangesValueOfParameterInUrl.html
  760. function url_arg ($url, $arg, $value, $amp = '&amp;')
  761. {
  762. $arg = preg_quote($arg, '/');
  763. // ????????? URL ? ANCHOR
  764. $anchor = '';
  765. if (preg_match('/(.*)(#.*)/s', $url, $m))
  766. {
  767. $url = $m[1];
  768. $anchor = $m[2];
  769. }
  770. // ???????? ????????, ???? ?? ??????????
  771. if (preg_match("/((\?|&|&amp;)$arg=)[^&]*/s", $url, $m))
  772. {
  773. $cur = $m[0];
  774. $new = is_null($value) ? '' : $m[1] . urlencode($value);
  775. $url = str_replace($cur, $new, $url);
  776. }
  777. // ????????? ????????
  778. else if (!is_null($value))
  779. {
  780. $div = (strpos($url, '?') !== false) ? $amp : '?';
  781. $url = $url . $div . $arg .'='. urlencode($value);
  782. }
  783. return $url . $anchor;
  784. }
  785. /**
  786. * Adds commas between every group of thousands
  787. */
  788. function commify ($number)
  789. {
  790. return number_format($number);
  791. }
  792. /**
  793. * Returns a size formatted in a more human-friendly format, rounded to the nearest GB, MB, KB..
  794. */
  795. function humn_size ($size, $rounder = null, $min = null, $space = '&nbsp;')
  796. {
  797. static $sizes = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
  798. static $rounders = array(0, 0, 0, 2, 3, 3, 3, 3, 3);
  799. $size = (float) $size;
  800. $ext = $sizes[0];
  801. $rnd = $rounders[0];
  802. if ($min == 'KB' && $size < 1024)
  803. {
  804. $size = $size / 1024;
  805. $ext = 'KB';
  806. $rounder = 1;
  807. }
  808. else
  809. {
  810. for ($i=1, $cnt=count($sizes); ($i < $cnt && $size >= 1024); $i++)
  811. {
  812. $size = $size / 1024;
  813. $ext = $sizes[$i];
  814. $rnd = $rounders[$i];
  815. }
  816. }
  817. if (!$rounder)
  818. {
  819. $rounder = $rnd;
  820. }
  821. return round($size, $rounder) . $space . $ext;
  822. }
  823. function bt_show_ip ($ip, $port = '')
  824. {
  825. global $bb_cfg;
  826. if (IS_AM)
  827. {
  828. $ip = decode_ip($ip);
  829. $ip .= ($port) ? ":$port" : '';
  830. return $ip;
  831. }
  832. else
  833. {
  834. return ($bb_cfg['bt_show_ip_only_moder']) ? false : decode_ip_xx($ip);
  835. }
  836. }
  837. function bt_show_port ($port)
  838. {
  839. global $bb_cfg;
  840. if (IS_AM)
  841. {
  842. return $port;
  843. }
  844. else
  845. {
  846. return ($bb_cfg['bt_show_port_only_moder']) ? false : $port;
  847. }
  848. }
  849. function decode_ip_xx ($ip)
  850. {
  851. $h = explode('.', chunk_split($ip, 2, '.'));
  852. return hexdec($h[0]) .'.'. hexdec($h[1]) .'.'. hexdec($h[2]) .'.xx';
  853. }
  854. function checkbox_get_val (&$key, &$val, $default = 1, $on = 1, $off = 0)
  855. {
  856. global $previous_settings, $search_id;
  857. if (isset($_REQUEST[$key]) && is_string($_REQUEST[$key]))
  858. {
  859. $val = (int) $_REQUEST[$key];
  860. }
  861. else if (!isset($_REQUEST[$key]) && isset($_REQUEST['prev_'. $key]))
  862. {
  863. $val = $off;
  864. }
  865. else if (isset($previous_settings[$key]) && (!IS_GUEST || !empty($search_id)))
  866. {
  867. $val = ($previous_settings[$key]) ? $on : $off;
  868. }
  869. else
  870. {
  871. $val = $default;
  872. }
  873. }
  874. function select_get_val ($key, &$val, $options_ary, $default, $num = true)
  875. {
  876. global $previous_settings;
  877. if (isset($_REQUEST[$key]) && is_string($_REQUEST[$key]))
  878. {
  879. if (isset($options_ary[$_REQUEST[$key]]))
  880. {
  881. $val = ($num) ? intval($_REQUEST[$key]) : $_REQUEST[$key];
  882. }
  883. }
  884. else if (isset($previous_settings[$key]))
  885. {
  886. $val = $previous_settings[$key];
  887. }
  888. else
  889. {
  890. $val = $default;
  891. }
  892. }
  893. /**
  894. * set_var
  895. *
  896. * Set variable, used by {@link request_var the request_var function}
  897. *
  898. * @access private
  899. */
  900. function set_var(&$result, $var, $type, $multibyte = false, $strip = true)
  901. {
  902. settype($var, $type);
  903. $result = $var;
  904. if ($type == 'string')
  905. {
  906. $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r"), array("\n", "\n"), $result)));
  907. if (!empty($result))
  908. {
  909. // Make sure multibyte characters are wellformed
  910. if ($multibyte)
  911. {
  912. if (!preg_match('/^./u', $result))
  913. {
  914. $result = '';
  915. }
  916. }
  917. }
  918. $result = ($strip) ? stripslashes($result) : $result;
  919. }
  920. }
  921. /**
  922. * request_var
  923. *
  924. * Used to get passed variable
  925. */
  926. function request_var($var_name, $default, $multibyte = false, $cookie = false)
  927. {
  928. if (!$cookie && isset($_COOKIE[$var_name]))
  929. {
  930. if (!isset($_GET[$var_name]) && !isset($_POST[$var_name]))
  931. {
  932. return (is_array($default)) ? array() : $default;
  933. }
  934. $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
  935. }
  936. if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name])))
  937. {
  938. return (is_array($default)) ? array() : $default;
  939. }
  940. $var = $_REQUEST[$var_name];
  941. if (!is_array($default))
  942. {
  943. $type = gettype($default);
  944. }
  945. else
  946. {
  947. list($key_type, $type) = each($default);
  948. $type = gettype($type);
  949. $key_type = gettype($key_type);
  950. if ($type == 'array')
  951. {
  952. reset($default);
  953. $default = current($default);
  954. list($sub_key_type, $sub_type) = each($default);
  955. $sub_type = gettype($sub_type);
  956. $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type;
  957. $sub_key_type = gettype($sub_key_type);
  958. }
  959. }
  960. if (is_array($var))
  961. {
  962. $_var = $var;
  963. $var = array();
  964. foreach ($_var as $k => $v)
  965. {
  966. set_var($k, $k, $key_type);
  967. if ($type == 'array' && is_array($v))
  968. {
  969. foreach ($v as $_k => $_v)
  970. {
  971. if (is_array($_v))
  972. {
  973. $_v = null;
  974. }
  975. set_var($_k, $_k, $sub_key_type);
  976. set_var($var[$k][$_k], $_v, $sub_type, $multibyte);
  977. }
  978. }
  979. else
  980. {
  981. if ($type == 'array' || is_array($v))
  982. {
  983. $v = null;
  984. }
  985. set_var($var[$k], $v, $type, $multibyte);
  986. }
  987. }
  988. }
  989. else
  990. {
  991. set_var($var, $var, $type, $multibyte);
  992. }
  993. return $var;
  994. }
  995. function get_username ($user_id)
  996. {
  997. if (empty($user_id))
  998. {
  999. return is_array($user_id) ? array() : false;
  1000. }
  1001. if (is_array($user_id))
  1002. {
  1003. $usernames = array();
  1004. foreach (DB()->fetch_rowset("SELECT user_id, username FROM ". BB_USERS ." WHERE user_id IN(". get_id_csv($user_id) .")") as $row)
  1005. {
  1006. $usernames[$row['user_id']] = $row['username'];
  1007. }
  1008. return $usernames;
  1009. }
  1010. else
  1011. {
  1012. $row = DB()->fetch_row("SELECT username FROM ". BB_USERS ." WHERE user_id = $user_id LIMIT 1");
  1013. return $row['username'];
  1014. }
  1015. }
  1016. function get_user_id ($username)
  1017. {
  1018. if (empty($username)) return false;
  1019. $row = DB()->fetch_row("SELECT user_id FROM ". BB_USERS ." WHERE username = '". DB()->escape($username) ."' LIMIT 1");
  1020. return $row['user_id'];
  1021. }
  1022. function str_short ($text, $max_length, $space = ' ')
  1023. {
  1024. if ($max_length && mb_strlen($text, 'UTF-8') > $max_length)
  1025. {
  1026. $text = mb_substr($text, 0, $max_length, 'UTF-8');
  1027. if ($last_space_pos = $max_length - intval(strpos(strrev($text), $space)))
  1028. {
  1029. if ($last_space_pos > round($max_length * 3/4))
  1030. {
  1031. $last_space_pos--;
  1032. $text = mb_substr($text, 0, $last_space_pos, 'UTF-8');
  1033. }
  1034. }
  1035. $text .= '...';
  1036. $text = preg_replace('!&#?(\w+)?;?(\w{1,5})?\.\.\.$!', '...', $text);
  1037. }
  1038. return $text;
  1039. }
  1040. function wbr ($text, $max_word_length = HTML_WBR_LENGTH)
  1041. {
  1042. return preg_replace("/([\w\->;:.,~!?(){}@#$%^*\/\\\\]{". $max_word_length ."})/ui", '$1<wbr>', $text);
  1043. }
  1044. function get_bt_userdata ($user_id)
  1045. {
  1046. return DB()->fetch_row("SELECT bt.*, SUM(tr.speed_up) as speed_up, SUM(tr.speed_down) as speed_down
  1047. FROM ". BB_BT_USERS ." bt
  1048. LEFT JOIN ". BB_BT_TRACKER ." tr ON (bt.user_id = tr.user_id)
  1049. WHERE bt.user_id = ". (int) $user_id ."
  1050. GROUP BY bt.user_id");
  1051. }
  1052. function get_bt_ratio ($btu)
  1053. {
  1054. return
  1055. (!empty($btu['u_down_total']) && $btu['u_down_total'] > MIN_DL_FOR_RATIO)
  1056. ? round((($btu['u_up_total'] + $btu['u_up_release'] + $btu['u_up_bonus']) / $btu['u_down_total']), 2)
  1057. : null
  1058. ;
  1059. }
  1060. function show_bt_userdata ($user_id)
  1061. {
  1062. global $lang, $template;
  1063. $btu = get_bt_userdata($user_id);
  1064. $template->assign_vars(array(
  1065. 'SHOW_BT_USERDATA' => true,
  1066. 'UP_TOTAL' => humn_size($btu['u_up_total']),
  1067. 'UP_BONUS' => humn_size($btu['u_up_bonus']),
  1068. 'RELEASED' => humn_size($btu['u_up_release']),
  1069. 'DOWN_TOTAL' => humn_size($btu['u_down_total']),
  1070. 'DOWN_TOTAL_BYTES' => $btu['u_down_total'],
  1071. 'USER_RATIO' => get_bt_ratio($btu),
  1072. 'MIN_DL_FOR_RATIO' => humn_size(MIN_DL_FOR_RATIO),
  1073. 'MIN_DL_BYTES' => MIN_DL_FOR_RATIO,
  1074. 'AUTH_KEY' => ($btu['auth_key']) ? $btu['auth_key'] : $lang['NONE'],
  1075. 'TD_DL' => humn_size($btu['down_today']),
  1076. 'TD_UL' => humn_size($btu['up_today']),
  1077. 'TD_REL' => humn_size($btu['up_release_today']),
  1078. 'TD_BONUS' => humn_size($btu['up_bonus_today']),
  1079. 'TD_POINTS' => ($btu['auth_key']) ? $btu['points_today'] : '0.00',
  1080. 'YS_DL' => humn_size($btu['down_yesterday']),
  1081. 'YS_UL' => humn_size($btu['up_yesterday']),
  1082. 'YS_REL' => humn_size($btu['up_release_yesterday']),
  1083. 'YS_BONUS' => humn_size($btu['up_bonus_yesterday']),
  1084. 'YS_POINTS' => ($btu['auth_key']) ? $btu['points_yesterday'] : '0.00',
  1085. 'SPEED_UP' => humn_size($btu['speed_up'], 0, 'KB') .'/s',
  1086. 'SPEED_DOWN' => humn_size($btu['speed_down'], 0, 'KB') .'/s',
  1087. ));
  1088. }
  1089. function get_attachments_dir ($cfg = null)
  1090. {
  1091. if (!$cfg AND !$cfg = $GLOBALS['attach_config'])
  1092. {
  1093. $cfg = bb_get_config(BB_ATTACH_CONFIG, true, false);
  1094. }
  1095. if (!$cfg['allow_ftp_upload'])
  1096. {
  1097. if ($cfg['upload_dir'][0] == '/' || ($cfg['upload_dir'][0] != '/' && $cfg['upload_dir'][1] == ':'))
  1098. {
  1099. return $cfg['upload_dir'];
  1100. }
  1101. else
  1102. {
  1103. return BB_ROOT . $cfg['upload_dir'];
  1104. }
  1105. }
  1106. else
  1107. {
  1108. return $cfg['download_path'];
  1109. }
  1110. }
  1111. function bb_get_config ($table, $from_db = false, $update_cache = true)
  1112. {
  1113. if ($from_db OR !$cfg = CACHE('bb_cache')->get("config_{$table}"))
  1114. {
  1115. $cfg = array();
  1116. foreach (DB()->fetch_rowset("SELECT * FROM $table") as $row)
  1117. {
  1118. $cfg[$row['config_name']] = $row['config_value'];
  1119. }
  1120. if ($update_cache)
  1121. {
  1122. CACHE('bb_cache')->set("config_{$table}", $cfg);
  1123. }
  1124. }
  1125. return $cfg;
  1126. }
  1127. function bb_update_config ($params, $table = BB_CONFIG)
  1128. {
  1129. $updates = array();
  1130. foreach ($params as $name => $val)
  1131. {
  1132. $updates[] = array(
  1133. 'config_name' => $name,
  1134. 'config_value' => $val,
  1135. );
  1136. }
  1137. $updates = DB()->build_array('MULTI_INSERT', $updates);
  1138. DB()->query("REPLACE INTO $table $updates");
  1139. // Update cache
  1140. bb_get_config($table, true, true);
  1141. }
  1142. function get_db_stat($mode)
  1143. {
  1144. switch( $mode )
  1145. {
  1146. case 'usercount':
  1147. $sql = "SELECT COUNT(user_id) AS total
  1148. FROM " . BB_USERS;
  1149. break;
  1150. case 'newestuser':
  1151. $sql = "SELECT user_id, username
  1152. FROM " . BB_USERS . "
  1153. WHERE user_id <> " . GUEST_UID . "
  1154. ORDER BY user_id DESC
  1155. LIMIT 1";
  1156. break;
  1157. case 'postcount':
  1158. case 'topiccount':
  1159. $sql = "SELECT SUM(forum_topics) AS topic_total, SUM(forum_posts) AS post_total
  1160. FROM " . BB_FORUMS;
  1161. break;
  1162. }
  1163. if ( !($result = DB()->sql_query($sql)) )
  1164. {
  1165. return false;
  1166. }
  1167. $row = DB()->sql_fetchrow($result);
  1168. switch ( $mode )
  1169. {
  1170. case 'usercount':
  1171. return $row['total'];
  1172. break;
  1173. case 'newestuser':
  1174. return $row;
  1175. break;
  1176. case 'postcount':
  1177. return $row['post_total'];
  1178. break;
  1179. case 'topiccount':
  1180. return $row['topic_total'];
  1181. break;
  1182. }
  1183. return false;
  1184. }
  1185. function clean_username($username)
  1186. {
  1187. $username = mb_substr(htmlspecialchars(str_replace("\'", "'", trim($username))), 0, 25, 'UTF-8');
  1188. $username = bb_rtrim($username, "\\");
  1189. $username = str_replace("'", "\'", $username);
  1190. return $username;
  1191. }
  1192. function bb_ltrim($str, $charlist = false)
  1193. {
  1194. if ($charlist === false)
  1195. {
  1196. return ltrim($str);
  1197. }
  1198. $str = ltrim($str, $charlist);
  1199. return $str;
  1200. }
  1201. function bb_rtrim($str, $charlist = false)
  1202. {
  1203. if ($charlist === false)
  1204. {
  1205. return rtrim($str);
  1206. }
  1207. $str = rtrim($str, $charlist);
  1208. return $str;
  1209. }
  1210. // Get Userdata, $u can be username or user_id. If $force_name is true, the username will be forced.
  1211. function get_userdata ($u, $force_name = false, $allow_guest = false)
  1212. {
  1213. if (!$u) return false;
  1214. if (intval($u) == GUEST_UID && $allow_guest)
  1215. {
  1216. if ($u_data = CACHE('bb_cache')->get('guest_userdata'))
  1217. {
  1218. return $u_data;
  1219. }
  1220. }
  1221. $u_data = array();
  1222. $name_search = false;
  1223. $exclude_anon_sql = (!$allow_guest) ? "AND user_id != ". GUEST_UID : '';
  1224. if ($force_name || !is_numeric($u))
  1225. {
  1226. $name_search = true;
  1227. $where_sql = "WHERE username = '". DB()->escape(clean_username($u)) ."'";
  1228. }
  1229. else
  1230. {
  1231. $where_sql = "WHERE user_id = ". (int) $u;
  1232. }
  1233. $sql = "SELECT * FROM ". BB_USERS ." $where_sql $exclude_anon_sql LIMIT 1";
  1234. if (!$u_data = DB()->fetch_row($sql))
  1235. {
  1236. if (!is_int($u) && !$name_search)
  1237. {
  1238. $where_sql = "WHERE username = '". DB()->escape(clean_username($u)) ."'";
  1239. $sql = "SELECT * FROM ". BB_USERS ." $where_sql $exclude_anon_sql LIMIT 1";
  1240. $u_data = DB()->fetch_row($sql);
  1241. }
  1242. }
  1243. if ($u_data['user_id'] == GUEST_UID)
  1244. {
  1245. CACHE('bb_cache')->set('guest_userdata', $u_data);
  1246. }
  1247. return $u_data;
  1248. }
  1249. function make_jumpbox ($selected = 0)
  1250. {
  1251. global $datastore, $template;
  1252. if (!$jumpbox = $datastore->get('jumpbox'))
  1253. {
  1254. $datastore->update('jumpbox');
  1255. $jumpbox = $datastore->get('jumpbox');
  1256. }
  1257. $template->assign_vars(array(
  1258. 'JUMPBOX' => (IS_GUEST) ? $jumpbox['guest'] : $jumpbox['user'],
  1259. ));
  1260. }
  1261. // $mode: array(not_auth_forum1,not_auth_forum2,..) or (string) 'mode'
  1262. function get_forum_select ($mode = 'guest', $name = POST_FORUM_URL, $selected = null, $max_length = HTML_SELECT_MAX_LENGTH, $multiple_size = null, $js = '', $all_forums_option = null)
  1263. {
  1264. global $lang, $datastore;
  1265. if (is_array($mode))
  1266. {
  1267. $not_auth_forums_fary = array_flip($mode);
  1268. $mode = 'not_auth_forums';
  1269. }
  1270. if (is_null($max_length))
  1271. {
  1272. $max_length = HTML_SELECT_MAX_LENGTH;
  1273. }
  1274. $select = is_null($all_forums_option) ? array() : array($lang['ALL_AVAILABLE'] => $all_forums_option);
  1275. if (!$forums = $datastore->get('cat_forums'))
  1276. {
  1277. $datastore->update('cat_forums');
  1278. $forums = $datastore->get('cat_forums');
  1279. }
  1280. foreach ($forums['f'] as $fid => $f)
  1281. {
  1282. switch ($mode)
  1283. {
  1284. case 'guest':
  1285. if ($f['auth_view'] != AUTH_ALL) continue 2;
  1286. break;
  1287. case 'user':
  1288. if ($f['auth_view'] != AUTH_ALL && $f['auth_view'] != AUTH_REG) continue 2;
  1289. break;
  1290. case 'not_auth_forums':
  1291. if (isset($not_auth_forums_fary[$f['forum_id']])) continue 2;
  1292. break;
  1293. case 'admin':
  1294. break;
  1295. default:
  1296. trigger_error(__FUNCTION__ .": invalid mode '$mode'", E_USER_ERROR);
  1297. }
  1298. $cat_title = $forums['c'][$f['cat_id']]['cat_title'];
  1299. $f_name = ($f['forum_parent']) ? ' |- ' : '';
  1300. $f_name .= $f['forum_name'];
  1301. while (isset($select[$cat_title][$f_name]))
  1302. {
  1303. $f_name .= ' ';
  1304. }
  1305. $select[$cat_title][$f_name] = $fid;
  1306. if (!$f['forum_parent'])
  1307. {
  1308. $class = 'root_forum';
  1309. $class .= isset($f['subforums']) ? ' has_sf' : '';
  1310. $select['__attributes'][$cat_title][$f_name]['class'] = $class;
  1311. }
  1312. }
  1313. return build_select($name, $select, $selected, $max_length, $multiple_size, $js);
  1314. }
  1315. function setup_style ()
  1316. {
  1317. global $bb_cfg, $template, $userdata;
  1318. // AdminCP works only with default template
  1319. $tpl_dir_name = defined('IN_ADMIN') ? 'default' : basename($bb_cfg['tpl_name']);
  1320. $stylesheet = defined('IN_ADMIN') ? 'main.css' : basename($bb_cfg['stylesheet']);
  1321. if (!IS_GUEST && !empty($userdata['tpl_name']))
  1322. {
  1323. foreach ($bb_cfg['templates'] as $folder => $name)
  1324. {
  1325. if ($userdata['tpl_name'] == $folder) $tpl_dir_name = basename($userdata['tpl_name']);
  1326. }
  1327. }
  1328. $template = new Template(TEMPLATES_DIR . $tpl_dir_name);
  1329. $css_dir = basename(TEMPLATES_DIR) ."/$tpl_dir_name/css/";
  1330. $template->assign_vars(array(
  1331. 'BB_ROOT' => BB_ROOT,
  1332. 'SPACER' => make_url('/images/spacer.gif'),
  1333. 'STYLESHEET' => make_url($css_dir . $stylesheet),
  1334. 'EXT_LINK_NEW_WIN' => $bb_cfg['ext_link_new_win'],
  1335. 'TPL_DIR' => make_url($css_dir),
  1336. 'SITE_URL' => make_url('/'),
  1337. ));
  1338. require(TEMPLATES_DIR . $tpl_dir_name .'/tpl_config.php');
  1339. $theme = array('template_name' => $tpl_dir_name);
  1340. return $theme;
  1341. }
  1342. // Create date/time from format and timezone
  1343. function bb_date ($gmepoch, $format = false, $tz = null)
  1344. {
  1345. global $bb_cfg, $lang, $userdata;
  1346. if (!$format) $format = $bb_cfg['default_dateformat'];
  1347. if (empty($lang)) require_once($bb_cfg['default_lang_dir'] .'lang_main.php');
  1348. if (is_null($tz) || $tz == 'false')
  1349. {
  1350. if (empty($userdata['session_logged_in']))
  1351. {
  1352. $tz2 = $bb_cfg['board_timezone'];
  1353. }
  1354. else $tz2 = $userdata['user_timezone'];
  1355. }
  1356. elseif (is_numeric($tz)) $tz2 = $tz;
  1357. $date = gmdate($format, $gmepoch + (3600 * $tz2));
  1358. if ($tz != 'false')
  1359. {
  1360. $time_format = " H:i";
  1361. $today = gmdate("d", TIMENOW + (3600 * $tz2));
  1362. $month = gmdate("m", TIMENOW + (3600 * $tz2));
  1363. $year = gmdate("Y", TIMENOW + (3600 * $tz2));
  1364. $date_today = gmdate("d", $gmepoch + (3600 * $tz2));
  1365. $date_month = gmdate("m", $gmepoch + (3600 * $tz2));
  1366. $date_year = gmdate("Y", $gmepoch + (3600 * $tz2));
  1367. if ($date_today == $today && $date_month == $month && $date_year == $year)
  1368. {
  1369. $date = 'today' . gmdate($time_format, $gmepoch + (3600 * $tz2));
  1370. }
  1371. elseif ($today != 1 && $date_today == ($today-1) && $date_month == $month && $date_year == $year)
  1372. {
  1373. $date = 'yesterday' . gmdate($time_format, $gmepoch + (3600 * $tz2));
  1374. }
  1375. elseif ($today == 1 && $month != 1)
  1376. {
  1377. $yesterday = date ("t", mktime(0, 0, 0, ($month-1), 1, $year));
  1378. if ($date_today == $yesterday && $date_month == ($month-1) && $date_year == $year)
  1379. $date = 'yesterday' . gmdate($time_format, $gmepoch + (3600 * $tz2));
  1380. }
  1381. elseif ($today == 1 && $month == 1)
  1382. {
  1383. $yesterday = date ("t", mktime(0, 0, 0, 12, 1, ($year -1)));
  1384. if ($date_today == $yesterday && $date_month == 12 && $date_year == ($year-1))
  1385. $date = 'yesterday' . gmdate($time_format, $gmepoch + (3600 * $tz));
  1386. }
  1387. }
  1388. return ($bb_cfg['translate_dates']) ? strtr(strtoupper($date), $lang['DATETIME']) : $date;
  1389. }
  1390. // Birthday
  1391. // Add function mkrealdate for Birthday MOD
  1392. // the originate php "mktime()", does not work proberly on all OS, especially when going back in time
  1393. // before year 1970 (year 0), this function "mkrealtime()", has a mutch larger valid date range,
  1394. // from 1901 - 2099. it returns a "like" UNIX timestamp divided by 86400, so
  1395. // calculation from the originate php date and mktime is easy.
  1396. // mkrealdate, returns the number of day (with sign) from 1.1.1970.
  1397. function mkrealdate ($day, $month, $birth_year)
  1398. {
  1399. // define epoch
  1400. $epoch = 0;
  1401. // range check months
  1402. if ($month < 1 || $month > 12) return "error";
  1403. // range check days
  1404. switch ($month)
  1405. {
  1406. case 1: if ($day > 31) return "error"; break;
  1407. case 2: if ($day > 29) return "error";
  1408. $epoch = $epoch+31; break;
  1409. case 3: if ($day > 31) return "error";
  1410. $epoch = $epoch+59; break;
  1411. case 4: if ($day > 30) return "error" ;
  1412. $epoch = $epoch+90; break;
  1413. case 5: if ($day > 31) return "error";
  1414. $epoch = $epoch+120; break;
  1415. case 6: if ($day > 30) return "error";
  1416. $epoch = $epoch+151; break;
  1417. case 7: if ($day > 31) return "error";
  1418. $epoch = $epoch+181; break;
  1419. case 8: if ($day > 31) return "error";
  1420. $epoch = $epoch+212; break;
  1421. case 9: if ($day > 30) return "error";
  1422. $epoch = $epoch+243; break;
  1423. case 10: if ($day > 31) return "error";
  1424. $epoch = $epoch+273; break;
  1425. case 11: if ($day > 30) return "error";
  1426. $epoch = $epoch+304; break;
  1427. case 12: if ($day > 31) return "error";
  1428. $epoch = $epoch+334; break;
  1429. }
  1430. $epoch = $epoch+$day;
  1431. $epoch_Y = sqrt(($birth_year-1970)*($birth_year-1970));
  1432. $leapyear = round((($epoch_Y+2) / 4)-.5);
  1433. if (($epoch_Y+2)%4 == 0)
  1434. {// curent year is leapyear
  1435. $leapyear--;
  1436. if ($birth_year > 1970 && $month >= 3) $epoch = $epoch+1;
  1437. if ($birth_year < 1970 && $month < 3) $epoch = $epoch-1;
  1438. }
  1439. else if ($month == 2 && $day > 28) return "error";//only 28 days in feb.
  1440. //year
  1441. if ($birth_year > 1970)
  1442. {
  1443. $epoch = $epoch + $epoch_Y*365-1 + $leapyear;
  1444. }
  1445. else
  1446. {
  1447. $epoch = $epoch - $epoch_Y*365-1 - $leapyear;
  1448. }
  1449. return $epoch;
  1450. }
  1451. // Add function realdate for Birthday MOD
  1452. // the originate php "date()", does not work proberly on all OS, especially when going back in time
  1453. // before year 1970 (year 0), this function "realdate()", has a mutch larger valid date range,
  1454. // from 1901 - 2099. it returns a "like" UNIX date format (only date, related letters may be used, due to the fact that
  1455. // the given date value should already be divided by 86400 - leaving no time information left)
  1456. // a input like a UNIX timestamp divided by 86400 is expected, so
  1457. // calculation from the originate php date and mktime is easy.
  1458. // e.g. realdate ("m d Y", 3) returns the string "1 3 1970"
  1459. // UNIX users should replace this function with the below code, since this should be faster
  1460. //
  1461. function realdate ($date, $format = "Ymd")
  1462. {
  1463. if (!$date) return;
  1464. return bb_date($date*86400 + 1, $format, 0);
  1465. }
  1466. function birthday_age ($date, $list = 0)
  1467. {
  1468. if (!$date) return;
  1469. return delta_time(mktime(11, 0, 0, date('m', strtotime($date)), date('d', strtotime($date)), (date('Y', strtotime($date)) - $list)));
  1470. }
  1471. //
  1472. // Pagination routine, generates
  1473. // page number sequence
  1474. //
  1475. function generate_pagination ($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = TRUE)
  1476. {
  1477. global $lang, $template;
  1478. // Pagination Mod
  1479. $begin_end = 3;
  1480. $from_middle = 1;
  1481. /*
  1482. By default, $begin_end is 3, and $from_middle is 1, so on page 6 in a 12 page view, it will look like this:
  1483. a, d = $begin_end = 3
  1484. b, c = $from_middle = 1
  1485. "begin" "middle" "end"
  1486. | | |
  1487. | a b | c d |
  1488. | | | | | | |
  1489. v v v v v v v
  1490. 1, 2, 3 ... 5, 6, 7 ... 10, 11, 12
  1491. Change $begin_end and $from_middle to suit your needs appropriately
  1492. */
  1493. $total_pages = ceil($num_items/$per_page);
  1494. if ( $total_pages == 1 || $num_items == 0 )
  1495. {
  1496. return '';
  1497. }
  1498. $on_page = floor($start_item / $per_page) + 1;
  1499. $page_string = '';
  1500. if ( $total_pages > ((2*($begin_end + $from_middle)) + 2) )
  1501. {
  1502. $init_page_max = ( $total_pages > $begin_end ) ? $begin_end : $total_pages;
  1503. for($i = 1; $i < $init_page_max + 1; $i++)
  1504. {
  1505. $page_string .= ( $i == $on_page ) ? '<b>' . $i . '</b>' : '<a href="' . $base_url . "&amp;start=" . ( ( $i - 1 ) * $per_page ) . '">' . $i . '</a>';
  1506. if ( $i < $init_page_max )
  1507. {
  1508. $page_string .= ", ";
  1509. }
  1510. }
  1511. if ( $total_pages > $begin_end )
  1512. {
  1513. if ( $on_page > 1 && $on_page < $total_pages )
  1514. {
  1515. $page_string .= ( $on_page > ($begin_end + $from_middle + 1) ) ? ' ... ' : ', ';
  1516. $init_page_min = ( $on_page > ($begin_end + $from_middle) ) ? $on_page : ($begin_end + $from_middle + 1);
  1517. $init_page_max = ( $on_page < $total_pages - ($begin_end + $from_middle) ) ? $on_page : $total_pages - ($begin_end + $from_middle);
  1518. for($i = $init_page_min - $from_middle; $i < $init_page_max + ($from_middle + 1); $i++)
  1519. {
  1520. $page_string .= ($i == $on_page) ? '<b>' . $i . '</b>' : '<a href="' . $base_url . "&amp;start=" . ( ( $i - 1 ) * $per_page ) . '">' . $i . '</a>';
  1521. if ( $i < $init_page_max + $from_middle )
  1522. {
  1523. $page_string .= ', ';
  1524. }
  1525. }
  1526. $page_string .= ( $on_page < $total_pages - ($begin_end + $from_middle) ) ? ' ... ' : ', ';
  1527. }
  1528. else
  1529. {
  1530. $page_string .= '&nbsp;...&nbsp;';
  1531. }
  1532. for($i = $total_pages - ($begin_end - 1); $i < $total_pages + 1; $i++)
  1533. {
  1534. $page_string .= ( $i == $on_page ) ? '<b>' . $i . '</b>' : '<a href="' . $base_url . "&amp;start=" . ( ( $i - 1 ) * $per_page ) . '">' . $i . '</a>';
  1535. if( $i < $total_pages )
  1536. {
  1537. $page_string .= ", ";
  1538. }
  1539. }
  1540. }
  1541. }
  1542. else
  1543. {
  1544. for($i = 1; $i < $total_pages + 1; $i++)
  1545. {
  1546. $page_string .= ( $i == $on_page ) ? '<b>' . $i . '</b>' : '<a href="' . $base_url . "&amp;start=" . ( ( $i - 1 ) * $per_page ) . '">' . $i . '</a>';
  1547. if ( $i < $total_pages )
  1548. {
  1549. $page_string .= ', ';
  1550. }
  1551. }
  1552. }
  1553. if ( $add_prevnext_text )
  1554. {
  1555. if ( $on_page > 1 )
  1556. {
  1557. $page_string = ' <a href="' . $base_url . "&amp;start=" . ( ( $on_page - 2 ) * $per_page ) . '">' . $lang['PREVIOUS_PAGE'] . '</a>&nbsp;&nbsp;' . $page_string;
  1558. }
  1559. if ( $on_page < $total_pages )
  1560. {
  1561. $page_string .= '&nbsp;&nbsp;<a href="' . $base_url . "&amp;start=" . ( $on_page * $per_page ) . '">' . $lang['NEXT_PAGE'] . '</a>';
  1562. }
  1563. }
  1564. $pagination = ($page_string) ? '<a class="menu-root" href="#pg-jump">'. $lang['GOTO_PAGE'] .'</a> :&nbsp;&nbsp;'. $page_string : '';
  1565. $pagination = str_replace('&amp;start=0', '', $pagination);
  1566. $template->assign_vars(array(
  1567. 'PAGINATION' => $pagination,
  1568. 'PAGE_NUMBER' => sprintf($lang['PAGE_OF'], ( floor($start_item/$per_page) + 1 ), ceil( $num_items / $per_page )),
  1569. 'PG_BASE_URL' => $base_url,
  1570. 'PG_PER_PAGE' => $per_page,
  1571. ));
  1572. return $pagination;
  1573. }
  1574. //
  1575. // This does exactly what preg_quote() does in PHP 4-ish
  1576. // If you just need the 1-parameter preg_quote call, then don't bother using this.
  1577. //
  1578. function bb_preg_quote($str, $delimiter)
  1579. {
  1580. $text = preg_quote($str);
  1581. $text = str_replace($delimiter, '\\' . $delimiter, $text);
  1582. return $text;
  1583. }
  1584. //
  1585. // Obtain list of naughty words and build preg style replacement arrays for use by the
  1586. // calling script, note that the vars are passed as references this just makes it easier
  1587. // to return both sets of arrays
  1588. //
  1589. function obtain_word_list(&$orig_word, &$replacement_word)
  1590. {
  1591. global $bb_cfg;
  1592. if (!$bb_cfg['use_word_censor']) return;
  1593. if (!$sql = CACHE('bb_cache')->get('censored'))
  1594. {
  1595. $sql = DB()->fetch_rowset("SELECT word, replacement FROM ". BB_WORDS);
  1596. if(!$sql) $sql = array(array('word' => 1, 'replacement' => 1));
  1597. CACHE('bb_cache')->set('censored', $sql, 7200);
  1598. }
  1599. foreach($sql as $row)
  1600. {
  1601. //$orig_word[] = '#(?<!\S)(' . str_replace('\*', '\S*?', preg_quote($row['word'], '#')) . ')(?!\S)#iu';
  1602. $orig_word[] = '#(?<![\p{Nd}\p{L}_])(' . str_replace('\*', '[\p{Nd}\p{L}_]*?', preg_quote($row['word'], '#')) . ')(?![\p{Nd}\p{L}_])#iu';
  1603. $replacement_word[] = $row['replacement'];
  1604. }
  1605. return true;
  1606. }
  1607. function smiley_sort ($a, $b)
  1608. {
  1609. if (strlen($a['code']) == strlen($b['code']))
  1610. {
  1611. return 0;
  1612. }
  1613. return (strlen($a['code']) > strlen($b['code'])) ? -1 : 1;
  1614. }
  1615. function bb_die ($msg_text)
  1616. {
  1617. if (defined('IN_AJAX'))
  1618. {
  1619. $GLOBALS['ajax']->ajax_die($msg

Large files files are truncated, but you can click here to view the full file