############################################################################### # MoveSplitSplice.pm # # $Date: 26.7.26 $ # ############################################################################### # YaBB: Yet another Bulletin Board # # Open-Source Community Software for Webmasters # # Version: YaBB 2.6.15 # # Packaged: July 26, 2026 # # Distributed by: https://yabbforum.nz # # =========================================================================== # # Copyright (c) 2000-2026 YaBB (yabbforum.nz) - All Rights Reserved. # # Software by: The YaBB Development Team # # with assistance from the YaBB community. # ############################################################################### use CGI::Carp qw(fatalsToBrowser); our $VERSION = '2.6.15'; $movesplitsplicepmver = 'YaBB 2.6.15 $Revision: 2601 $'; if ( $action eq 'detailedversion' ) { return 1; } LoadLanguage('MoveSplitSplice'); get_template('Display'); sub Split_Splice { if ( !$staff ) { fatal_error('split_splice_not_allowed'); } if ( $FORM{'ss_submit'} || $INFO{'ss_submit'} ) { Split_Splice_2(); } my $curboard = $INFO{'board'}; my $curthread = $INFO{'thread'}; if ( !exists $FORM{'oldposts'} ) { $FORM{'oldposts'} = $INFO{'oldposts'}; } if ( !exists $FORM{'leave'} ) { $FORM{'leave'} = $INFO{'leave'}; } if ( exists $INFO{'newinfo'} ) { $FORM{'newinfo'} = $INFO{'newinfo'}; } my $newcat = $FORM{'newcat'} || $INFO{'newcat'}; my $newboard = $FORM{'newboard'} || $INFO{'newboard'}; if ( !exists $FORM{'newthread'} ) { $FORM{'newthread'} = $INFO{'newthread'}; } my $newthread = $FORM{'newthread'} || 'new'; if ( !exists $FORM{'newthread_subject'} ) { $FORM{'newthread_subject'} = $INFO{'newthread_subject'}; } if ( !exists $FORM{'position'} ) { $FORM{'position'} = $INFO{'position'}; } require Sources::YaBBC; LoadCensorList(); # Get posts of current thread if ( !ref $thread_arrayref{$curthread} ) { fopen( FILE, "$datadir/$curthread.txt" ); @{ $thread_arrayref{$curthread} } = ; fclose(FILE); } my @messages = @{ $thread_arrayref{$curthread} }; my ( $counter, $size1 ); for my $counter ( 0 .. $#messages ) { $message = ( split /\|/xsm, $messages[$counter], 10 )[8]; ( $message, undef ) = Split_Splice_Move( $message, 1 ); DoUBBC(); $convertstr = $message; $convertstr =~ s/<(p|br|div).*?>/ /gxsm; $convertstr =~ s/<.*?>//gxsm; # remove HTML-tags $convertcut = 50; CountChars(); $message = $convertstr; if ($cliped) { $message .= ' ...'; } ToChars($message); $message = Censor($message); $messages[$counter] = qq~\n~; } if ( ( $ttsureverse && ${ $uid . $username }{'reversetopic'} ) || $ttsreverse ) { @messages = reverse @messages; } my $postlist = ( $FORM{'oldposts'} eq 'all' ? qq~\n~ : qq~\n~ ) . join q{}, @messages; $size1 = @messages + 1; $size1 = $size1 > 10 ? 10 : $size1; # maximum size of multiselect field # List of options of what, if anything, to leave in place of the posts moved my @leaveopts = ( $sstxt{'11'}, $sstxt{'12'}, $sstxt{'13'} ); for my $counter ( 0 .. $#leaveopts ) { $leavelist .= qq~\n~; } # Get categories and make the current one the default selection my $catlist = qq~\n~; foreach (@categoryorder) { my ( $catname, $catperms ) = split /\|/xsm, $catinfo{$_}, 3; next if !CatAccess($catperms); $catlist .= qq~\n~; } # Get boards and make the current one the default selection $boardlist = qq~\n~; my $indent = -2; *get_subboards = sub { my @x = @_; $indent += 2; foreach my $childbd (@x) { my $dash; if ( $indent > 0 ) { $dash = q{-}; } my ( $boardname, $boardperms ) = split /\|/xsm, $board{$childbd}, 3; ToChars($boardname); my $access = AccessCheck( $_, q{}, $boardperms ); next if !$iamadmin && $access ne 'granted' && $boardview != 1; my $bdnopost = ( ${ $uid . $childbd }{'canpost'} || !$subboard{$childbd} ) ? q{} : q~ class="nopost"~; $boardlist .= qq~~ . ( ' ' x $indent ) . ( $dash x ( $indent / 2 ) ) . qq~ $boardname\n~; if ( $subboard{$childbd} ) { get_subboards( split /\|/xsm, $subboard{$childbd} ); } } $indent -= 2; return; }; get_subboards( split /,/xsm, $cat{$newcat} ); # Get threads and make the current one the default selection my ( $threadlist, $threadids, $positionlist ); fopen( FILE, "$boardsdir/$newboard.txt" ); my @threads = ; fclose(FILE); $threadlist = qq~\n~; my $threadid; foreach (@threads) { ( $threadid, $message, undef ) = split /\|/xsm, $_, 3; next if $curthread eq $threadid; $threadids .= "$threadid,"; ( $message, undef ) = Split_Splice_Move( $message, $threadid ); DoUBBC(); $convertstr = $message; $convertcut = 50; CountChars(); $message = $convertstr; if ($cliped) { $message .= ' ...'; } ToChars($message); $message =~ s/<(p|br|div).*?>/ /gxsm; $message =~ s/<.*?>//gxsm; # remove HTML-tags $message = Censor($message); $threadlist .= qq~\n~; } # Get new thread posts to select splice site if ( $FORM{'newthread'} ne 'new' ) { if ( !ref $thread_arrayref{$newthread} ) { fopen( FILE, "$datadir/$newthread.txt" ); @{ $thread_arrayref{$newthread} } = ; fclose(FILE); } @messages = @{ $thread_arrayref{$newthread} }; for my $counter ( 0 .. $#messages ) { $message = ( split /[\|]/xsm, $messages[$counter], 10 )[8]; ( $message, undef ) = Split_Splice_Move( $message, 1 ); DoUBBC(); $convertstr = $message; $convertcut = 50; CountChars(); $message = $convertstr; if ($cliped) { $message .= ' ...'; } ToChars($message); $message =~ s/<(p|br|div).*?>/ /gxsm; $message =~ s/<.*?>//gxsm; # remove HTML-tags $message = Censor($message); $messages[$counter] = qq~\n~; } if ( ( $ttsureverse && ${ $uid . $username }{'reversetopic'} ) || $ttsreverse ) { @messages = reverse @messages; } $positionlist = qq~\n~; $positionlist .= qq~\n~; $positionlist .= join q{}, @messages; if ( $FORM{'position'} && $newthread == $FORM{'old_position_thread'} ) { $positionlist =~ s/(value="$FORM{'position'}")/$1 selected="selected"/xsm; } } if ( $newthread eq 'new' || !$threadlist || $threadids !~ /\b$newthread\b/xsm ) { $my_output = $mymove_output_a; $my_output =~ s/{yabb newthread_subject}/$FORM{'newthread_subject'}/sm; $my_output =~ s/{yabb position}/$FORM{'position'}/sm; $my_output =~ s/{yabb old_position_thread}/$FORM{'old_position_thread'}/sm; } else { $my_output = $mymove_output_b; $my_output =~ s/{yabb positionlist}/$positionlist/sm; $my_output =~ s/{yabb newthread_subject}/$FORM{'newthread_subject'}/sm; $my_output =~ s/{yabb newthread}/$newthread/sm; } $my_checked = $FORM{'newinfo'} ? ' checked="checked"' : q{}; $output = $mymove_top; $output =~ s/{yabb formsession}/$formsession/sm; $output =~ s/{yabb postlist}/$postlist/sm; $output =~ s/{yabb leavelist}/$leavelist/sm; $output =~ s/{yabb catlist}/$catlist/sm; $output =~ s/{yabb boardlist}/$boardlist/sm; $output =~ s/{yabb threadlist}/$threadlist/sm; $output =~ s/{yabb my_output}/$my_output/sm; $output =~ s/{yabb my_checked}/$my_checked/sm; $output =~ s/{yabb size1}/$size1/sm; print_output_header(); print_HTML_output_and_finish(); return; } sub Split_Splice_2 { if ( !$staff && $INFO{'newboard'} ne $binboard ) { fatal_error('split_splice_not_allowed'); } my $curboard = $INFO{'board'}; my $curthreadid = $INFO{'thread'}; my $movingposts = exists $INFO{'oldposts'} ? $INFO{'oldposts'} : $FORM{'oldposts'}; $FORM{'oldposts'} = $movingposts; my $leavemess = exists $INFO{'leave'} ? $INFO{'leave'} : $FORM{'leave'}; my $forcenewinfo = exists $INFO{'newinfo'} ? $INFO{'newinfo'} : $FORM{'newinfo'}; my $newcat = exists $INFO{'newcat'} ? $INFO{'newcat'} : $FORM{'newcat'}; my $newboard = exists $INFO{'newboard'} ? $INFO{'newboard'} : $FORM{'newboard'}; my $newthreadid = exists $INFO{'newthread'} ? $INFO{'newthread'} : $FORM{'newthread'}; $FORM{'newthread'} = $newthreadid; my $newthreadsub = exists $INFO{'newthread_subject'} ? $INFO{'newthread_subject'} : $FORM{'newthread_subject'}; my $newposition = exists $INFO{'position'} ? $INFO{'position'} : $FORM{'position'}; $FORM{'position'} = $newposition; # Error messages if something is not filled out right if ( $movingposts eq q{} ) { fatal_error( q{}, "$sstxt{'22b'} $sstxt{'23'} $sstxt{'50'}" ); } if ( $newcat eq 'cats' ) { fatal_error( q{}, "$sstxt{'22'}" ); } if ( $newboard eq 'boards' ) { fatal_error( q{}, "$sstxt{'22a'}" ); } if ( -e "$datadir/$curthreadid.poll" && -e "$datadir/$newthreadid.poll" ) { fatal_error( q{}, "$sstxt{'51'} $sstxt{'50'}" ); } my ( @postnum, @utdcurthread, @utdnewthread, $i ); my $linkcount = 0; # Get current thread posts if ( !ref $thread_arrayref{$curthreadid} ) { fopen( FILE, "$datadir/$curthreadid.txt" ); @{ $thread_arrayref{$curthreadid} } = ; fclose(FILE); } my @curthread = @{ $thread_arrayref{$curthreadid} }; MessageTotals( 'load', $curthreadid ); # Store post numbers to be moved in array if ( ( split /\, /sm, $movingposts, 2 )[0] eq 'all' ) { @postnum = ( 0 .. $#curthread ); } else { @postnum = sort { $a <=> $b } split /\, /sm, $movingposts; } # sort numerically ascending because may be reversed! # Check to see if current thread was the latest post for the board and if the last post was selected to change BoardTotals( 'load', $curboard ); if ( ${$curthreadid}{'lastpostdate'} == ${ $uid . $curboard }{'lastposttime'} && $leavemess == 2 && $postnum[-1] == $#curthread ) { $newest_post = 1; } # Move selected posts to a brand new thread if ( $newthreadid eq 'new' ) { # Find a valid random ID for new thread. $newthreadid = ( split /\|/xsm, $curthread[ $postnum[0] ], 5 )[3] + 1; while ( -e "$datadir/$newthreadid.txt" ) { $newthreadid++; } foreach (@postnum) { if ( $newthreadsub || $leavemess == 1 ) { # insert new subject name || add 'no_postcount' into copies my @x = split /\|/xsm, $curthread[$_]; if ($newthreadsub) { $x[0] = $_ == $postnum[0] ? $newthreadsub : qq~$sstxt{'21'} $newthreadsub~; } if ( $leavemess == 1 ) { $x[5] = 'no_postcount'; } push @utdnewthread, join q{|}, @x; } else { push @utdnewthread, $curthread[$_]; } } # Place selected posts in existing thread at selected position } else { # Get existing thread posts if ( !ref $thread_arrayref{$newthreadid} ) { fopen( FILE, "$datadir/$newthreadid.txt" ); @{ $thread_arrayref{$newthreadid} } = ; fclose(FILE); } my @newthread = @{ $thread_arrayref{$newthreadid} }; MessageTotals( 'load', $newthreadid ); if ( $newposition eq 'end' ) { $newposition = $#newthread; } elsif ( $newposition eq 'begin' ) { foreach (@postnum) { if ( $leavemess == 1 ) { # add 'no_postcount' into copies my @x = split /\|/xsm, $curthread[$_]; $x[5] = 'no_postcount'; push @utdnewthread, join q{|}, @x; } else { push @utdnewthread, $curthread[$_]; } } $newposition = -1; } for my $i ( 0 .. $#newthread ) { push @utdnewthread, $newthread[$i]; if ( $newposition == $i ) { foreach (@postnum) { if ( $leavemess == 1 ) { # add 'no_postcount' into copies my @x = split /\|/xsm, $curthread[$_]; $x[5] = 'no_postcount'; push @utdnewthread, join q{|}, @x; } else { push @utdnewthread, $curthread[$_]; } } $linkcount = $i + 1; } } } # Remove or copy selected posts from current thread if ( $#postnum == $#curthread && $leavemess != 1 ) { if ( $newboard ne $binboard ) { my ( $tmpsub, $tmpmessage ); my $hidename = cloak($username); ( $tmpsub, undef ) = split /\|/xsm, $curthread[0], 2; if ( $curboard eq $newboard ) { $tmpmessage = qq~[m by=$hidename dest=$newthreadid/$linkcount#$linkcount]~; $tmpsub = qq~[m by=$hidename dest=$newthreadid]: '$tmpsub'~; } else { $tmpmessage = qq~[m by=$hidename destboard=$newboard dest=$newthreadid/$linkcount#$linkcount]~; $tmpsub = qq~[m by=$hidename destboard=$newboard dest=$newthreadid]: '$tmpsub'~; } FromChars($tmpmessage); $utdcurthread[0] = qq~$tmpsub|${$uid.$username}{'realname'}|${$uid.$username}{'email'}|$date|$username|no_postcount||$user_ip|$tmpmessage||||\n~; if ( eval { require Variables::Movedthreads; 1 } ) { $moved_file{$curthreadid} = $newthreadid; delete $moved_file{$newthreadid}; save_moved_file(); $leavemess = 0; } } else { $leavemess = 2; $forcenewinfo = 1; } } elsif ( $leavemess != 1 ) { if ( $newboard eq $binboard ) { $leavemess = 2; } for my $i ( 0 .. $#curthread ) { if ( $movingposts =~ /\b$i\b/xsm ) { if ( $leavemess == 0 && $i == $postnum[-1] ) { my $tmpsub; ( $tmpsub, undef ) = split /\|/xsm, $curthread[$i], 2; push @utdcurthread, qq~$tmpsub|${$uid.$username}{'realname'}|${$uid.$username}{'email'}|$date|$username|no_postcount||$user_ip|[split] [link=$scripturl?num=$newthreadid/$linkcount#$linkcount][splithere][/link][splithere_end]||||\n~; } } else { push @utdcurthread, $curthread[$i]; } } } else { @utdcurthread = @curthread; } if ($forcenewinfo) { my ( $boardtitle, $tmpsub, $tmpmessage ); ( $boardtitle, undef ) = split /\|/xsm, $board{$curboard}, 2; $tmpmessage = ( $#postnum == $#utdnewthread ? '[b][movedhere]' : '[b][postsmovedhere1] ' . @postnum . ' [postsmovedhere2]' ) . " [i]$boardtitle\[/i] [move by] [i]${$uid.$username}{'realname'}\[/i].[/b]"; FromChars($tmpmessage); ( $tmpsub, undef, undef, undef, undef, undef, undef ) = split /\|/xsm, $utdnewthread[0], 7; splice @utdnewthread, ( $linkcount + @postnum ), 0, qq~$sstxt{'21'} $tmpsub|${$uid.$username}{'realname'}|${$uid.$username}{'email'}|$date|$username|no_postcount||$user_ip|$tmpmessage||||\n~; } if (@utdcurthread) { for my $i ( 0 .. $#utdcurthread ) { # sort post numbers my @x = split /\|/xsm, $utdcurthread[$i]; $x[6] = $i; $utdcurthread[$i] = join q{|}, @x; } # Update current thread fopen( FILE, ">$datadir/$curthreadid.txt" ); print {FILE} @utdcurthread or croak "$croak{'print'} FILE"; fclose(FILE); } else { require Sources::RemoveTopic; my $moveit = $INFO{'moveit'}; $INFO{'moveit'} = 1; RemoveThread(); $INFO{'moveit'} = $moveit; } for my $i ( 0 .. $#utdnewthread ) { # sort post numbers my @x = split /\|/xsm, $utdnewthread[$i]; $x[6] = $i; $utdnewthread[$i] = join q{|}, @x; } # Update new thread fopen( FILE, ">$datadir/$newthreadid.txt" ); print {FILE} @utdnewthread or croak "$croak{'print'} FILE"; fclose(FILE); # Update the .rlog files of the users my ( $reply, $ms, $mn, $md, $mu, $mnp, $mi, %mu, %curthreadusersdate, %curthreaduserscount, %newthreadusersdate, %newthreaduserscount, %BoardTotals ); $reply = 0; foreach (@utdcurthread) { # $subject|$name|$email|$date|$username|$icon|0|$user_ip|$message|$ns|||$fixfile ( $ms, $mn, undef, $md, $mu, $mnp, undef, $mi, undef ) = split /\|/xsm, $_, 9; if ( ${ $BoardTotals{$curthreadid} }[0] <= $md ) { $BoardTotals{$curthreadid} = [ $md, $mu, $reply, $ms, $mn, $mi ]; } $reply++; next if $mnp eq 'no_postcount'; if ( $curthreadusersdate{$mu} < $md ) { $curthreadusersdate{$mu} = $md; } $curthreaduserscount{$mu}++; $mu{$mu} = 1; } $reply = 0; foreach (@utdnewthread) { ( $ms, $mn, undef, $md, $mu, $mnp, undef, $mi, undef ) = split /\|/xsm, $_, 9; if ( ${ $BoardTotals{$newthreadid} }[0] <= $md ) { $BoardTotals{$newthreadid} = [ $md, $mu, $reply, $ms, $mn, $mi ]; } $reply++; next if $mnp eq 'no_postcount'; if ( $newthreadusersdate{$mu} < $md ) { $newthreadusersdate{$mu} = $md; } $newthreaduserscount{$mu}++; $mu{$mu} = 1; } foreach my $mu ( keys %mu ) { Recent_Load($mu); delete $recent{$curthreadid}; delete $recent{$newthreadid}; if ( $curthreaduserscount{$mu} ) { ${ $recent{$curthreadid} }[0] = $curthreaduserscount{$mu}; ${ $recent{$curthreadid} }[1] = $curthreadusersdate{$mu}; } if ( $newthreaduserscount{$mu} ) { ${ $recent{$newthreadid} }[0] = $newthreaduserscount{$mu}; ${ $recent{$newthreadid} }[1] = $newthreadusersdate{$mu}; } Recent_Save($mu); } # For: Mark threads/boards as read getlog(); my $boardlog = 1; # Mark new thread as read because you will be directed there at the end delete $yyuserlog{"$newthreadid--unread"}; $yyuserlog{$newthreadid} = $date; # Update .ctb, tags=>(board replies views lastposter lastpostdate threadstatus repliers) # curthread ${$curthreadid}{'replies'} = $#utdcurthread; ${$curthreadid}{'lastpostdate'} = ${ $BoardTotals{$curthreadid} }[0]; ${$curthreadid}{'lastposter'} = ${ $BoardTotals{$curthreadid} }[1] eq 'Guest' ? "Guest-${$BoardTotals{$curthreadid}}[4]" : ${ $BoardTotals{$curthreadid} }[1]; # newthread ${$newthreadid}{'replies'} = $#utdnewthread; ${$newthreadid}{'lastpostdate'} = ${ $BoardTotals{$newthreadid} }[0]; ${$newthreadid}{'lastposter'} = ${ $BoardTotals{$newthreadid} }[1] eq 'Guest' ? "Guest-${$BoardTotals{$newthreadid}}[4]" : ${ $BoardTotals{$newthreadid} }[1]; if ( $FORM{'newthread'} eq 'new' ) { ${$newthreadid}{'board'} = $newboard; ${$newthreadid}{'views'} = $#postnum == $#curthread ? ${$curthreadid}{'views'} : ( $INFO{'ss_submit'} ? 1 : 0 ); ${$newthreadid}{'threadstatus'} = ${$curthreadid}{'threadstatus'}; ${$curthreadid}{'views'} = $#postnum == $#curthread && $leavemess != 1 ? 0 : ${$curthreadid}{'views'}; } else { ${$newthreadid}{'views'} += int( ${$curthreadid}{'views'} / @curthread * @postnum ); } # Update current message index fopen( BOARD, "<$boardsdir/$curboard.txt", 1 ); my @curmessindex = ; fclose( BOARD ); my $old_mstate; for my $i ( 0 .. $#curmessindex ) { my ( $mnum, $msub, $mname, $memail, $mdate, $mreplies, $musername, $micon, $mstate ) = split /\|/xsm, $curmessindex[$i]; if ( $mdate > $yyuserlog{$curboard} ) { $boardlog = 0; } # For: Mark boards as read if ( $mnum == $curthreadid ) { chomp $mstate; if ( $#postnum == $#curthread && $leavemess != 1 ) { # thread was moved my $hidename = cloak($username); if ( $curboard eq $newboard ) { $msub = qq~[m by=$hidename dest=$newthreadid]: '$msub'~; } else { $msub = qq~[m by=$hidename destboard=$newboard dest=$newthreadid]: '$msub'~; } $mname = ${ $uid . $username }{'realname'}; $memail = ${ $uid . $username }{'email'}; $mreplies = 0; $musername = $username; # alter message icon to 'exclamation' to match status 'lm' if ( $micon ne 'no_postcount' ) { $micon = 'exclamation'; } # thread status - (a)nnoumcement, (h)idden, (l)ocked, (m)oved and (s)ticky $old_mstate = $mstate; if ( $curboard eq $annboard && $mstate !~ /a/ism ) { $mstate .= 'a'; } if ( $mstate !~ /l/ism ) { $mstate .= 'l'; } if ( $mstate !~ /m/ism ) { $mstate .= 'm'; } ${$curthreadid}{'threadstatus'} = $mstate; } else { ( $msub, $mname, $memail, undef, $musername, $micon, undef ) = split /\|/xsm, $utdcurthread[0], 7; $mreplies = ${$curthreadid}{'replies'}; } $curmessindex[$i] = qq~$mnum|$msub|$mname|$memail|${$curthreadid}{'lastpostdate'}|$mreplies|$musername|$micon|$mstate\n~; ${ $BoardTotals{$mnum} }[6] = $mstate; } elsif ( $mnum == $newthreadid ) { chomp $mstate; if ( $FORM{'position'} eq 'begin' ) { ( $msub, $mname, $memail, undef, $musername, $micon, undef ) = split /\|/xsm, $utdnewthread[0], 7; } $yyThreadLine = $curmessindex[$i] = qq~$mnum|$msub|$mname|$memail|${$newthreadid}{'lastpostdate'}|${$newthreadid}{'replies'}|$musername|$micon|$mstate\n~; ${ $BoardTotals{$mnum} }[6] = $mstate; if ( ( $enable_notifications == 1 || $enable_notifications == 3 ) && ( -e "$boardsdir/$curboard.mail" || -e "$datadir/$newthreadid.mail" ) ) { require Sources::Post; $currentboard = $curboard; $msub = Censor($msub); ReplyNotify( $newthreadid, $msub, ${$newthreadid}{'replies'} ); } } } if ( $curboard eq $newboard && $FORM{'newthread'} eq 'new' ) { my ( $msub, $mname, $memail, $musername, $micon ); ( $msub, $mname, $memail, undef, $musername, $micon, undef ) = split /\|/xsm, $utdnewthread[0], 7; if ( $old_mstate !~ /0/ism ) { $old_mstate .= '0'; } $yyThreadLine = qq~$newthreadid|$msub|$mname|$memail|${$newthreadid}{'lastpostdate'}|${$newthreadid}{'replies'}|$musername|$micon|$old_mstate\n~; unshift @curmessindex, $yyThreadLine; ${ $BoardTotals{$newthreadid} }[6] = $old_mstate; if ( ( $enable_notifications == 1 || $enable_notifications == 3 ) && -e "$boardsdir/$newboard.mail" ) { require Sources::Post; $currentboard = $curboard; $msub = Censor($msub); NewNotify( $newthreadid, $msub ); } } fopen( BOARD, ">$boardsdir/$curboard.txt", 1 ); print {BOARD} reverse sort { ( split /\|/xsm, $a, 6 )[4] <=> ( split /\|/xsm, $b, 6 )[4] } @curmessindex or croak "$croak{'print'} BOARD"; fclose( BOARD ); if ($boardlog) { $yyuserlog{$curboard} = $date; } # For: Mark boards as read # Update new message index if needed if ( $curboard ne $newboard ) { $boardlog = 1; # For: Mark boards as read fopen( BOARD, "+<$boardsdir/$newboard.txt", 1 ); seek BOARD, 0, 0; my @newmessindex = ; truncate BOARD, 0; seek BOARD, 0, 0; if ( $FORM{'newthread'} eq 'new' ) { # For: Mark boards as read foreach (@newmessindex) { if ( ( split /\|/xsm, $_, 6 )[4] > $yyuserlog{$newboard} ) { $boardlog = 0; } last if !$boardlog; } my ( $msub, $mname, $memail, undef, $musername, $micon, undef ) = split /\|/xsm, $utdnewthread[0], 7; if ( $old_mstate =~ /a/ism ) { if ( $newboard ne $annboard ) { $old_mstate =~ s/a//gism; } } elsif ( $newboard eq $annboard ) { $old_mstate .= 'a'; } if ( $old_mstate !~ /0/ism ) { $old_mstate .= '0'; } $yyThreadLine = qq~$newthreadid|$msub|$mname|$memail|${$newthreadid}{'lastpostdate'}|${$newthreadid}{'replies'}|$musername|$micon|$old_mstate\n~; unshift @newmessindex, $yyThreadLine; ${ $BoardTotals{$newthreadid} }[6] = $old_mstate; if ( ( $enable_notifications == 1 || $enable_notifications == 3 ) && -e "$boardsdir/$newboard.mail" ) { require Sources::Post; $currentboard = $newboard; $msub = Censor($msub); NewNotify( $newthreadid, $msub ); } } else { for my $i ( 0 .. $#newmessindex ) { my ( $mnum, $msub, $mname, $memail, $mdate, $mreplies, $musername, $micon, $mstate ) = split /\|/xsm, $newmessindex[$i]; if ( $mdate > $yyuserlog{$newboard} ) { $boardlog = 0; } # For: Mark boards as read if ( $mnum == $newthreadid ) { chomp $mstate; if ( $FORM{'position'} eq 'begin' ) { ( $msub, $mname, $memail, undef, $musername, $micon, undef ) = split /\|/xsm, $utdnewthread[0], 7; } $yyThreadLine = $newmessindex[$i] = qq~$mnum|$msub|$mname|$memail|${$newthreadid}{'lastpostdate'}|${$newthreadid}{'replies'}|$musername|$micon|$mstate\n~; ${ $BoardTotals{$mnum} }[6] = $mstate; } } if ( ( $enable_notifications == 1 || $enable_notifications == 3 ) && ( -e "$boardsdir/$newboard.mail" || -e "$datadir/$newthreadid.mail" ) ) { require Sources::Post; $currentboard = $newboard; $msub = Censor($msub); ReplyNotify( $newthreadid, $msub, ${$newthreadid}{'replies'} ); } } print {BOARD} reverse sort { ( split /\|/xsm, $a, 6 )[4] <=> ( split /\|/xsm, $b, 6 )[4] } @newmessindex or croak "$croak{'print'} BOARD"; fclose(BOARD); if ($boardlog) { $yyuserlog{$newboard} = $date; } # For: Mark boards as read } if (@utdcurthread) { MessageTotals( 'update', $curthreadid ); } MessageTotals( 'update', $newthreadid ); # update current board totals # BoardTotals- tags => (board threadcount messagecount lastposttime lastposter lastpostid lastreply lastsubject lasticon lasttopicstate) #&BoardTotals("load", $curboard); - Load this at top now to detect if newest board post is being moved - Unilat if ( ${ $BoardTotals{$curthreadid} }[6] =~ /m/sm ) { # Moved-Info thread if ( $curboard ne $newboard ) { ${ $uid . $curboard }{'threadcount'}--; ${ $uid . $curboard }{'messagecount'} -= @postnum; } BoardSetLastInfo( $curboard, \@curmessindex ); } else { if ( $FORM{'newthread'} eq 'new' && $curboard eq $newboard ) { ${ $uid . $curboard }{'threadcount'}++; } if ( $leavemess == 0 ) { if ( $curboard ne $newboard ) { ${ $uid . $curboard }{'messagecount'} -= $#postnum; } else { ${ $uid . $curboard }{'messagecount'} += ( $forcenewinfo ? 2 : 1 ); } } elsif ( $leavemess == 1 && $curboard eq $newboard ) { ${ $uid . $curboard }{'messagecount'} += $#postnum + ( $forcenewinfo ? 1 : 0 ); } elsif ( $leavemess == 2 && $curboard ne $newboard && @utdcurthread ) { ${ $uid . $curboard }{'messagecount'} -= @postnum; } if ( $newest_post || ( ( ( ${ $uid . $curboard }{'threadcount'} == 1 && @utdcurthread ) || ${ $BoardTotals{$curthreadid} }[0] >= ${ $uid . $curboard }{'lastposttime'} ) && ( $curboard ne $newboard || ${ $BoardTotals{$curthreadid} }[0] >= ${ $BoardTotals{$newthreadid} }[0] ) ) ) { ${ $uid . $curboard }{'lastposttime'} = ${ $BoardTotals{$curthreadid} }[0]; ${ $uid . $curboard }{'lastposter'} = ${ $BoardTotals{$curthreadid} }[1] eq 'Guest' ? "Guest-${$BoardTotals{$curthreadid}}[4]" : ${ $BoardTotals{$curthreadid} }[1]; ${ $uid . $curboard }{'lastpostid'} = $curthreadid; ${ $uid . $curboard }{'lastreply'} = ${ $BoardTotals{$curthreadid} }[2]--; ${ $uid . $curboard }{'lastsubject'} = ${ $BoardTotals{$curthreadid} }[3]; ${ $uid . $curboard }{'lasticon'} = ${ $BoardTotals{$curthreadid} }[5]; ${ $uid . $curboard }{'lasttopicstate'} = ${ $BoardTotals{$curthreadid} }[6]; } elsif ( ${ $BoardTotals{$newthreadid} }[0] >= ${ $uid . $curboard }{'lastposttime'} && $curboard eq $newboard ) { ${ $uid . $curboard }{'lastposttime'} = ${ $BoardTotals{$newthreadid} }[0]; ${ $uid . $curboard }{'lastposter'} = ${ $BoardTotals{$newthreadid} }[1] eq 'Guest' ? "Guest-${$BoardTotals{$newthreadid}}[4]" : ${ $BoardTotals{$newthreadid} }[1]; ${ $uid . $curboard }{'lastpostid'} = $newthreadid; ${ $uid . $curboard }{'lastreply'} = ${ $BoardTotals{$newthreadid} }[2]--; ${ $uid . $curboard }{'lastsubject'} = ${ $BoardTotals{$newthreadid} }[3]; ${ $uid . $curboard }{'lasticon'} = ${ $BoardTotals{$newthreadid} }[5]; ${ $uid . $curboard }{'lasttopicstate'} = ${ $BoardTotals{$newthreadid} }[6]; } BoardSetLastInfo( $curboard, \@curmessindex ); } # update new board totals if needed if ( $curboard ne $newboard ) { BoardTotals( 'load', $newboard ); if ( $FORM{'newthread'} eq 'new' ) { ${ $uid . $newboard }{'threadcount'}++; } ${ $uid . $newboard }{'messagecount'} += @postnum + ( $forcenewinfo ? 1 : 0 ); if ( ${ $uid . $newboard }{'threadcount'} == 1 || ${ $BoardTotals{$newthreadid} }[0] >= ${ $uid . $newboard }{'lastposttime'} ) { ${ $uid . $newboard }{'lastposttime'} = ${ $BoardTotals{$newthreadid} }[0]; ${ $uid . $newboard }{'lastposter'} = ${ $BoardTotals{$newthreadid} }[1] eq 'Guest' ? "Guest-${$BoardTotals{$newthreadid}}[4]" : ${ $BoardTotals{$newthreadid} }[1]; ${ $uid . $newboard }{'lastpostid'} = $newthreadid; ${ $uid . $newboard }{'lastreply'} = ${ $BoardTotals{$newthreadid} }[2]--; ${ $uid . $newboard }{'lastsubject'} = ${ $BoardTotals{$newthreadid} }[3]; ${ $uid . $newboard }{'lasticon'} = ${ $BoardTotals{$newthreadid} }[5]; ${ $uid . $newboard }{'lasttopicstate'} = ${ $BoardTotals{$newthreadid} }[6]; } BoardTotals( 'update', $newboard ); } # now fix all attachments.txt info my $attachments; for my $i ( $postnum[0] .. $#curthread ) { # see if old thread had attachments $attachments = ( split /\|/xsm, $curthread[$i] )[12]; chomp $attachments; if ($attachments) { $attachments = 1; last; } } if ( !$attachments ) { # see if new thread has attachments for my $i ( $linkcount .. $#utdnewthread ) { $attachments = ( split /\|/xsm, $utdnewthread[$i] )[12]; chomp $attachments; if ($attachments) { $attachments = 2; last; } } } if ($attachments) { my ( @newattachments, %attachments ); fopen( ATM, "<$vardir/attachments.txt", 1 ) or fatal_error( 'cannot_open', "$vardir/attachments.txt", 1 ); my @attach = ; fclose(ATM); for (@attach) { my ( $attid, undef, undef, undef, undef, undef, undef, $attachmentname, $downloadscount ) = split /\|/xsm, $_; if ( ( $attid != $curthreadid && $attid != $newthreadid ) || ( $attid == $curthreadid && $attachments != 1 ) ) { push @newattachments, $_; } chomp $downloadscount; $attachments{$attachmentname} = $downloadscount; } my $mreplies = 0; if ( $attachments == 1 ) { foreach (@utdcurthread) { # fix new old thread attachments my ( $msub, $mname, undef, $mdate, undef, undef, undef, undef, undef, undef, undef, undef, $mfn ) = split /\|/xsm, $_; chomp $mfn; foreach ( split /,/xsm, $mfn ) { if ( -e "$uploaddir/$_" ) { my $asize = int( ( -s "$uploaddir/$_" ) / 1024 ) || 1; push @newattachments, qq~$curthreadid|$mreplies|$msub|$mname|$curboard|$asize|$mdate|$_|~ . ( $attachments{$_} || 0 ) . qq~\n~; } } $mreplies++; } } $mreplies = 0; foreach (@utdnewthread) { # fix new thread attachments my ( $msub, $mname, undef, $mdate, undef, undef, undef, undef, undef, undef, undef, undef, $mfn ) = split /\|/xsm, $_; chomp $mfn; foreach ( split /,/xsm, $mfn ) { if ( -e "$uploaddir/$_" ) { my $asize = int( ( -s "$uploaddir/$_" ) / 1024 ) || 1; push @newattachments, qq~$newthreadid|$mreplies|$msub|$mname|$newboard|$asize|$mdate|$_|~ . ( $attachments{$_} || 0 ) . qq~\n~; } } $mreplies++; } fopen( FATM, ">$vardir/attachments.txt" ) or fatal_error( 'cannot_open', "$vardir/attachments.txt" ); print {FATM} sort { ( split /\|/xsm, $a, 8 )[6] <=> ( split /\|/xsm, $b, 8 )[6] } @newattachments or croak "$croak{'print'} ATM"; fclose(FATM); } if ( $#postnum == $#curthread ) { if ( -e "$datadir/$curthreadid.poll" ) { rename "$datadir/$curthreadid.poll", "$datadir/$newthreadid.poll"; } if ( -e "$datadir/$curthreadid.polled" ) { rename "$datadir/$curthreadid.polled", "$datadir/$newthreadid.polled"; } if ( -e "$datadir/$curthreadid.mail" ) { rename "$datadir/$curthreadid.mail", "$datadir/$newthreadid.mail"; require Sources::Notify; ManageThreadNotify( 'load', $newthreadid ); my (%t); foreach my $u ( keys %thethread ) { LoadUser($u); foreach ( split /,/xsm, ${ $uid . $u }{'thread_notifications'} ) { $t{$_} = 1; } delete $t{$curthreadid}; $t{$newthreadid} = 1; ${ $uid . $u }{'thread_notifications'} = join q{,}, keys %t; UserAccount($u); undef %t; } } } # Mark current thread as read delete $yyuserlog{"$curthreadid--unread"}; dumplog($curthreadid); # Save threads/boards as read chomp $yyThreadLine; if ( $INFO{'moveit'} == 1 ) { $currentboard = $curboard; return; } if ( $INFO{'ss_submit'} ) { $currentboard = $newboard; $INFO{'num'} = $INFO{'thread'} = $FORM{'threadid'} = $curnum = $newthreadid; redirectinternal(); } if ( $debug == 1 or ( $debug == 2 && $iamadmin ) ) { require Sources::Debug; Debug(); $yydebug = qq~\n- $#utdnewthread
\n- @utdnewthread
\n- ${$newthreadid}{'lastpostdate'}
\n- ${$newthreadid}{'lastposter'}
\n- \$enable_notifications == $enable_notifications
\n- \$attachments = $attachments
\ncontinue\n$yydebug~; } print_output_header(); $output = qq~ $sstxt{'1'}  $yydebug ~; print_HTML_output_and_finish(); return; } 1;