1############################################################################### 2# Notify.pm # 3# $Date: 12.02.14 $ # 4############################################################################### 5# YaBB: Yet another Bulletin Board # 6# Open-Source Community Software for Webmasters # 7# Version: YaBB 2.6.11 # 8# Packaged: December 2, 2014 # 9# Distributed by: http://www.yabbforum.com # 10# =========================================================================== # 11# Copyright (c) 2000-2014 YaBB (www.yabbforum.com) - All Rights Reserved. # 12# Software by: The YaBB Development Team # 13# with assistance from the YaBB community. # 14############################################################################### 15use CGI::Carp qw(fatalsToBrowser); 16our $VERSION = '2.6.11'; 17 18$notifypmver = 'YaBB 2.6.11 $Revision: 1611 $'; 19if ( $action eq 'detailedversion' ) { return 1; } 20 21LoadLanguage('Notify'); 22 23sub ManageBoardNotify { 24 my ( $todo, $theboard, $user, $userlang, $notetype, $noteview ) = @_; 25 if ( $todo eq 'load' 26 || $todo eq 'update' 27 || $todo eq 'delete' 28 || $todo eq 'add' ) 29 { 30 undef %theboard; 31 ## open board mail file and build hash name / detail 32 if ( -e "$boardsdir/$theboard.mail" ) { 33 fopen( BOARDNOTE, "$boardsdir/$theboard.mail" ); 34 %theboard = map { /(.*)\t(.*)/xsm } <BOARDNOTE>; 35 fclose(BOARDNOTE); 36 } 37 } 38 if ( $todo eq 'add' ) { 39 if ( !$maxtnote ) { $maxtnote = 10; } 40 $theboard{$user} = "$userlang|$notetype|$noteview"; 41 LoadUser($user); 42 my %bb; 43 my @oldnote = split /,/xsm, 44 ${ $uid . $username }{'board_notifications'}; 45 if ( @oldnote < ( $maxtnote || 10 ) ) { 46 foreach ( split /,/xsm, ${ $uid . $user }{'board_notifications'} ) { 47 $bb{$_} = 1; 48 } 49 $bb{$theboard} = 1; 50 ${ $uid . $user }{'board_notifications'} = join q{,}, keys %bb; 51 UserAccount($user); 52 } 53 } 54 elsif ( $todo eq 'update' ) { 55 if ( exists $theboard{$user} ) { 56 my ( $memlang, $memtype, $memview ) = 57 split /\|/xsm, $theboard{$user}; 58 if ($userlang) { $memlang = $userlang; } 59 if ($notetype) { $memtype = $notetype; } 60 if ($noteview) { $memview = $noteview; } 61 $theboard{$user} = "$memlang|$memtype|$memview"; 62 } 63 } 64 elsif ( $todo eq 'delete' ) { 65 my %bb; 66 foreach my $u ( split /,/xsm, $user ) { 67 delete $theboard{$u}; 68 LoadUser($u); 69 foreach ( split /,/xsm, ${ $uid . $u }{'board_notifications'} ) { 70 $bb{$_} = 1; 71 } 72 if ( delete $bb{$theboard} ) { 73 ${ $uid . $u }{'board_notifications'} = join q{,}, keys %bb; 74 UserAccount($u); 75 } 76 undef %bb; 77 } 78 } 79 if ( $todo eq 'save' 80 || $todo eq 'update' 81 || $todo eq 'delete' 82 || $todo eq 'add' ) 83 { 84 if (%theboard) { 85 fopen( BOARDNOTE, ">$boardsdir/$theboard.mail" ); 86 print {BOARDNOTE} map { "$_\t$theboard{$_}\n" } 87 sort { $theboard{$a} cmp $theboard{$b} } keys %theboard 88 or croak "$croak{'print'} BOARDNOTE"; 89 fclose(BOARDNOTE); 90 undef %theboard; 91 } 92 else { 93 unlink "$boardsdir/$theboard.mail"; 94 } 95 } 96 return; 97} 98 99sub BoardNotify { 100 if ( !$currentboard ) { fatal_error('no_access'); } 101 if ($iamguest) { fatal_error('members_only'); } 102 $selected1 = q{}; 103 $selected2 = q{}; 104 $deloption = q{}; 105 my ( $boardname, undef ) = split /\|/xsm, $board{$currentboard}, 2; 106 ToChars($boardname); 107 ManageBoardNotify( 'load', $currentboard ); 108 109## popup from MessageIndex 110 111 LoadLanguage('Notify'); 112 get_template('MessageIndex'); 113 114 if ( exists $theboard{$username} ) { 115 ( $memlang, $memtype, $memview ) = split /\|/xsm, $theboard{$username}; 116 ${ 'selected' . $memtype } = q~ selected="selected"~; 117 $deloption = qq~<option value="3">$notify_txt{'134'}</option>~; 118 $my_delopt = qq~$notify_txt{'137'} ~; 119 } 120 else { 121 $my_delopt = qq~$notify_txt{'126'} ~; 122 } 123 124 $yymain .= $brd_notify; 125 $yymain =~ s/{yabb boardname}/$boardname/gsm; 126 $yymain =~ s/{yabb currentboard}/$currentboard/gsm; 127 $yymain =~ s/{yabb currentboard}/$currentboard/gsm; 128 $yymain =~ s/{yabb selected1}/$selected1/gsm; 129 $yymain =~ s/{yabb selected2}/$selected2/gsm; 130 $yymain =~ s/{yabb deloption}/$deloption/gsm; 131 $yymain =~ s/{yabb my_delopt}/$my_delopt/gsm; 132 133 undef %theboard; 134 $yytitle = "$notify_txt{'125'}"; 135 template(); 136 return; 137} 138 139sub BoardNotify2 { 140 if ($iamguest) { fatal_error('members_only'); } 141 foreach my $variable ( keys %FORM ) { 142 if ( $variable eq 'formsession' ) { next; } 143 $notify_type = $FORM{$variable}; 144 if ( $notify_type == 1 || $notify_type == 2 ) { 145 ManageBoardNotify( 'add', $variable, $username, 146 ${ $uid . $username }{'language'}, 147 $notify_type, '1' ); 148 } 149 elsif ( $notify_type == 3 ) { 150 ManageBoardNotify( 'delete', $variable, $username ); 151 } 152 } 153 if ( $action eq 'boardnotify3' ) { 154 $yySetLocation = qq~$scripturl?board=$INFO{'board'}~; 155 } 156 else { 157 $yySetLocation = qq~$scripturl?action=shownotify~; 158 } 159 redirectexit(); 160 return; 161} 162 163sub ManageThreadNotify { 164 my ( $todo, $thethread, $user, $userlang, $notetype, $noteview ) = @_; 165 if ( $todo eq 'load' 166 || $todo eq 'update' 167 || $todo eq 'delete' 168 || $todo eq 'add' ) 169 { 170 undef %thethread; 171 ## open mail file and build hash 172 if ( -e "$datadir/$thethread.mail" ) { 173 fopen( THREADNOTE, "$datadir/$thethread.mail" ); 174 %thethread = map /(.*)\t(.*)/, <THREADNOTE>; 175 fclose(THREADNOTE); 176 } 177 } 178 if ( $todo eq 'add' ) { 179 $thethread{$user} = "$userlang|$notetype|$noteview"; 180 LoadUser($user); 181 my %t; 182 foreach ( split /,/xsm, ${ $uid . $user }{'thread_notifications'} ) { 183 $t{$_} = 1; 184 } 185 $t{$thethread} = 1; 186 ${ $uid . $user }{'thread_notifications'} = join q{,}, keys %t; 187 UserAccount($user); 188 } 189 elsif ( $todo eq 'update' ) { 190 if ( exists $thethread{$user} ) { 191 ( $memlang, $memtype, $memview ) = split /\|/xsm, $thethread{$user}; 192 if ($userlang) { $memlang = $userlang; } 193 if ($notetype) { $memtype = $notetype; } 194 if ($noteview) { $memview = $noteview; } 195 $thethread{$user} = "$memlang|$memtype|$memview"; 196 } 197 } 198 elsif ( $todo eq 'delete' ) { 199 my %t; 200 foreach my $u ( split /,/xsm, $user ) { 201 delete $thethread{$u}; 202 LoadUser($u); 203 foreach ( split /,/xsm, ${ $uid . $u }{'thread_notifications'} ) { 204 $t{$_} = 1; 205 } 206 if ( delete $t{$thethread} ) { 207 ${ $uid . $u }{'thread_notifications'} = join q{,}, keys %t; 208 UserAccount($u); 209 } 210 undef %t; 211 } 212 } 213 if ( $todo eq 'save' 214 || $todo eq 'update' 215 || $todo eq 'delete' 216 || $todo eq 'add' ) 217 { 218 if (%thethread) { 219 fopen( THREADNOTE, ">$datadir/$thethread.mail" ); 220 print {THREADNOTE} map { "$_\t$thethread{$_}\n" } 221 sort { $thethread{$a} cmp $thethread{$b} } keys %thethread 222 or croak "$croak{'print'} THREADNOTE"; 223 fclose(THREADNOTE); 224 undef %thethread; 225 } 226 else { 227 unlink "$datadir/$thethread.mail"; 228 } 229 } 230 return; 231} 232 233# sub Notify { deleted because not needed since YaBB 2.3 (deti) 234 235sub Notify2 { 236 if ($iamguest) { fatal_error('members_only'); } 237 238 ManageThreadNotify( 'add', $INFO{'num'}, $username, 239 ${ $uid . $username }{'language'}, 240 1, 1 ); 241 242 if ( $INFO{'oldnotify'} ) { 243 redirectinternal(); 244 } 245 $elenable = 0; 246 croak q{}; # This is here only to avoid server error log entries! 247} 248 249sub Notify3 { 250 if ($iamguest) { fatal_error('members_only'); } 251 252 ManageThreadNotify( 'delete', $INFO{'num'}, $username ); 253 254 if ( $INFO{'oldnotify'} ) { 255 redirectinternal(); 256 } 257 $elenable = 0; 258 croak q{}; # This is here only to avoid server error log entries! 259} 260 261sub Notify4 { 262 if ($iamguest) { fatal_error('members_only'); } 263 foreach my $variable ( keys %FORM ) { 264 my ( $notype, $threadno ) = split /-/xsm, $variable; 265 if ( $notype eq 'thread' ) { 266 ManageThreadNotify( 'delete', $threadno, $username ); 267 } 268 } 269 $action = 'shownotify'; 270 ShowNotifications(); 271 return; 272} 273 274sub updateLanguage { 275 my ( $user, $newlang ) = @_; 276 getMailFiles(); 277 foreach (@bmaildir) { 278 ManageBoardNotify( 'update', $_, $user, $newlang, q{}, q{} ); 279 } 280 foreach (@tmaildir) { 281 ManageThreadNotify( 'update', $_, $user, $newlang, q{}, q{} ); 282 } 283 return; 284} 285 286sub removeNotifications { 287 my $user_s = shift; 288 getMailFiles(); 289 foreach (@bmaildir) { 290 ManageBoardNotify( 'delete', $_, $user_s ); 291 } 292 foreach (@tmaildir) { 293 ManageThreadNotify( 'delete', $_, $user_s ); 294 } 295 return; 296} 297 298sub getMailFiles { 299 opendir BOARDNOT, "$boardsdir"; 300 @bmaildir = 301 map { ( split /\./xsm, $_ )[0] } grep { /\.mail$/xsm } readdir BOARDNOT; 302 closedir BOARDNOT; 303 opendir THREADNOT, "$datadir"; 304 @tmaildir = 305 map { ( split /\./xsm, $_ )[0] } grep { /\.mail$/xsm } readdir THREADNOT; 306 closedir THREADNOT; 307 return; 308} 309 310sub ShowNotifications { 311 ## bye bye guest.... 312 if ($iamguest) { fatal_error('members_only'); } 313 314 $yynavigation = 315qq~› <a href="$scripturl?action=mycenter" class="nav">$img_txt{'mycenter'}</a> › $img_txt{'418'}~; 316 317 LoadLanguage('Notify'); 318 get_template('MyPosts'); 319 320 my @oldnote = split /,/xsm, ${ $uid . $username }{'board_notifications'}; 321 $curbrd = @oldnote; 322 # if ( !$maxtnote ) { $maxtnote = 10; } 323 324 # $note_brd = qq~<br />$notify_txt{'75'}<br />$notify_txt{'76'} $curbrd $notify_txt{'77'} $maxtnote $notify_txt{'78'}~; 325 $curbrd = NumberFormat($curbrd); 326 327 # Show Javascript for 'check all' notifications 328 329 ( $board_notify, $thread_notify ) = NotificationAlert(); 330 my ( $num, $new ); 331 332 # Board notifications 333 foreach ( keys %{$board_notify} ) { # boardname, boardnotifytype , new 334 $num++; 335 336 my ( $selected1, $selected2 ); 337 if ( ${ $$board_notify{$_} }[1] == 1 ) { # new topics 338 $selected1 = q~ selected="selected"~; 339 } 340 else { # all new posts 341 $selected2 = q~ selected="selected"~; 342 } 343 344 if ( ${ $$board_notify{$_} }[2] ) { 345 $new = 346qq~<img src="$imagesdir/$brdimg_new" alt="$notify_txt{'333'}" title="$notify_txt{'333'}" />~; 347 } 348 else { 349 $new = 350qq~<img src="$imagesdir/$brdimg_old" alt="$notify_txt{'334'}" title="$notify_txt{'334'}" />~; 351 } 352 353 ## output notify detail - option 3 = remove notify 354 $boardblock .= $my_boardblock; 355 $boardblock =~ s/{yabb brd}/$_/gsm; 356 $boardblock =~ s/{yabb new}/$new/gsm; 357 $boardblock =~ s/{yabb brdnote0}/${$$board_notify{$_}}[0]/gsm; 358 $boardblock =~ s/{yabb selected1}/$selected1/gsm; 359 $boardblock =~ s/{yabb selected2}/$selected2/gsm; 360 } 361 362 if ( !$num ) { # no board notifies up 363 $my_showNotifications_b = $my_nonotes; 364 } 365 else { # list boards 366 $my_showNotifications_b = $my_notebrdlist; 367 $my_showNotifications_b =~ s/{yabb boardblock}/$boardblock/gsm; 368 } 369 370 $num = 0; 371 foreach ( keys %{$thread_notify} ) 372 { # mythread, msub, new, username_link, catname_link, boardname_link, lastpostdate 373 $num++; 374 375 ## build block for display 376 $threadblock .= $my_threadblock; 377 $threadblock =~ s/{yabb tnote0}/${$$thread_notify{$_}}[0]/gsm; 378 $threadblock =~ s/{yabb tnote1}/${$$thread_notify{$_}}[1]/gsm; 379 $threadblock =~ s/{yabb tnote2}/${$$thread_notify{$_}}[2]/gsm; 380 $threadblock =~ s/{yabb tnote3}/${$$thread_notify{$_}}[3]/gsm; 381 $threadblock =~ s/{yabb tnote4}/${$$thread_notify{$_}}[4]/gsm; 382 $threadblock =~ s/{yabb tnote5}/${$$thread_notify{$_}}[5]/gsm; 383 $threadblock =~ s/{yabb tnote6}/${$$thread_notify{$_}}[6]/gsm; 384 } 385 386 if ( !$num ) { ## no threads listed 387 $my_showNotifications_t = $my_nothreads; 388 } 389 else { ## output details 390 $my_showNotifications_t = $my_threadnote_b; 391 $my_showNotifications_t =~ s/{yabb threadblock}/$threadblock/gsm; 392 } 393 $showNotifications = $my_boardnote; 394 395 # $showNotifications =~ s/{yabb note_brd}/$note_brd/sm; 396 $showNotifications =~ s/{yabb note_brd}//sm; 397 $showNotifications =~ 398 s/{yabb my_showNotifications_b}/$my_showNotifications_b/sm; 399 $showNotifications =~ 400 s/{yabb my_showNotifications_t}/$my_showNotifications_t/sm; 401 $showNotifications .= $my_threadnote_end; 402 403 $yytitle = "$notify_txt{'124'}"; 404 405 ## and finally, add jump menu for a route back. 406 if ( !$view ) { 407 jumpto(); 408 $yymain .= qq~$showNotifications$selecthtml~; 409 template(); 410 } 411 return; 412} 413 414sub NotificationAlert { 415 my ( $myboard, %board_notify, $mythread, %thread_notify ); 416 417 @bmaildir = split /,/xsm, ${ $uid . $username }{'board_notifications'}; 418 @tmaildir = split /,/xsm, ${ $uid . $username }{'thread_notifications'}; 419 420 # needed for $new - icon (on/off/new) 421 my @noloadboard = 422 grep { !exists ${ $uid . $_ }{'lastposttime'} } @allboards; 423 if (@noloadboard) { BoardTotals( 'load', @noloadboard ); } 424 425 # to get ${$uid.$myboard}{'lastposttime'} 426 getlog(); # sub in Subs.pm, for $yyuserlog{$myboard} 427 my $dmax = $date - ( $max_log_days_old * 86400 ); 428 429 ## run through boards list 430 foreach my $myboard (@bmaildir) { # board name from file name 431 if ( !-e "$boardsdir/$myboard.txt" ) 432 { # remove from user board_notifications 433 ManageBoardNotify( 'delete', $myboard, $username ); 434 next; 435 } 436 437 ## load in hash of name / detail for board 438 ManageBoardNotify( 'load', $myboard ); 439 440 if ( exists $theboard{$username} ) { 441 ## grab board name 442 my $boardname = ( split /\|/xsm, $board{$myboard} )[0]; 443 444 $board_notify{$myboard} = [ 445 $boardname, 446 ( split /\|/xsm, $theboard{$username} )[1], # boardnotifytype 447 ( 448 ( 449 $max_log_days_old 450 && int( ${ $uid . $myboard }{'lastposttime'} ) 451 && ( 452 ( 453 !$yyuserlog{$myboard} 454 && ${ $uid . $myboard }{'lastposttime'} > $dmax 455 ) 456 || ( $yyuserlog{$myboard} > $dmax 457 && $yyuserlog{$myboard} < 458 ${ $uid . $myboard }{'lastposttime'} ) 459 ) 460 ) ? 1 : 0 461 ), # new == 1 462 ]; 463 464 undef %theboard; 465 } 466 } 467 468 if ( $action eq 'shownotify' ) { LoadCensorList(); } 469 470 ## load board names 471 get_forum_master(); # for $board{...} 472 473 foreach my $mythread (@tmaildir) { # number of next thread 474 # see if thread exists and search for it if moved 475 if ( !-e "$datadir/$mythread.txt" ) { 476 ManageThreadNotify( 'delete', $mythread, $username ); 477 if ( eval { require Variables::Movedthreads; 1 } ) { 478 next 479 if !exists $moved_file{$mythread} || !$moved_file{$mythread}; 480 my $newthread; 481 while ( exists $moved_file{$mythread} ) { 482 $mythread = $moved_file{$mythread}; 483 if ( !exists $moved_file{$mythread} 484 && -e "$datadir/$mythread.txt" ) 485 { 486 $newthread = $mythread; 487 } 488 } 489 next if !$newthread; 490 ManageThreadNotify( 'add', $newthread, $username, 491 ${ $uid . $username }{'language'}, 492 1, 1 ); 493 } 494 } 495 496 ## load threads hash 497 ManageThreadNotify( 'load', $mythread ); 498 499 if ( exists $thethread{$username} ) { 500 ## load ctb file for board data 501 MessageTotals( 'load', $mythread ); 502 503 ## pull out board and last post 504 my $boardid = ${$mythread}{'board'}; 505 my ( $msub, $mname, $musername, $new, $username_link, $catname_link, 506 $boardname_link, $lastpostdate ); 507 if ( $action eq 'shownotify' ) { 508 if ( !${ ${ 'notify' . $boardid . $mythread } }[0] ) { 509 my ( $messageid, $messagesubject ); 510 fopen( BOARDTXT, "$boardsdir/$boardid.txt" ) 511 or fatal_error( 'cannot_open', "$boardsdir/$boardid.txt", 512 1 ); 513 while ( my $brd = <BOARDTXT> ) { 514 ( 515 $messageid, $messagesubject, $mname, undef, undef, 516 undef, $musername, undef 517 ) = split /\|/xsm, $brd, 8; 518 ${ 'notify' . $boardid . $messageid } = 519 [ $messagesubject, $mname, $musername ]; 520 } 521 fclose(BOARDTXT); 522 } 523 $msub = ${ ${ 'notify' . $boardid . $mythread } }[0]; 524 $mname = ${ ${ 'notify' . $boardid . $mythread } }[1]; 525 $musername = ${ ${ 'notify' . $boardid . $mythread } }[2]; 526 527 ToChars($msub); 528 ( $msub, undef ) = Split_Splice_Move( $msub, 0 ); 529 $msub = Censor($msub); # censor subject text ! 530 531 ## run through the categories until we hit the match for category name 532 my ( $catname, $thiscatid, $catid ); 533 my $boardname = ( split /\|/xsm, $board{$boardid} )[0]; 534 535 # grab boardname from list 536 CHECKBOARDNAME: foreach my $catid (@categoryorder) { 537 foreach ( split /\,/xsm, $cat{$catid} ) { 538 ## find the match, grab data and jump out 539 if ( $_ eq $boardid ) { 540 $catname = ( split /\|/xsm, $catinfo{$catid} )[0]; 541 $thiscatid = $catid; 542 last CHECKBOARDNAME; 543 } 544 } 545 } 546 $catname_link = 547 qq~<a href="$scripturl?catselect=$thiscatid">$catname</a>~; 548 $boardname_link = 549 qq~<a href="$scripturl?board=$boardid">$boardname</a>~; 550 551 ## build view profile link, if real name exists 552 LoadUser($musername); # load poster 553 if ( ${ $uid . $musername }{'realname'} ) { 554 $username_link = 555qq~<a href="$scripturl?action=viewprofile;username=$useraccount{$musername}">$format_unbold{$musername}</a>~; 556 } 557 elsif ($mname) { 558 $username_link = $mname; 559 } 560 else { 561 $username_link = $musername; 562 } 563 564 ## format last post for output 565 $lastpostdate = timeformat( ${$mythread}{'lastpostdate'} ); 566 } 567 568 if ($max_log_days_old) { 569 570 # Decide if thread should have the "NEW" indicator next to it. 571 # Do this by reading the user's log for last read time on thread, 572 # and compare to the last post time on the thread. 573 my $dlp = int $yyuserlog{$mythread}; 574 my $dlpb = int $yyuserlog{"$boardid--mark"}; 575 $dlp = $dlp > $dlpb ? $dlp : $dlpb; 576 if ( $yyuserlog{"$mythread--unread"} 577 || ( !$dlp && ${$mythread}{'lastpostdate'} > $dmax ) 578 || ( $dlp > $dmax && $dlp < ${$mythread}{'lastpostdate'} ) ) 579 { 580 $new = 581qq~<img src="$imagesdir/$brdimg_new" alt="$notify_txt{'335'}" title="$notify_txt{'335'}"/>~; 582 } 583 } 584 585 $thread_notify{$mythread} = [ 586 $mythread, $msub, $new, 587 $username_link, $catname_link, $boardname_link, 588 $lastpostdate 589 ]; 590 } 591 } 592 593 return ( \%board_notify, \%thread_notify ); 594} 595 5961; 597