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