· 8 years ago · May 08, 2018, 03:44 PM
1<?php
2/* by Tomasz 'Devilshakerz' Mlynski [devilshakerz.com]; Copyright (C) 2014-2017
3 released under Creative Commons BY-NC-SA 4.0 license: https://creativecommons.org/licenses/by-nc-sa/4.0/ */
4
5$plugins->add_hook('global_start', ['dvz_shoutbox', 'global_start']); // cache shoutbox templates
6$plugins->add_hook('global_end', ['dvz_shoutbox', 'global_end']); // catch archive page
7$plugins->add_hook('xmlhttp', ['dvz_shoutbox', 'xmlhttp']); // xmlhttp.php listening
8$plugins->add_hook('index_end', ['dvz_shoutbox', 'load_window']); // load Shoutbox window to {$dvz_shoutbox} variable
9$plugins->add_hook('index_start', 'dvz_shoutbox_stats'); //Stas index
10$plugins->add_hook('index_start', 'dvz_shoutbox_users_on_sb'); //Kto jest online
11
12$plugins->add_hook('admin_config_settings_change', ['dvz_shoutbox', 'admin_config_settings_change']);
13$plugins->add_hook('admin_user_users_merge_commit', ['dvz_shoutbox', 'user_merge']);
14
15$plugins->add_hook('fetch_wol_activity_end', ['dvz_shoutbox', 'activity']); // catch activity
16$plugins->add_hook('build_friendly_wol_location_end', ['dvz_shoutbox', 'activity_translate']); // translate activity
17
18$plugins->add_hook('misc_clearcookies', ['dvz_shoutbox', 'clearcookies']);
19
20function dvz_shoutbox_info()
21{
22 return [
23 'name' => 'DVZ Shoutbox',
24 'description' => 'Lightweight AJAX chat.',
25 'website' => 'https://devilshakerz.com/',
26 'author' => 'Tomasz \'Devilshakerz\' Mlynski',
27 'authorsite' => 'https://devilshakerz.com/',
28 'version' => '2.3.2',
29 'codename' => 'dvz_shoutbox',
30 'compatibility' => '18*',
31 ];
32}
33
34function dvz_shoutbox_install()
35{
36 global $mybb, $db;
37
38 $mybb->binary_fields['dvz_shoutbox'] = ['ipaddress' => true];
39
40 // table
41 switch ($db->type) {
42 case 'pgsql':
43 $db->write_query("
44 CREATE TABLE IF NOT EXISTS " . TABLE_PREFIX . "dvz_shoutbox (
45 id serial,
46 uid int NOT NULL,
47 text text NULL,
48 date int NOT NULL,
49 modified int NULL DEFAULT NULL,
50 ipaddress bytea NOT NULL,
51 PRIMARY KEY (id)
52 )
53 ");
54 break;
55 case 'sqlite':
56 $db->write_query("
57 CREATE TABLE IF NOT EXISTS " . TABLE_PREFIX . "dvz_shoutbox (
58 id integer primary key,
59 uid integer NOT NULL,
60 text text NULL,
61 date integer NOT NULL,
62 modified integer NULL DEFAULT NULL,
63 ipaddress bytea NOT NULL
64 )
65 ");
66 break;
67 default:
68 $query = $db->query("SELECT SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE = 'InnoDB'");
69 $innodbSupport = $db->num_rows($query) && in_array($db->fetch_field($query, 'SUPPORT'), ['DEFAULT', 'YES']);
70
71 $db->write_query("
72 CREATE TABLE IF NOT EXISTS `" . TABLE_PREFIX . "dvz_shoutbox` (
73 `id` int(11) NOT NULL auto_increment,
74 `uid` int(11) NOT NULL,
75 `text` text NULL,
76 `date` int(11) NOT NULL,
77 `modified` int(11) NULL DEFAULT NULL,
78 `ipaddress` varbinary(16) NOT NULL,
79 PRIMARY KEY (`id`)
80 ) " . ($innodbSupport ? "ENGINE=InnoDB" : null) . " " . $db->build_create_table_collation() . "
81 ");
82 break;
83 }
84
85 // example shout
86 $db->insert_query('dvz_shoutbox', [
87 'uid' => 1,
88 'text' => 'DVZ Shoutbox!',
89 'date' => TIME_NOW,
90 'ipaddress' => $db->escape_binary( my_inet_pton('127.0.0.1') ),
91 ]);
92
93 // settings
94 $settingGroupId = $db->insert_query('settinggroups', [
95 'name' => 'dvz_shoutbox',
96 'title' => 'DVZ Shoutbox',
97 'description' => 'Settings for DVZ Shoutbox.',
98 ]);
99
100 $settings = [
101 [
102 'name' => 'dvz_sb_num',
103 'title' => 'Shouts to display',
104 'description' => 'Number of shouts to be displayed in the Shoutbox window.',
105 'optionscode' => 'numeric',
106 'value' => '20',
107 ],
108 [
109 'name' => 'dvz_sb_num_archive',
110 'title' => 'Shouts to display on archive',
111 'description' => 'Number of shouts to be displayed per page on Archive view.',
112 'optionscode' => 'numeric',
113 'value' => '20',
114 ],
115 [
116 'name' => 'dvz_sb_reversed',
117 'title' => 'Reversed order',
118 'description' => 'Reverses the shouts display order in the Shoutbox window so that new ones appear on the bottom. You may also want to move the <b>{$panel}</b> variable below the window in the <i>dvz_shoutbox</i> template.',
119 'optionscode' => 'yesno',
120 'value' => '0',
121 ],
122 [
123 'name' => 'dvz_sb_height',
124 'title' => 'Shoutbox height',
125 'description' => 'Height of the Shoutbox window in pixels.',
126 'optionscode' => 'numeric',
127 'value' => '160',
128 ],
129 [
130 'name' => 'dvz_sb_dateformat',
131 'title' => 'Date format',
132 'description' => 'Format of the date displayed. This format uses the PHP\'s <a href="https://secure.php.net/manual/en/function.date.php#refsect1-function.date-parameters">date() function syntax</a>.',
133 'optionscode' => 'text',
134 'value' => 'd M H:i',
135 ],
136 [
137 'name' => 'dvz_sb_maxlength',
138 'title' => 'Maximum message length',
139 'description' => 'Set 0 to disable the limit.',
140 'optionscode' => 'numeric',
141 'value' => '0',
142 ],
143 [
144 'name' => 'dvz_sb_mycode',
145 'title' => 'Parse MyCode',
146 'description' => '',
147 'optionscode' => 'yesno',
148 'value' => '1',
149 ],
150 [
151 'name' => 'dvz_sb_smilies',
152 'title' => 'Parse smilies',
153 'description' => '',
154 'optionscode' => 'yesno',
155 'value' => '1',
156 ],
157 [
158 'name' => 'dvz_sb_interval',
159 'title' => 'Refresh interval',
160 'description' => 'Number of seconds between Shoutbox updates (lower values provide better synchronization but cause higher server load). Set 0 to disable the auto-refreshing feature.',
161 'optionscode' => 'numeric',
162 'value' => '5',
163 ],
164 [
165 'name' => 'dvz_sb_away',
166 'title' => 'Away mode',
167 'description' => 'Number of seconds after last user action (e.g. click) after which shoutbox will be minimized to prevent unnecessary usage of server resources. Set 0 to disable this feature.',
168 'optionscode' => 'numeric',
169 'value' => '600',
170 ],
171 [
172 'name' => 'dvz_sb_antiflood',
173 'title' => 'Anti-flood interval',
174 'description' => 'Forces a minimum number of seconds to last between user\'s shouts (this does not apply to Shoutbox moderators).',
175 'optionscode' => 'numeric',
176 'value' => '5',
177 ],
178 [
179 'name' => 'dvz_sb_sync',
180 'title' => 'Moderation synchronization',
181 'description' => 'Applies moderation actions without refreshing the Shoutbox window page.',
182 'optionscode' => 'onoff',
183 'value' => '1',
184 ],
185 [
186 'name' => 'dvz_sb_mark_unread',
187 'title' => 'Mark unread messages',
188 'description' => 'Marks messages that appeared after user\'s last visit.',
189 'optionscode' => 'onoff',
190 'value' => '1',
191 ],
192 [
193 'name' => 'dvz_sb_lazyload',
194 'title' => 'Lazy load',
195 'description' => 'Start loading data only when the Shoutbox window is actually being displayed on the screen (the page is scrolled to the Shoutbox position).',
196 'optionscode' => 'select
197off=Disabled
198start=Check if on display to start
199always=Always check if on display to refresh',
200 'value' => 'off',
201 ],
202 [
203 'name' => 'dvz_sb_status',
204 'title' => 'Shoutbox default status',
205 'description' => 'Choose whether Shoutbox window should be expanded or collapsed by default.',
206 'optionscode' => 'onoff',
207 'value' => '1',
208 ],
209 [
210 'name' => 'dvz_sb_minposts',
211 'title' => 'Minimum posts required to shout',
212 'description' => 'Set 0 to allow everyone.',
213 'optionscode' => 'numeric',
214 'value' => '0',
215 ],
216 [
217 'name' => 'dvz_sb_groups_view',
218 'title' => 'Group permissions: View',
219 'description' => 'User groups that can view Shoutbox.',
220 'optionscode' => 'groupselect',
221 'value' => '-1',
222 ],
223 [
224 'name' => 'dvz_sb_groups_refresh',
225 'title' => 'Group permissions: Auto-refresh',
226 'description' => 'User groups that shoutbox will be refreshing for.',
227 'optionscode' => 'groupselect',
228 'value' => '-1',
229 ],
230 [
231 'name' => 'dvz_sb_groups_shout',
232 'title' => 'Group permissions: Shout',
233 'description' => 'User groups that can post shouts in Shoutbox (logged in users only).',
234 'optionscode' => 'groupselect',
235 'value' => '-1',
236 ],
237 [
238 'name' => 'dvz_sb_groups_recall',
239 'title' => 'Group permissions: Scroll back to show past shouts',
240 'description' => 'User groups that shoutbox will load previous posts when scrolling back for.',
241 'optionscode' => 'groupselect',
242 'value' => '-1',
243 ],
244 [
245 'name' => 'dvz_sb_groups_mod',
246 'title' => 'Group permissions: Moderation',
247 'description' => 'User groups that can moderate the Shoutbox (edit and delete shouts).',
248 'optionscode' => 'groupselect',
249 'value' => '',
250 ],
251 [
252 'name' => 'dvz_sb_groups_mod_own',
253 'title' => 'Group permissions: Moderation of own shouts',
254 'description' => 'Users groups whose members can edit and delete their own shouts.',
255 'optionscode' => 'groupselect',
256 'value' => '',
257 ],
258 [
259 'name' => 'dvz_sb_supermods',
260 'title' => 'Super moderators are Shoutbox moderators',
261 'description' => 'Automatically allow forum super moderators to moderate Shoutbox as well.',
262 'optionscode' => 'yesno',
263 'value' => '1',
264 ],
265 [
266 'name' => 'dvz_sb_blocked_users',
267 'title' => 'Banned users',
268 'description' => 'Comma-separated list of user IDs that are banned from posting messages.',
269 'optionscode' => 'textarea',
270 'value' => '',
271 ],
272 ];
273
274 $i = 1;
275
276 foreach ($settings as &$row) {
277 $row['gid'] = $settingGroupId;
278 $row['title'] = $db->escape_string($row['title']);
279 $row['description'] = $db->escape_string($row['description']);
280 $row['disporder'] = $i++;
281 }
282
283 $db->insert_query_multiple('settings', $settings);
284
285 rebuild_settings();
286
287 // templates
288 $templates = [
289 'dvz_shoutbox_panel' => '<div class="panel">
290<form>
291<input type="text" class="text" placeholder="{$lang->dvz_sb_default}" maxlength="{$maxlength}" autocomplete="off" />
292<input type="submit" style="display:none" />
293</form>
294</div>',
295
296 'dvz_shoutbox' => '<div id="shoutbox" class="front{$classes}">
297
298<div class="head">
299<strong>{$lang->dvz_sb_shoutbox}</strong>
300<p class="right"><a href="{$mybb->settings[\'bburl\']}/index.php?action=shoutbox_archive">« {$lang->dvz_sb_archivelink}</a></p>
301</div>
302
303<div class="body">
304
305{$panel}
306
307<div class="window" style="height:{$mybb->settings[\'dvz_sb_height\']}px">
308<div class="data">
309{$html}
310</div>
311</div>
312
313</div>
314
315<script type="text/javascript" src="{$mybb->settings[\'bburl\']}/jscripts/dvz_shoutbox.js"></script>
316{$javascript}
317
318</div>',
319
320 'dvz_shoutbox_archive' => '<html>
321<head>
322<title>{$lang->dvz_sb_archive}</title>
323{$headerinclude}
324</head>
325<body>
326{$header}
327
328<script type="text/javascript" src="{$mybb->settings[\'bburl\']}/jscripts/dvz_shoutbox.js"></script>
329{$javascript}
330
331{$modoptions}
332
333{$multipage}
334
335<br />
336
337<div id="shoutbox">
338
339<div class="head">
340<strong>{$lang->dvz_sb_archive}</strong>
341{$last_read_link}
342</div>
343
344<div class="data">
345{$archive}
346</div>
347</div>
348
349<br />
350
351{$multipage}
352
353{$footer}
354</body>
355</html>',
356
357 'dvz_shoutbox_last_read_link' => '<p class="right"><a href="{$last_read_url}">{$lang->dvz_sb_last_read_link}</a> | <a href="{$unmark_all_url}">{$lang->dvz_sb_last_read_unmark_all}</a></p>',
358
359 'dvz_shoutbox_archive_modoptions' => '<table border="0" cellspacing="{$theme[\'borderwidth\']}" cellpadding="{$theme[\'tablespace\']}" class="tborder">
360<tr><td class="thead" colspan="2"><strong>{$lang->dvz_sb_mod}</strong></td></tr>
361<tr><td class="tcat">{$lang->dvz_sb_mod_banlist}</td><td class="tcat">{$lang->dvz_sb_mod_clear}</td></tr>
362<tr>
363<td class="trow1">
364<form action="" method="post">
365<input type="text" class="textbox" style="width:80%" name="banlist" value="{$blocked_users}" />
366<input type="hidden" name="postkey" value="{$mybb->post_code}" />
367<input type="submit" class="button" value="{$lang->dvz_sb_mod_banlist_button}" />
368</form>
369</td>
370<td class="trow1">
371<form action="" method="post">
372<select name="days">
373<option value="2">2 {$lang->days}</option>
374<option value="7">7 {$lang->days}</option>
375<option value="30">30 {$lang->days}</option>
376<option value="90">90 {$lang->days}</option>
377<option value="all">* {$lang->dvz_sb_mod_clear_all} *</option>
378</select>
379<input type="hidden" name="postkey" value="{$mybb->post_code}" />
380<input type="submit" class="button" value="{$lang->dvz_sb_mod_clear_button}" />
381</form>
382</td>
383</tr>
384</table>
385<br />',
386 ];
387
388 $data = [];
389
390 foreach ($templates as $name => $content) {
391 $data[] = [
392 'title' => $name,
393 'template' => $db->escape_string($content),
394 'sid' => -1,
395 'version' => 1,
396 'status' => '',
397 'dateline' => TIME_NOW,
398 ];
399 }
400
401 $db->insert_query_multiple('templates', $data);
402}
403
404function dvz_shoutbox_uninstall()
405{
406 global $db;
407
408 $settingGroupId = $db->fetch_field(
409 $db->simple_select('settinggroups', 'gid', "name='dvz_shoutbox'"),
410 'gid'
411 );
412
413 // delete settings
414 $db->delete_query('settinggroups', 'gid=' . (int)$settingGroupId);
415 $db->delete_query('settings', 'gid=' . (int)$settingGroupId);
416
417 rebuild_settings();
418
419 // delete templates
420 $db->delete_query('templates', "title IN(
421 'dvz_shoutbox',
422 'dvz_shoutbox_panel',
423 'dvz_shoutbox_archive',
424 'dvz_shoutbox_last_read_link',
425 'dvz_shoutbox_archive_modoptions'
426 )");
427
428 // delete data
429 if ($db->type == 'sqlite') {
430 $db->close_cursors();
431 }
432
433 $db->drop_table('dvz_shoutbox');
434}
435
436function dvz_shoutbox_is_installed()
437{
438 global $mybb;
439 return $mybb->settings['dvz_sb_num'] !== null;
440}
441
442
443class dvz_shoutbox
444{
445
446 // hooks
447 static function global_start()
448 {
449 global $mybb, $templatelist;
450
451 $mybb->binary_fields['dvz_shoutbox'] = ['ipaddress' => true];
452
453 if (defined('THIS_SCRIPT') && THIS_SCRIPT == 'index.php' && self::access_view()) {
454
455 if (!empty($templatelist)) {
456 $templatelist .= ',';
457 }
458
459 if ($mybb->get_input('action') == 'shoutbox_archive') {
460 // archive templates
461
462 $templatelist .= 'dvz_shoutbox_archive,dvz_shoutbox_last_read_link,multipage,multipage_page,multipage_page_current,multipage_prevpage,multipage_nextpage,multipage_start,multipage_end,multipage_jump_page';
463
464 if (self::access_mod()) {
465 $templatelist .= ',dvz_shoutbox_archive_modoptions';
466 }
467
468 } else {
469 // index templates
470 $templatelist .= 'dvz_shoutbox,dvz_shoutbox_panel';
471 }
472
473 }
474 }
475
476 static function global_end()
477 {
478 global $mybb;
479
480 if ($mybb->get_input('action') == 'shoutbox_archive' && self::access_view()) {
481 return self::show_archive();
482 }
483 }
484
485 static function xmlhttp()
486 {
487 global $mybb, $db, $charset, $plugins;
488
489 $mybb->binary_fields['dvz_shoutbox'] = ['ipaddress' => true];
490
491 switch ($mybb->get_input('action')) {
492
493 case 'dvz_sb_get_updates':
494
495 $permissions = (
496 self::access_view() &&
497 self::access_refresh()
498 );
499
500 $handler = function () use ($mybb, $db, $plugins) {
501
502 $syncConditions = $mybb->settings['dvz_sb_sync']
503 ? "OR (s.modified >= " . (time() - $mybb->settings['dvz_sb_interval']) . " AND s.id BETWEEN " . abs($mybb->get_input('first', MyBB::INPUT_INT)) . " AND " . abs($mybb->get_input('last', MyBB::INPUT_INT)) . ")"
504 : null
505 ;
506
507 $data = self::get_multiple("WHERE (s.id > " . abs($mybb->get_input('last', MyBB::INPUT_INT)) . " AND s.text IS NOT NULL) " . $syncConditions . " ORDER BY s.id DESC LIMIT " . self::async_limit());
508
509 $html = null; // JS-handled empty response
510 $sync = [];
511 $firstId = 0;
512 $lastId = 0;
513
514 while ($row = $db->fetch_array($data)) {
515
516 if ($row['id'] <= $mybb->get_input('last', MyBB::INPUT_INT)) {
517 // sync update
518
519 $sync[ $row['id'] ] = $row['text'] === null
520 ? null
521 : self::parse($row['text'], $row['username'])
522 ;
523
524 } else {
525 // new shout
526
527 $firstId = $row['id'];
528
529 if ($lastId == 0) {
530 $lastId = $row['id'];
531 }
532
533 $shout = self::render_shout($row);
534
535 $html = $mybb->settings['dvz_sb_reversed']
536 ? $shout . $html
537 : $html . $shout
538 ;
539
540 }
541
542 }
543
544 if ($html != null || !empty($sync)) {
545
546 $response = [];
547
548 if ($html != null) {
549
550 $response['html'] = $html;
551 $response['last'] = $lastId;
552
553 if ($mybb->get_input('first', MyBB::INPUT_INT) == 0) {
554 $response['first'] = $firstId;
555 }
556
557 }
558
559 if (!empty($sync)) {
560 $response['sync'] = $sync;
561 }
562
563 $plugins->run_hooks('dvz_shoutbox_get_updates', $response);
564
565 echo json_encode($response);
566
567 }
568 };
569
570 break;
571
572 case 'dvz_sb_recall':
573
574 $permissions = (
575 self::access_view() &&
576 self::access_refresh() &&
577 self::access_recall()
578 );
579
580 $handler = function () use ($mybb, $db, $plugins) {
581
582 $data = self::get_multiple("WHERE s.id < " . abs($mybb->get_input('first', MyBB::INPUT_INT)) . " AND s.text IS NOT NULL ORDER BY s.id DESC LIMIT " . abs((int)$mybb->settings['dvz_sb_num']));
583
584 $response = [];
585
586 $html = null; // JS-handled empty response
587 $firstId = 0;
588
589 while ($row = $db->fetch_array($data)) {
590
591 $firstId = $row['id'];
592
593 $shout = self::render_shout($row);
594
595 $html = $mybb->settings['dvz_sb_reversed']
596 ? $shout . $html
597 : $html . $shout
598 ;
599 }
600
601 if ($html != null) {
602 $response['html'] = $html;
603 }
604
605 if ($db->num_rows($data) < abs((int)$mybb->settings['dvz_sb_num'])) {
606 $response['end'] = 1;
607 }
608
609 if ($response) {
610 $response['first'] = $firstId;
611 }
612
613 $plugins->run_hooks('dvz_shoutbox_recall', $response);
614
615 echo json_encode($response);
616
617 };
618
619 break;
620
621 case 'dvz_sb_shout':
622
623 $permissions = (
624 self::access_shout() &&
625 verify_post_check($mybb->get_input('key'), true)
626 );
627
628 $handler = function () use ($mybb, $db, $plugins) {
629
630 if (!self::antiflood_pass() && !self::access_mod()) {
631 die('A'); // JS-handled error (Anti-flood)
632 }
633
634 $data = [
635 'uid' => (int)$mybb->user['uid'],
636 'text' => $mybb->get_input('text'),
637 'ipaddress' => $db->escape_binary( my_inet_pton(get_ip()) ),
638 ];
639
640 $plugins->run_hooks('dvz_shoutbox_shout', $data);
641
642 $data['shout_id'] = self::shout($data);
643
644 $plugins->run_hooks('dvz_shoutbox_shout_commit', $data);
645
646 };
647
648 break;
649
650 case 'dvz_sb_get':
651
652 $data = self::get($mybb->get_input('id', MyBB::INPUT_INT));
653
654 $permissions = (
655 (
656 self::access_mod() ||
657 (self::access_mod_own() && $data['uid'] == $mybb->user['uid'])
658 ) &&
659 verify_post_check($mybb->get_input('key'), true)
660 );
661
662 $handler = function () use ($data, $plugins) {
663
664 $plugins->run_hooks('dvz_shoutbox_get', $data);
665
666 echo json_encode([
667 'text' => $data['text'],
668 ]);
669
670 };
671
672 break;
673
674 case 'dvz_sb_update':
675
676 $data = self::get($mybb->get_input('id', MyBB::INPUT_INT));
677
678 $permissions = (
679 $data &&
680 self::can_mod($data) &&
681 verify_post_check($mybb->get_input('key'), true)
682 );
683
684 $handler = function () use ($mybb, $data, $plugins) {
685
686 $plugins->run_hooks('dvz_shoutbox_update', $data);
687
688 self::update($mybb->get_input('id', MyBB::INPUT_INT), $mybb->get_input('text'));
689
690 $data['text'] = $mybb->get_input('text');
691
692 $plugins->run_hooks('dvz_shoutbox_update_commit', $data);
693
694 echo self::parse($mybb->get_input('text'), self::get_username($mybb->get_input('id', MyBB::INPUT_INT)));
695
696 };
697
698 break;
699
700 case 'dvz_sb_delete':
701
702 $permissions = (
703 self::can_mod($mybb->get_input('id', MyBB::INPUT_INT)) &&
704 verify_post_check($mybb->get_input('key'), true)
705 );
706
707 $handler = function () use ($mybb, $plugins) {
708
709 $plugins->run_hooks('dvz_shoutbox_delete');
710
711 $result = self::delete($mybb->get_input('id', MyBB::INPUT_INT));
712
713 $plugins->run_hooks('dvz_shoutbox_delete_commit', $result);
714
715 };
716
717 break;
718
719 }
720
721 if (isset($permissions)) {
722
723 if ($permissions == false) {
724 echo 'P'; // JS-handled error (Permissions)
725 } else {
726
727 header('Content-type: text/plain; charset=' . $charset);
728 header('Cache-Control: no-store'); // force update on load
729 $handler();
730
731 }
732
733 }
734 }
735
736 static function load_window()
737 {
738 global $templates, $dvz_shoutbox, $lang, $mybb, $db, $theme,$our_shouts,$wpisy,$top_spamer_noformatted,$shouts,$users_online_o, $users_online, $onlinemembers;
739
740 $lang->load('dvz_shoutbox');
741
742 // MyBB template
743 $dvz_shoutbox = null;
744
745 // dvz_shoutbox template
746 $javascript = null;
747 $panel = null;
748 $classes = null;
749
750 if (self::access_view()) {
751
752 if (self::is_user()) {
753
754 // message: blocked
755 if (self::is_blocked()) {
756 $panel = '<div class="panel blocked"><p>' . $lang->dvz_sb_user_blocked . '</p></div>';
757 }
758 // message: minimum posts
759 else if (!self::access_minposts() && !self::access_mod()) {
760 $panel = '<div class="panel minposts"><p>' . str_replace('{MINPOSTS}', (int)$mybb->settings['dvz_sb_minposts'], $lang->dvz_sb_minposts) . '</p></div>';
761 }
762 // shout form
763 else if (self::access_shout()) {
764 $maxlength = $mybb->settings['dvz_sb_maxlength'] ? (int)$mybb->settings['dvz_sb_maxlength'] : null;
765 eval('$panel = "' . $templates->get('dvz_shoutbox_panel') . '";');
766 }
767
768 }
769
770 $js = null;
771
772 // configuration
773 $js .= 'dvz_shoutbox.interval = ' . (self::access_refresh() ? (float)$mybb->settings['dvz_sb_interval'] : 0) . ';' . PHP_EOL;
774 $js .= 'dvz_shoutbox.antiflood = ' . (self::access_mod() ? 0 : (float)$mybb->settings['dvz_sb_antiflood']) . ';' . PHP_EOL;
775 $js .= 'dvz_shoutbox.maxShouts = ' . (int)$mybb->settings['dvz_sb_num'] . ';' . PHP_EOL;
776 $js .= 'dvz_shoutbox.awayTime = ' . (float)$mybb->settings['dvz_sb_away'] . '*1000;' . PHP_EOL;
777 $js .= 'dvz_shoutbox.lang = [\'' . $lang->dvz_sb_delete_confirm . '\', \'' . str_replace('{ANTIFLOOD}', (float)$mybb->settings['dvz_sb_antiflood'], $lang->dvz_sb_antiflood) . '\', \''.$lang->dvz_sb_permissions.'\'];' . PHP_EOL;
778
779 // mark unread
780 if ($mybb->settings['dvz_sb_mark_unread']) {
781 $js .= 'dvz_shoutbox.markUnread = true;' . PHP_EOL;
782 }
783
784 // reversed order
785 if ($mybb->settings['dvz_sb_reversed']) {
786 $js .= 'dvz_shoutbox.reversed = true;' . PHP_EOL;
787 }
788
789 // lazyload
790 if (in_array($mybb->settings['dvz_sb_lazyload'], ['off', 'start', 'always'])) {
791 $js .= 'dvz_shoutbox.lazyMode = \'' . $mybb->settings['dvz_sb_lazyload'] . '\';' . PHP_EOL;
792 $js .= '$(window).bind(\'scroll resize\', dvz_shoutbox.checkVisibility);' . PHP_EOL;
793 }
794
795 // away mode
796 if ($mybb->settings['dvz_sb_away']) {
797 $js .= '$(window).on(\'mousemove click dblclick keydown scroll\', dvz_shoutbox.updateActivity);' . PHP_EOL;
798 }
799
800 // shoutbox status
801 $status =
802 (!isset($mybb->cookies['dvz_sb_status']) && $mybb->settings['dvz_sb_status'] == 1) ||
803 $mybb->cookies['dvz_sb_status'] == '1'
804 ;
805
806 $js .= 'dvz_shoutbox.status = ' . (int)$status . ';' . PHP_EOL;
807
808 if ($status == false) {
809 $classes .= ' collapsed';
810 }
811
812 $html = null;
813 $firstId = 0;
814 $lastId = 0;
815
816 if ($status == true) {
817
818 // preloaded shouts
819 $data = self::get_multiple("WHERE s.text IS NOT NULL ORDER BY s.id DESC LIMIT " . abs((int)$mybb->settings['dvz_sb_num']));
820
821 while ($row = $db->fetch_array($data)) {
822
823 $firstId = $row['id'];
824
825 if ($lastId == 0) {
826 $lastId = $row['id'];
827 }
828
829 $shout = self::render_shout($row);
830
831 $html = $mybb->settings['dvz_sb_reversed']
832 ? $shout . $html
833 : $html . $shout
834 ;
835 }
836
837 }
838
839 if (self::access_recall()) {
840 $js .= 'dvz_shoutbox.recalling = true;' . PHP_EOL;
841 }
842
843 if (self::access_refresh()) {
844 $js .= 'setTimeout(\'dvz_shoutbox.loop()\', ' . (float)$mybb->settings['dvz_sb_interval'] . ' * 1000);' . PHP_EOL;
845 }
846
847 $javascript = '
848<script>
849' . $js . '
850dvz_shoutbox.firstId = ' . $firstId . ';
851dvz_shoutbox.lastId = ' . $lastId . ';
852dvz_shoutbox.parseEntries();
853dvz_shoutbox.updateActivity();
854</script>';
855
856 eval('$dvz_shoutbox = "' . $templates->get('dvz_shoutbox') . '";');
857
858 }
859 }
860
861 static function show_archive()
862 {
863 global $db, $mybb, $templates, $lang, $theme, $footer, $headerinclude, $header, $charset;
864
865 $lang->load('dvz_shoutbox');
866
867 header('Content-type: text/html; charset=' . $charset);
868
869 add_breadcrumb($lang->dvz_sb_shoutbox, "index.php?action=shoutbox_archive");
870
871 // moderation panel
872 if (self::access_mod()) {
873
874 if (isset($mybb->input['banlist']) && verify_post_check($mybb->get_input('postkey'))) {
875 self::banlist_update($mybb->get_input('banlist'));
876 }
877
878 if ($mybb->get_input('days') && verify_post_check($mybb->get_input('postkey'))) {
879 if ($mybb->get_input('days') == 'all') {
880 self::clear();
881 } else {
882 $allowed = [2, 7, 30, 90];
883 if (in_array($mybb->get_input('days'), $allowed)) {
884 self::clear($mybb->get_input('days'));
885 }
886 }
887 }
888
889 $blocked_users = htmlspecialchars_uni($mybb->settings['dvz_sb_blocked_users']);
890 eval('$modoptions = "' . $templates->get("dvz_shoutbox_archive_modoptions") . '";');
891
892 } else {
893 $modoptions = null;
894 }
895
896 // unmark all unread messages
897 if ($mybb->get_input('unmark_all') && verify_post_check($mybb->get_input('postkey'))) {
898 my_unsetcookie('dvz_sb_last_read');
899 }
900
901 // pagination
902 $perPage = abs((int)$mybb->settings['dvz_sb_num_archive']);
903 $items = self::count();
904
905 $requestedId = $mybb->get_input('sid', MyBB::INPUT_INT);
906
907 if ($requestedId && self::get($requestedId)) {
908
909 if ($perPage == 0) {
910 $page = 0;
911 } else {
912 $itemsAfter = self::count('id > ' . $requestedId);
913 $itemPage = ceil( ($itemsAfter + 1) / $perPage );
914
915 $page = $itemPage;
916 }
917
918 } else {
919
920 $page = abs($mybb->get_input('page', MyBB::INPUT_INT));
921
922 if ($perPage == 0) {
923 $pages = 0;
924 } else {
925 $pages = ceil($items / $perPage);
926 }
927
928 if (!$page || $page < 1 || $page > $pages) {
929 $page = 1;
930 }
931
932 }
933
934 $limitStart = ($page - 1) * $perPage;
935
936 if ($items > $perPage && $perPage > 0) {
937 $multipage = multipage($items, $perPage, $page, 'index.php?action=shoutbox_archive');
938 }
939
940 $limit = $perPage;
941
942 if ($mybb->settings['dvz_sb_mark_unread'] && isset($mybb->cookies['dvz_sb_last_read'])) {
943 $limit += 1;
944 }
945
946 $data = self::get_multiple("WHERE s.text IS NOT NULL ORDER by s.id DESC LIMIT $limitStart,$limit");
947
948 $firstId = null;
949 $lastId = null;
950
951 $archive = null;
952
953 $rowCount = 1;
954
955 while ($row = $db->fetch_array($data)) {
956
957 if ($rowCount > $perPage) {
958
959 $nextPageLastId = $row['id'];
960
961 } else {
962
963 if ($mybb->settings['dvz_sb_mark_unread'] && isset($mybb->cookies['dvz_sb_last_read']) && $row['id'] > $mybb->cookies['dvz_sb_last_read']) {
964 $row['unread'] = true;
965 }
966
967 $archive .= self::render_shout($row, true);
968
969 if ($lastId == null) {
970 $lastId = $row['id'];
971 }
972
973 $firstId = $row['id'];
974
975 $rowCount++;
976
977 }
978
979 }
980
981 // update last read information
982 if ($mybb->settings['dvz_sb_mark_unread']) {
983 if (
984 !isset($mybb->cookies['dvz_sb_last_read']) ||
985 (
986 $lastId > $mybb->cookies['dvz_sb_last_read'] &&
987 (!isset($nextPageLastId) || $mybb->cookies['dvz_sb_last_read'] >= $nextPageLastId)
988 )
989 ) {
990 my_setcookie('dvz_sb_last_read', $lastId);
991 }
992 }
993
994 // last read link
995 if (
996 $mybb->settings['dvz_sb_mark_unread'] &&
997 isset($mybb->cookies['dvz_sb_last_read']) &&
998 !($page == 1 && $lastId == abs((int)$mybb->cookies['dvz_sb_last_read']))
999 ) {
1000
1001 $sid = abs((int)$mybb->cookies['dvz_sb_last_read']);
1002 $last_read_url = $mybb->settings['bburl'] . '/index.php?action=shoutbox_archive&sid=' . $sid . '#sid' . $sid;
1003 $unmark_all_url = $mybb->settings['bburl'] . '/index.php?action=shoutbox_archive&unmark_all=1&postkey=' . $mybb->post_code;
1004
1005 eval('$last_read_link = "' . $templates->get('dvz_shoutbox_last_read_link') . '";');
1006
1007 } else {
1008 $last_read_link = null;
1009 }
1010
1011 $javascript = '
1012<script>
1013dvz_shoutbox.lang = [\'' . $lang->dvz_sb_delete_confirm . '\', \'' . str_replace('{ANTIFLOOD}', (float)$mybb->settings['dvz_sb_antiflood'], $lang->dvz_sb_antiflood) . '\', \'' . $lang->dvz_sb_permissions . '\'];
1014</script>';
1015
1016 eval('$content = "' . $templates->get("dvz_shoutbox_archive") . '";');
1017
1018 output_page($content);
1019
1020 exit;
1021 }
1022
1023 static function user_merge()
1024 {
1025 global $db, $source_user, $destination_user;
1026 return $db->update_query('dvz_shoutbox', ['uid' => (int)$destination_user['uid']], 'uid=' . (int)$source_user['uid']);
1027 }
1028
1029 static function activity(&$user_activity)
1030 {
1031 $location = parse_url($user_activity['location']);
1032 $filename = basename($location['path']);
1033
1034 parse_str(html_entity_decode($location['query']), $parameters);
1035
1036 if ($filename == 'index.php' && $parameters['action'] == 'shoutbox_archive') {
1037 $user_activity['activity'] = 'dvz_shoutbox_archive';
1038 }
1039 }
1040
1041 static function activity_translate(&$data)
1042 {
1043 global $lang;
1044
1045 $lang->load('dvz_shoutbox');
1046
1047 if ($data['user_activity']['activity'] == 'dvz_shoutbox_archive') {
1048 $data['location_name'] = sprintf($lang->dvz_sb_activity, 'index.php?action=shoutbox_archive');
1049 }
1050 }
1051
1052 static function clearcookies()
1053 {
1054 global $remove_cookies;
1055 $remove_cookies[] = 'dvz_sb_status';
1056 $remove_cookies[] = 'dvz_sb_last_read';
1057 }
1058
1059 static function admin_config_settings_change()
1060 {
1061 global $lang;
1062 $lang->load('dvz_shoutbox');
1063 }
1064
1065 // data handling
1066 static function get($id)
1067 {
1068 global $db;
1069
1070 return $db->fetch_array(
1071 $db->simple_select('dvz_shoutbox s', '*', 'id=' . (int)$id . ' AND s.text IS NOT NULL')
1072 );
1073 }
1074
1075 static function get_multiple($clauses)
1076 {
1077 global $db;
1078 return $db->query("
1079 SELECT
1080 s.*, u.username, u.usergroup, u.displaygroup, u.avatar
1081 FROM
1082 " . TABLE_PREFIX . "dvz_shoutbox s
1083 LEFT JOIN " . TABLE_PREFIX . "users u ON u.uid = s.uid
1084 " . $clauses . "
1085 ");
1086 }
1087
1088 static function get_username($id)
1089 {
1090 global $db;
1091 return $db->fetch_field(
1092 $db->query("SELECT username FROM " . TABLE_PREFIX . "users u, " . TABLE_PREFIX . "dvz_shoutbox s WHERE u.uid=s.uid AND s.id=" . (int)$id),
1093 'username'
1094 );
1095 }
1096
1097 static function user_last_shout_time($uid)
1098 {
1099 global $db;
1100 return $db->fetch_field(
1101 $db->simple_select('dvz_shoutbox s', 'date', 'uid=' . (int)$uid . ' AND s.text IS NOT NULL', [
1102 'order_by' => 'date',
1103 'order_dir' => 'desc',
1104 'limit' => 1,
1105 ]),
1106 'date'
1107 );
1108 }
1109
1110 static function count($where = false)
1111 {
1112 global $db;
1113 return $db->fetch_field(
1114 $db->simple_select('dvz_shoutbox', 'COUNT(text) as n', $where),
1115 'n'
1116 );
1117 }
1118
1119 static function shout($data)
1120 {
1121 global $mybb, $db;
1122
1123 if ($mybb->settings['dvz_sb_maxlength'] > 0) {
1124 $data['text'] = mb_substr($data['text'], 0, $mybb->settings['dvz_sb_maxlength']);
1125 }
1126
1127 foreach ($data as $key => &$value) {
1128 if (!in_array($key, array_keys($mybb->binary_fields['dvz_shoutbox']))) {
1129 $value = $db->escape_string($value);
1130 }
1131 }
1132
1133 $data['date'] = TIME_NOW;
1134
1135 return $db->insert_query('dvz_shoutbox', $data);
1136 }
1137
1138 static function update($id, $text)
1139 {
1140 global $db;
1141 return $db->update_query('dvz_shoutbox', [
1142 'text' => $db->escape_string($text),
1143 'modified' => time(),
1144 ], 'id=' . (int)$id);
1145 }
1146
1147 static function banlist_update($new)
1148 {
1149 global $db;
1150
1151 $db->update_query('settings', ['value' => $db->escape_string($new)], "name='dvz_sb_blocked_users'");
1152
1153 rebuild_settings();
1154 }
1155
1156 static function delete($id)
1157 {
1158 global $mybb, $db;
1159
1160 if ($mybb->settings['dvz_sb_sync']) {
1161 return $db->update_query('dvz_shoutbox', [
1162 'text' => 'NULL',
1163 'modified' => time(),
1164 ], 'id=' . (int)$id, false, true);
1165 } else {
1166 return $db->delete_query('dvz_shoutbox', 'id=' . (int)$id);
1167 }
1168 }
1169
1170 static function clear($days = false)
1171 {
1172 global $db;
1173
1174 if ($days) {
1175 $where = 'date < ' . ( TIME_NOW - ((int)$days * 86400) );
1176 } else {
1177 $where = false;
1178 }
1179
1180 return $db->delete_query('dvz_shoutbox', $where);
1181 }
1182
1183 // permissions
1184 static function is_user()
1185 {
1186 global $mybb;
1187 return $mybb->user['uid'] != 0;
1188 }
1189
1190 static function is_blocked()
1191 {
1192 global $mybb;
1193 return in_array($mybb->user['uid'], self::settings_get_csv('blocked_users'));
1194 }
1195
1196 static function access_view()
1197 {
1198 $array = self::settings_get_csv('groups_view');
1199 return $array[0] == -1 || is_member($array);
1200 }
1201
1202 static function access_refresh()
1203 {
1204 $array = self::settings_get_csv('groups_refresh');
1205 return $array[0] == -1 || is_member($array);
1206 }
1207
1208 static function access_shout()
1209 {
1210 $array = self::settings_get_csv('groups_shout');
1211
1212 return (
1213 self::is_user() &&
1214 !self::is_blocked() &&
1215 (
1216 self::access_mod() ||
1217 (
1218 self::access_view() &&
1219 self::access_minposts() &&
1220 $array[0] == -1 || is_member($array)
1221 )
1222 )
1223 );
1224 }
1225
1226 static function access_recall()
1227 {
1228 $array = self::settings_get_csv('groups_recall');
1229 return $array[0] == -1 || is_member($array);
1230 }
1231
1232 static function access_mod()
1233 {
1234 global $mybb;
1235
1236 $array = self::settings_get_csv('groups_mod');
1237
1238 return (
1239 ($array[0] == -1 || is_member($array)) ||
1240 ($mybb->settings['dvz_sb_supermods'] && $mybb->usergroup['issupermod'])
1241 );
1242 }
1243
1244 static function access_mod_own()
1245 {
1246 $array = self::settings_get_csv('groups_mod_own');
1247
1248 return $array[0] == -1 || is_member($array);
1249 }
1250
1251 static function access_minposts()
1252 {
1253 global $mybb;
1254 return $mybb->user['postnum'] >= $mybb->settings['dvz_sb_minposts'];
1255 }
1256
1257 static function can_mod($data)
1258 {
1259 global $mybb;
1260
1261 if (self::access_mod()) {
1262 return true;
1263 } else if (self::access_mod_own() && self::access_shout()) {
1264
1265 if (is_int($data)) {
1266 $data = self::get($data);
1267 }
1268
1269 if ($data['uid'] == $mybb->user['uid']) {
1270 return true;
1271 }
1272
1273 }
1274
1275 return false;
1276 }
1277
1278 // core
1279 static function render_shout($data, $static = false)
1280 {
1281 global $mybb;
1282
1283 $id = (int)$data['id'];
1284 $text = self::parse($data['text'], $data['username']);
1285 $date = htmlspecialchars_uni(my_date($mybb->settings['dvz_sb_dateformat'], $data['date']));
1286 $username = htmlspecialchars_uni($data['username']);
1287 $user = build_profile_link(format_name($username, $data['usergroup'], $data['displaygroup']), (int)$data['uid']);
1288 $avatar = '<img src="' . (empty($data['avatar']) ? htmlspecialchars_uni($mybb->settings['useravatar']) : htmlspecialchars_uni($data['avatar'])) . '" alt="avatar" />';
1289
1290 $staticLink = $mybb->settings['bburl'] . '/index.php?action=shoutbox_archive&sid=' . $id . '#sid' . $id;
1291
1292 $classes = 'entry';
1293 $notes = null;
1294 $attributes = null;
1295
1296 $own = $data['uid'] == $mybb->user['uid'];
1297
1298 if (!empty($data['unread'])) {
1299 $classes .= ' unread';
1300 }
1301
1302 if ($static) {
1303
1304 if (self::access_mod()) {
1305 $notes .= '<span class="ip">' . my_inet_ntop($data['ipaddress']) . '</span>';
1306 }
1307
1308 if (
1309 self::access_mod() ||
1310 (self::access_mod_own() && $own)
1311 ) {
1312 $notes .= '<a href="" class="mod edit">E</a><a href="" class="mod del">X</a>';
1313 }
1314
1315 $attributes .= ' id="sid' . $id . '"';
1316
1317 }
1318
1319 if (
1320 self::access_mod() ||
1321 (self::access_mod_own() && $own)
1322 ) {
1323 $attributes .= ' data-mod';
1324 }
1325
1326 if ($own) {
1327 $attributes .= ' data-own';
1328 }
1329
1330 return '
1331<div class="' . $classes . '" data-id="' . $id . '" data-username="' . $username . '"' . $attributes . '>
1332 <div class="avatar">' . $avatar . '</div>
1333 <div class="user">' . $user . '</div>
1334 <div class="text">' . $text . '</div>
1335 <div class="info">' . $notes . '<a href="' . $staticLink . '"><span class="date">' . $date . '</span></a></div>
1336</div>';
1337 }
1338
1339 static function parse($message, $me_username)
1340 {
1341 global $mybb;
1342
1343 require_once MYBB_ROOT . 'inc/class_parser.php';
1344
1345 $parser = new postParser;
1346 $options = [
1347 'allow_mycode' => $mybb->settings['dvz_sb_mycode'],
1348 'allow_smilies' => $mybb->settings['dvz_sb_smilies'],
1349 'allow_imgcode' => 0,
1350 'filter_badwords' => 1,
1351 'me_username' => $me_username,
1352 ];
1353
1354 return $parser->parse_message($message, $options);
1355 }
1356
1357 static function antiflood_pass()
1358 {
1359 global $mybb;
1360 return (
1361 !$mybb->settings['dvz_sb_antiflood'] ||
1362 ( TIME_NOW - self::user_last_shout_time($mybb->user['uid']) ) > $mybb->settings['dvz_sb_antiflood']
1363 );
1364 }
1365
1366 static function settings_get_csv($name)
1367 {
1368 global $mybb;
1369 return array_filter( explode(',', $mybb->settings['dvz_sb_' . $name]) );
1370 }
1371
1372 static function async_limit()
1373 {
1374 global $mybb;
1375 return max(
1376 abs((int)$mybb->settings['dvz_sb_num']),
1377 abs((int)$mybb->settings['dvz_sb_num_archive'])
1378 );
1379 }
1380
1381}
1382
1383function dvz_shoutbox_stats()
1384{
1385 global $db, $mybb, $templates, $theme, $wpisy, $users, $top_spamer, $users_online_o, $top_spamer_noformatted, $shshshs, $our_shouts, $timesearch, $shouts, $username, $user, $users_online, $anon_online, $invisiblemark, $onlinemembers, $guests_online, $spiders, $cache, $bots_online;
1386
1387 // Użytkownicy online
1388
1389 $timesearch = TIME_NOW - $mybb->settings['wolcutoff'];
1390 $comma = '';
1391 $query3 = $db->query("
1392 SELECT s.sid, s.ip, s.uid, s.time, s.location, s.location1, u.username, u.invisible, u.usergroup, u.displaygroup
1393 FROM ".TABLE_PREFIX."sessions s
1394 LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid)
1395 WHERE location LIKE '%shoutbox.php%' && s.time>'".$timesearch."'
1396 ORDER BY u.username ASC, s.time DESC
1397 ");
1398
1399 $spiders = $cache->read("spiders");
1400
1401 $users_online = 0;
1402 $anon_online = 0;
1403 $guests_online = 0;
1404 $bots_online = 0;
1405 $onlinemembers = '';
1406
1407 while($user = $db->fetch_array($query3))
1408 {
1409 if($user['uid'] > 0)
1410 {
1411 if($user['invisible'] == 1)
1412 {
1413 ++$anon_online;
1414 }
1415
1416 if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid'])
1417 {
1418 if($user['invisible'] == 1)
1419 {
1420 $invisiblemark = "*";
1421 }
1422 else
1423 {
1424 $invisiblemark = '';
1425 }
1426 ++$anon_online;
1427
1428 $username = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']);
1429 $onlinemembers .= ''.$comma.' '.$username.''.$invisiblemark.'';
1430 $comma = " ,";
1431 }
1432 ++$users_online;
1433 }
1434 elseif(my_strpos($user['sid'], "bot=") !== false && $spiders[$botkey])
1435 {
1436 // The user is a search bot.
1437 $onlinemembers .= $comma.format_name($spiders[$botkey]['name'], $spiders[$botkey]['usergroup']);
1438 $comma = ", ";
1439 ++$bots_online;
1440 }
1441 else
1442 {
1443 // The user is a guest.
1444 ++$guests_online;
1445 }
1446
1447 $users_online_o = $users_online + $guests_online;
1448 }
1449 // Statystyki
1450
1451 $query = $db->query("SELECT count(id) as id FROM ".TABLE_PREFIX."dvz_shoutbox");
1452
1453 $row = $db->fetch_array($query);
1454 $wpisy = $row['id'];
1455
1456 $query3 = $db->query("SELECT d.uid, u.username, u.usergroup, u.displaygroup, u.uid, u.avatar, count(*) as shouters
1457 FROM ".TABLE_PREFIX."dvz_shoutbox d
1458 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=d.uid)
1459 WHERE u.usergroup NOT IN(7)
1460 AND u.uid NOT IN(9486)
1461 GROUP BY d.uid
1462 ORDER BY shouters
1463 DESC LIMIT 1");
1464 $row3 = $db->fetch_array($query3);
1465
1466 $shouts = $row3['shouters'];
1467 $top_spamer_noformatted = $row3['username'];
1468 $top_spamer = build_profile_link(format_name($row3['username'], $row3['usergroup'], $row3['displaygroup']), $row3['uid']);
1469
1470 $query4 = $db->query("SELECT count(id) as id, uid FROM ".TABLE_PREFIX."dvz_shoutbox WHERE uid='".$mybb->user['uid']."'");
1471
1472 $our_shouts = $db->fetch_field($query4, "id");
1473}
1474
1475function dvz_shoutbox_users_on_sb()
1476{
1477 global $db, $mybb, $templates, $theme, $users_o_sb, $timesearch;
1478
1479 $timesearch = TIME_NOW - $mybb->settings['wolcutoff'];
1480 $query = $db->query("SELECT count(*) as guid, time FROM ".TABLE_PREFIX."sessions WHERE location LIKE '%shoutbox.php%' && uid!=0 && time>".$timesearch."");
1481 $users_o_sb = $db->fetch_field($query, 'guid');
1482}