Diff for /loncom/interface/lonfeedback.pm between versions 1.273.4.5 and 1.383

version 1.273.4.5, 2010/01/25 03:30:23 version 1.383, 2019/08/12 16:45:48
Line 41  use Apache::lonnavmaps; Line 41  use Apache::lonnavmaps;
 use Apache::lonenc();  use Apache::lonenc();
 use Apache::lonrss();  use Apache::lonrss();
 use HTML::LCParser();  use HTML::LCParser();
   #use HTML::Tidy::libXML;
 use Apache::lonspeller();  use Apache::lonspeller();
 use Apache::longroup;  use Apache::longroup;
 use Cwd;  use Archive::Zip qw( :ERROR_CODES );
 use LONCAPA;  use LONCAPA qw(:DEFAULT :match);
   
 sub discussion_open {  sub discussion_open {
     my ($status,$symb)=@_;      my ($status,$symb)=@_;
   # Advanced roles can always discuss
     if ($env{'request.role.adv'}) { return 1; }      if ($env{'request.role.adv'}) { return 1; }
   # Get discussion closing date
       my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);
   # If it is defined and in the future, the instructor wants this discussion to be open
       if (defined($close) && $close ne '' && $close > time) {
           return 1;
       }
   # It was not explicitly open, check if the problem is available.
   # If the problem is not available, close the discussion 
     if (defined($status) &&      if (defined($status) &&
  !($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'   !($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'
   || $status eq 'OPEN')) {    || $status eq 'OPEN')) {
  return 0;   return 0;
     }      }
     my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);  # The problem is available, but check if the instructor explictly closed discussion
     if (defined($close) && $close ne '' && $close < time) {      if (defined($close) && $close ne '' && $close < time) {
  return 0;   return 0;
     }      }
Line 72  sub discussion_visible { Line 82  sub discussion_visible {
     return 1;      return 1;
 }  }
   
   sub discussion_vote_available {
       my ($status,$symb)=@_;
       my $canvote=&Apache::lonnet::EXT('resource.0.discussvote',$symb);
       if ((lc($canvote) eq 'yes') || 
           ((lc($canvote) eq 'notended') && (&discussion_open($status,$symb)))) {
           return 1;
       }
   }
   
   sub get_realsymb {
       my ($symb) = @_;
       my $realsymb = $symb;
       if ($symb=~/^bulletin___/) {
           my $filename=(&Apache::lonnet::decode_symb($symb))[2];
           $filename=~s{^adm/wrapper/}{};
           $realsymb=&Apache::lonnet::symbread($filename);
       }
       return $realsymb;
   }
   
 sub list_discussion {  sub list_discussion {
     my ($mode,$status,$ressymb,$imsextras,$group)=@_;      my ($mode,$status,$ressymb,$imsextras,$group)=@_;
     unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }      unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }
Line 91  sub list_discussion { Line 121  sub list_discussion {
     if (not &discussion_visible($status)) {      if (not &discussion_visible($status)) {
         if ($mode ne 'board') {          if ($mode ne 'board') {
             &Apache::lonenc::check_encrypt(\$ressymb);               &Apache::lonenc::check_encrypt(\$ressymb); 
             return '<br />'.&send_message_link($ressymb);              return '<br /><div class="LC_feedback_link">'.&send_message_link($ressymb)."</div>";
         }          }
     }      }
     if ($group ne '' && $mode eq 'board') {      if ($group ne '' && $mode eq 'board') {
Line 103  sub list_discussion { Line 133  sub list_discussion {
     my ($blocked,$blocktext) =       my ($blocked,$blocktext) = 
         &Apache::loncommon::blocking_status('boards');          &Apache::loncommon::blocking_status('boards');
     if ($blocked) {      if ($blocked) {
           $blocktext = '<br /><div class="LC_feedback_link"><span class="LC_feedback_link">'.$blocktext."</span>";
         &Apache::lonenc::check_encrypt(\$ressymb);          &Apache::lonenc::check_encrypt(\$ressymb);
         if ($mode ne 'board') {          if ($mode ne 'board') {
             $blocktext.='<br />'.&send_message_link($ressymb);              $blocktext.=&send_message_link($ressymb).'</div>';
           }else{
               $blocktext.="</div>";
         }          }
         return $blocktext;           return $blocktext; 
     }      }
Line 122  sub list_discussion { Line 155  sub list_discussion {
     $crs=~s/\_/\//g;      $crs=~s/\_/\//g;
     my $encsymb=&Apache::lonenc::check_encrypt($ressymb);      my $encsymb=&Apache::lonenc::check_encrypt($ressymb);
     my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)      my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
   && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form|task)$/));    && ($ressymb=~/$LONCAPA::assess_re/));
           
     my %usernamesort = ();      my %usernamesort = ();
     my %namesort =();      my %namesort =();
Line 171  sub list_discussion { Line 204  sub list_discussion {
     my $cnum = $env{'course.'.$cid.'.num'};      my $cnum = $env{'course.'.$cid.'.num'};
     my $crstype = &Apache::loncommon::course_type();      my $crstype = &Apache::loncommon::course_type();
   
   
 # Get information about students and non-students in course for filtering display of posts  # Get information about students and non-students in course for filtering display of posts
     my %roleshash = ();      my %roleshash = ();
     my %roleinfo = ();      my %roleinfo = ();
Line 245  sub list_discussion { Line 277  sub list_discussion {
     $visit ++;      $visit ++;
   
     my $seeid;      my $seeid;
     if (($group ne '') && ($mode eq 'board') &&       if (&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
         ($ressymb =~ m|^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|)) {          $seeid = 1;
         if (&check_group_priv($group,'dgp') eq 'ok') {  
             $seeid = 1;  
         }  
     } else {  
         $seeid=&Apache::lonnet::allowed('rin',$crs);  
     }      }
       my $seehidden = &can_see_hidden($mode,$ressymb,undef,$group,$cdom,$cnum,$crs);
   
   # Is voting on discussions available
       my $realsymb = &get_realsymb($ressymb);
       my $canvote = &discussion_vote_available($status,$realsymb);
   
     my @discussionitems=();      my @discussionitems=();
     my %shown = ();      my %shown = ();
     my @posteridentity=();      my @posteridentity=();
Line 269  sub list_discussion { Line 302  sub list_discussion {
     my $maxdepth=0;      my $maxdepth=0;
     my %anonhash=();      my %anonhash=();
     my $anoncnt=0;      my $anoncnt=0;
     my $target='';  
     unless ($env{'browser.interface'} eq 'textual' ||  
     $env{'environment.remote'} eq 'off' ) {  
  $target='target="LONcom"';  
     }  
   
     my $now = time;      my $now = time;
     $discinfo{$visitkey} = $visit;      $discinfo{$visitkey} = $visit;
   
     &Apache::lonnet::put('nohist_'.$cid.'_discuss',\%discinfo,$env{'user.domain'},$env{'user.name'});      &Apache::lonnet::put('nohist_'.$cid.'_discuss',\%discinfo,$env{'user.domain'},$env{'user.name'});
     &build_posting_display(\%usernamesort,\%subjectsort,\%namesort,\%notshown,\%newitem,\%dischash,\%shown,\%alldiscussion,\%imsitems,\%imsfiles,\%roleinfo,\@discussionitems,\@replies,\@depth,\@posters,\$maxdepth,\$visible,\$newpostsflag,\$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$encsymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,\@grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,\%anonhash,$anoncnt,$group);      &build_posting_display(\%usernamesort,\%subjectsort,\%namesort,\%notshown,\%newitem,\%dischash,\%shown,\%alldiscussion,\%imsitems,\%imsfiles,\%roleinfo,\@discussionitems,\@replies,\@depth,\@posters,\$maxdepth,\$visible,\$newpostsflag,\$current,$status,$viewgrades,$seeid,$seehidden,$canvote,$prevread,$sortposts,$encsymb,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,\@grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,\%anonhash,$anoncnt,$group);
   
     my $discussion='';      my $discussion='';
     my $manifestfile;      my $manifestfile;
Line 289  sub list_discussion { Line 317  sub list_discussion {
     my $copyresult;      my $copyresult;
   
     my $function = &Apache::loncommon::get_users_function();      my $function = &Apache::loncommon::get_users_function();
     my $color = &Apache::loncommon::designparm($function.'.tabbg',  
                                                     $env{'user.domain'});  
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'cuse' => 'Current discussion settings',          'cuse' => 'My settings for this discussion',
         'allposts' => 'All posts',          'allposts' => 'All posts',
         'unread' => 'New posts only',          'unread' => 'New posts only',
         'unmark' => 'Unread only',          'unmark' => 'Unread only',
Line 310  sub list_discussion { Line 336  sub list_discussion {
         'aner' => 'An error occurred opening the manifest file.',          'aner' => 'An error occurred opening the manifest file.',
         'difo' => 'Discussion for',          'difo' => 'Discussion for',
         'aerr' => 'An error occurred opening the export file for posting',          'aerr' => 'An error occurred opening the export file for posting',
           'discussions' => 'DISCUSSIONS'
       );
       my %js_lt = &Apache::lonlocal::texthash(
         'aysu' => 'Are you sure you want to delete this post?',          'aysu' => 'Are you sure you want to delete this post?',
         'dpwn' => 'Deleted posts will no longer be visible to you and other students',          'dpwn' => 'Deleted posts will no longer be visible to you and other students',
         'bwco' => 'but will continue to be visible to your instructor',          'bwco' => 'but will continue to be visible to your instructor',
         'depo' => 'Deleted posts will no longer be visible to you or anyone else.',          'depo' => 'Deleted posts will no longer be visible to you or anyone else.',
     );      );
       &js_escape(\%js_lt);
   
     my $currdisp = $lt{'allposts'};      my $currdisp = $lt{'allposts'};
     my $currmark = $lt{'onmark'};      my $currmark = $lt{'onmark'};
Line 354  sub list_discussion { Line 384  sub list_discussion {
         $togglink = 'toggoff';          $togglink = 'toggoff';
     }       } 
         
     $chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;      $chglink .= '&amp;changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;
   
     if ($newpostsflag) {      if ($newpostsflag) {
         $chglink .= '&previous='.$prevread;          $chglink .= '&amp;previous='.$prevread;
     }      }
     $chglink.=&group_args($group);      $chglink.=&group_args($group);
   
Line 365  sub list_discussion { Line 395  sub list_discussion {
 # Print the discusssion  # Print the discusssion
         if ($outputtarget eq 'tex') {          if ($outputtarget eq 'tex') {
             $discussion.='<tex>{\tiny \vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.              $discussion.='<tex>{\tiny \vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.
                          '\textbf{DISCUSSIONS}\makebox[2 cm][b]{\hrulefill}'.                           '\textbf{'.$lt{'discussions'}.'}\makebox[2 cm][b]{\hrulefill}\vskip 0 mm'.
                          '\vskip 0 mm\noindent\textbf{'.$lt{'cuse'}.'}:\vskip 0 mm'.  
                          '\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.                           '\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.
                          '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}}</tex>';                           '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}}</tex>';
         } elsif ($outputtarget eq 'export') {          } elsif ($outputtarget eq 'export') {
Line 400  sub list_discussion { Line 429  sub list_discussion {
             my $manifestfilename = $tempexport.$manifest;              my $manifestfilename = $tempexport.$manifest;
             if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {              if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {
                 $manifestok=1;                  $manifestok=1;
                 print $manifestfile qq|                  print $manifestfile qq|<?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>  
 <manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2  <manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
 identifier="MANIFEST-$ressymb" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1   identifier="MANIFEST-$ressymb" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 
Line 414  imscp_v1p1.xsd http://www.imsglobal.org/ Line 442  imscp_v1p1.xsd http://www.imsglobal.org/
             }              }
  } else {   } else {
             my $colspan=$maxdepth+1;              my $colspan=$maxdepth+1;
             $discussion.= qq|              $discussion.= &Apache::lonhtmlcommon::scripttag(qq|
 <script>  
    function verifydelete (caller,symb,idx,newflag,previous,groupparm) {     function verifydelete (caller,symb,idx,newflag,previous,groupparm) {
        var symbparm = symb+':::'+idx         var symbparm = symb+':::'+idx
        var prevparm = ""         var prevparm = ""
        if (newflag == 1) {         if (newflag == 1) {
            prevparm = "&previous="+previous             prevparm = "&amp;previous="+previous
        }         }
        if (caller == 'studentdelete') {         if (caller == 'studentdelete') {
            if (confirm("$lt{'aysu'}\\n$lt{'dpwn'},\\n$lt{'bwco'}")) {             if (confirm("$js_lt{'aysu'}\\n$js_lt{'dpwn'},\\n$js_lt{'bwco'}")) {
                document.location.href = "/adm/feedback?hide="+symbparm+prevparm+groupparm                 document.location.href = "/adm/feedback?hide="+symbparm+prevparm+groupparm
            }             }
        } else {         } else {
            if (caller == 'seeiddelete') {             if (caller == 'seeiddelete') {
                if (confirm("$lt{'aysu'}\\n$lt{'depo'}")) {                 if (confirm("$js_lt{'aysu'}\\n$js_lt{'depo'}")) {
                    document.location.href = "/adm/feedback?deldisc="+symbparm+prevparm+groupparm                     document.location.href = "/adm/feedback?deldisc="+symbparm+prevparm+groupparm
                }                 }
            }             }
        }         }
    }     }
 </script>              |);
             |;  
     $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$ressymb.'" >'.      $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$ressymb.'" >'.
                          "\n".'<table class="LC_discussion">';                           "\n".'<table width="100%" class="LC_discussion">';
             $discussion .= &action_links_bar($colspan,$ressymb,$visible,              $discussion .= &action_links_bar($colspan,$ressymb,$visible,
                                              $newpostsflag,$group,                                               $newpostsflag,$group,
                                              $prevread,$markondisp);                                               $prevread,$markondisp,$seehidden);
             my $escsymb=&escape($ressymb);              my $escsymb=&escape($ressymb);
             my $numhidden = keys(%notshown);              my $numhidden = keys(%notshown);
             if ($numhidden > 0) {              if ($numhidden > 0) {
                 my $colspan = $maxdepth+1;                  my $colspan = $maxdepth+1;
                 $discussion.="\n".'<tr><td bgcolor="#CCCCCC" colspan="'.$colspan.'">'.                  $discussion.="\n".'<tr><td bgcolor="#CCCCCC" colspan="'.$colspan.'">';
                          '<a href="/adm/feedback?allposts=1&amp;symb='.$escsymb;                  my $href = '/adm/feedback?allposts=1&amp;symb='.$escsymb;
                 if ($newpostsflag) {                  if ($newpostsflag) {
                     $discussion .= '&previous='.$prevread;                      $href .= '&amp;previous='.$prevread;
                 }                  }
  $discussion .= &group_args($group);   $href .= &group_args($group);
                 $discussion .= '">'.&mt('Show all posts').'</a> '.&mt('to display').' '.  
                          $numhidden.' ';  
                 if ($showunmark) {                  if ($showunmark) {
                     $discussion .= &mt('posts previously marked read');                      $discussion .= &mt('[_1]Show all posts[_2] to display [quant,_3,post] previously marked read',
                                          '<a href="'.$href.'">','</a>',$numhidden);
                 } else {                  } else {
                     $discussion .= &mt('previously viewed posts');                      $discussion .= &mt('[_1]Show all posts[_2] to display [quant,_3,post] previously viewed',
                                          '<a href="'.$href.'">','</a>',$numhidden);
                 }                  }
                 $discussion .= '<br/></td></tr>';                  $discussion .= '<br/></td></tr>';
             }              }
Line 490  imscp_v1p1.xsd http://www.imsglobal.org/ Line 516  imscp_v1p1.xsd http://www.imsglobal.org/
         my $currdepth = 0;          my $currdepth = 0;
         my $firstidx = $alldiscussion{$showposts[0]};          my $firstidx = $alldiscussion{$showposts[0]};
         foreach my $post (@showposts) {          foreach my $post (@showposts) {
             unless (($sortposts eq 'thread') || (($sortposts eq '') && ($env{'environment.threadeddiscussion'})) || ($outputtarget eq 'export')) {              unless (($sortposts eq 'thread') || 
                       (($sortposts eq '') && (!$env{'environment.unthreadeddiscussion'})) || 
                       ($outputtarget eq 'export')) {
                 $alldiscussion{$post} = $post;                  $alldiscussion{$post} = $post;
             }              }
             unless ( ($notshown{$alldiscussion{$post}} eq '1') || ($shown{$alldiscussion{$post}} == 0) ) {              unless ( ($notshown{$alldiscussion{$post}} eq '1') || ($shown{$alldiscussion{$post}} == 0) ) {
Line 500  imscp_v1p1.xsd http://www.imsglobal.org/ Line 528  imscp_v1p1.xsd http://www.imsglobal.org/
         my $thisdepth=$depth[$alldiscussion{$post}];          my $thisdepth=$depth[$alldiscussion{$post}];
                 if ($outputtarget ne 'tex' && $outputtarget ne 'export') {                  if ($outputtarget ne 'tex' && $outputtarget ne 'export') {
     for (1..$thisdepth) {      for (1..$thisdepth) {
  $discussion.='<td>&nbsp;&nbsp;&nbsp;</td>';   $discussion.='<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>';
     }      }
  }   }
         my $colspan=$maxdepth-$thisdepth+1;          my $colspan=$maxdepth-$thisdepth+1;
Line 513  imscp_v1p1.xsd http://www.imsglobal.org/ Line 541  imscp_v1p1.xsd http://www.imsglobal.org/
  $threadinsert='<br /><strong>Reply: '.$thisdepth.'</strong>';   $threadinsert='<br /><strong>Reply: '.$thisdepth.'</strong>';
     }      }
     $discussionitems[$alldiscussion{$post}]=~s/<\/td><td([^>]*)>/$threadinsert<\/td><td TeXwidth="65 mm" align="left">/;      $discussionitems[$alldiscussion{$post}]=~s/<\/td><td([^>]*)>/$threadinsert<\/td><td TeXwidth="65 mm" align="left">/;
     $discussionitems[$alldiscussion{$post}]=~s/<a([^>]+)>(Edit|Hide|Delete|Reply|Submissions)<\/a>//g;  
                     $discussionitems[$alldiscussion{$post}]=~s/(<b>|<\/b>|<\/a>|<a([^>]+)>)//g;                      $discussionitems[$alldiscussion{$post}]=~s/(<b>|<\/b>|<\/a>|<a([^>]+)>)//g;
   
     $discussionitems[$alldiscussion{$post}]='<tex>\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}</tex>'.$discussionitems[$alldiscussion{$post}];      $discussionitems[$alldiscussion{$post}]='<tex>\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}</tex>'.$discussionitems[$alldiscussion{$post}];
Line 528  imscp_v1p1.xsd http://www.imsglobal.org/ Line 555  imscp_v1p1.xsd http://www.imsglobal.org/
                         print $manifestfile "\n".                           print $manifestfile "\n". 
       '<item identifier="ITEM-'.$ressymb.'-'.$alldiscussion{$post}.'" isvisible="'.        '<item identifier="ITEM-'.$ressymb.'-'.$alldiscussion{$post}.'" isvisible="'.
         $imsitems{$alldiscussion{$post}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$post}.'">'.          $imsitems{$alldiscussion{$post}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$post}.'">'.
         '<title>'.$imsitems{$alldiscussion{$post}}{'title'}.'</title>';          '<title>'.$imsitems{$alldiscussion{$post}}{'title'}.'</title></item>';
                         $imsresources .= "\n".                          $imsresources .= "\n".
     '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$post}.'" type="webcontent" href="'.$postfilename.'">'."\n".      '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$post}.'" type="webcontent" href="'.$postfilename.'">'."\n".
       '<file href="'.$postfilename.'">'."\n".        '<file href="'.$postfilename.'">'."\n".
       $imsfiles{$alldiscussion{$post}}{$imsitems{$alldiscussion{$post}}{'currversion'}}."\n".        $imsfiles{$alldiscussion{$post}}{$imsitems{$alldiscussion{$post}}{'currversion'}}.'</file>'."\n".
     '</resource>';      '</resource>';
                     }                      }
                     my $postingfile;                      my $postingfile;
                     my $postingfilename = $tempexport.'/'.$postfilename;                      my $postingfilename = $tempexport.'/'.$postfilename;
                     if ($postingfile = Apache::File->new('>'.$postingfilename)) {                      if ($postingfile = Apache::File->new('>'.$postingfilename)) {
                         print $postingfile '<html><head><title>Discussion Post</title></head><body>'.                          print $postingfile '<html><head><title>'.&mt('Discussion Post').'</title></head><body>'.
                                            $imsitems{$alldiscussion{$post}}{'title'}.' '.                                             $imsitems{$alldiscussion{$post}}{'title'}.' '.
                                            $imsitems{$alldiscussion{$post}}{'sender'}.                                             $imsitems{$alldiscussion{$post}}{'sender'}.
                                            $imsitems{$alldiscussion{$post}}{'timestamp'}.'<br /><br />'.                                             $imsitems{$alldiscussion{$post}}{'timestamp'}.'<br /><br />'.
Line 559  imscp_v1p1.xsd http://www.imsglobal.org/ Line 586  imscp_v1p1.xsd http://www.imsglobal.org/
  unless ($outputtarget eq 'tex' || $outputtarget eq 'export') {   unless ($outputtarget eq 'tex' || $outputtarget eq 'export') {
             my $colspan=$maxdepth+1;              my $colspan=$maxdepth+1;
             $discussion .= <<END;              $discussion .= <<END;
             <tr bgcolor="#FFFFFF">              <tr>
              <td colspan="$colspan" class="LC_disc_action_links_bar">               <td colspan="$colspan">
               <table class="LC_disc_action_table">                <table width="100%">
                <tr>                 <tr>
                 <td align="left">                  <td class="LC_disc_action_left">
                  <table border="0" cellpadding="0" cellspacing="4">                      <font size="-1"><b>$lt{'cuse'}</b>:&nbsp;
                   <tr>  
                    <td>  
                     <font size="-1"><b>$lt{'cuse'}</b>:</font></td>  
                    <td>&nbsp;</td>  
                    <td><font size="-1">  
 END  END
             if ($newpostsflag) {              if ($newpostsflag) {
                 $discussion .=                   $discussion .= 
Line 586  END Line 608  END
                 }                  }
             }              }
             $discussion .= <<END;              $discussion .= <<END;
                    </font></td>                     &nbsp;&nbsp;<b><a href="$chglink">$lt{'chgt'}</a></b></font>
                    <td>&nbsp;</td>  
                    <td align="left">  
                     <font size="-1"><b><a href="$chglink">$lt{'chgt'}</a>?</b></font>  
                    </td>  
                   </tr>  
                  </table>  
                 </td>                  </td>
 END  END
             if ($sortposts) {              if ($sortposts) {
Line 601  END Line 617  END
                 my %status_types = ();                  my %status_types = ();
                 &sort_filter_names(\%sort_types,\%role_types,\%status_types,$crstype);                  &sort_filter_names(\%sort_types,\%role_types,\%status_types,$crstype);
   
                 $discussion .= '<td><font size="-1"><b>'.&mt('Sorted by').'</b>: '.$sort_types{$sortposts}.'<br />';                  $discussion .= '<td class="LC_disc_action_right"><font size="-1"><b>'.&mt('Sorted by').'</b>: '.$sort_types{$sortposts}.'<br />';
                 if (defined($env{'form.totposters'})) {                  if (defined($env{'form.totposters'})) {
                     $discussion .= &mt('Posts by').':';                      $discussion .= &mt('Posts by').':';
                     if ($totposters > 0) {                      if ($totposters > 0) {
Line 636  END Line 652  END
                     if ($filterchoice) {                      if ($filterchoice) {
                         $discussion .= '<b>'.&mt('Filters').'</b>:&nbsp;'.$filterchoice;                          $discussion .= '<b>'.&mt('Filters').'</b>:&nbsp;'.$filterchoice;
                     }                      }
                     $discussion .= '</font></td>';  
                 }                  }
                   $discussion .= '</font></td>';
   
             }              }
             if ($dischash{$toggkey}) {              if ($dischash{$toggkey}) {
                 my $storebutton = &mt('Save read/unread changes');                  my $storebutton = &mt('Save read/unread changes');
                 $discussion.='<td align="right">'.                  $discussion.='<td align="right">'.
               '<input type="hidden" name="discsymb" value="'.$ressymb.'" />'."\n".                '<input type="hidden" name="discsymb" value="'.$ressymb.'" />'."\n".
               '<input type="button" name="readoptions" value="'.$storebutton.'"'.                '<input type="button" name="readoptions" value="'.$storebutton.'"'.
               ' onClick="this.form.submit();" />'."\n".                ' onclick="this.form.submit();" />'."\n".
               '</td>';                '</td>';
             }              }
             $discussion .= (<<END);              $discussion .= (<<END);
Line 655  END Line 672  END
 END  END
             $discussion .= &action_links_bar($colspan,$ressymb,$visible,              $discussion .= &action_links_bar($colspan,$ressymb,$visible,
                                              $newpostsflag,$group,                                               $newpostsflag,$group,
                                              $prevread,$markondisp);                                               $prevread,$markondisp,$seehidden);
             $discussion .= "              $discussion .= "</table></form>\n";
            </table>          }
            <br /><br /></form>\n";  
         }   
         if ($outputtarget eq 'export') {          if ($outputtarget eq 'export') {
             if ($manifestok) {              if ($manifestok) {
                 while ($currdepth > 0) {                  while ($currdepth > 0) {
Line 681  END Line 696  END
   
 #Create zip file in prtspool  #Create zip file in prtspool
   
                     my $imszipfile = '/prtspool/'.                      if (($env{'user.name'} =~ /^$match_username$/)
                     $env{'user.name'}.'_'.$env{'user.domain'}.'_'.                          && ($env{'user.domain'} =~ /^$match_domain$/)) {
                          time.'_'.rand(1000000000).'.zip';                          my $now = time();
                     my $cwd = &getcwd();                           my $imszipfile = '/prtspool/'.
                     my $imszip = '/home/httpd/'.$imszipfile;                                        join('_',$env{'user.name'},$env{'user.domain'},$now).
                     chdir $tempexport;                                        '_'.rand(1000000000).'.zip';
                     open(OUTPUT, "zip -r $imszip *  2> /dev/null |");                          my $zip = Archive::Zip->new();
                     close(OUTPUT);                          $zip->addTree($tempexport);
                     chdir $cwd;                          my $imszip = '/home/httpd/'.$imszipfile;
                     $discussion .= &mt('Download the zip file from [_1]Discussion Posting Archive','<a href="'.$imszipfile.'">').'</a><br />';                          if ($zip->writeToFileNamed($imszip) == AZ_OK) {
                     if ($copyresult) {                              $discussion .= &mt('Download the zip file from [_1]Discussion Posting Archive[_2]',
                         $discussion .= &mt('The following errors occurred during export').' - <br />'.$copyresult;                                             '<a href="'.$imszipfile.'">','</a>').'<br />';
                           } else {
                               $discussion .=  &mt('Failed to create zip file').'<br />';
                           }
                           if ($copyresult) {
                               $discussion .= '<span class="LC_error">'.
                                              &mt('The following errors occurred during export:').
                                              '</span><br />'.$copyresult;
                           }
                       } else {
                           $discussion .= '<p class="LC_error">'.
                                          &mt('Unfortunately you will not be able to retrieve an archive of the discussion posts at this time, because there was a problem creating the zip file.').'</p>';
                     }                      }
                 }                  }
             } else {              } else {
                 $discussion .= '<br />'.&mt('Unfortunately you will not be able to retrieve an archive of the discussion posts at this time, because there was a problem creating a manifest file.').'<br />';                  $discussion .= '<p class="LC_error">'.
                                  &mt('Unfortunately you will not be able to retrieve an archive of the discussion posts at this time, because there was a problem creating a manifest file.').'</p>';
             }              }
             return $discussion;              return $discussion;
         }          }
Line 718  END Line 745  END
                 $attachnum += @{$currnewattach};                  $attachnum += @{$currnewattach};
             }              }
         }          }
  if (&discussion_open($status)) {   if ((&discussion_open($status)) && ($outputtarget ne 'tex')) {
             if (($group ne '') && ($mode eq 'board')) {                if (($group ne '') && ($mode eq 'board')) {  
                 if (&check_group_priv($group,'pgd') eq 'ok') {                  if ((&check_group_priv($group,'pgd') eq 'ok') && 
                      ($ressymb =~ m{^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$})) {
                     $discussion .=                      $discussion .=
  &postingform_display($mode,$ressymb,$now,$subject,   &postingform_display($mode,$ressymb,$now,$subject,
      $comment,$outputtarget,$attachnum,       $comment,$outputtarget,$attachnum,
Line 728  END Line 756  END
      $group,$crstype);       $group,$crstype);
                 }                  }
             } else {              } else {
         $discussion.=                   if (&Apache::lonnet::allowed('pch',$env{'request.course.id'}.
     &postingform_display($mode,$ressymb,$now,$subject,                      ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
  $comment,$outputtarget,$attachnum,  
  $currnewattach,$currdelold,'',$crstype);              $discussion.= 
           &postingform_display($mode,$ressymb,$now,$subject,
        $comment,$outputtarget,$attachnum,
        $currnewattach,$currdelold,'',$crstype);
                   } else {
                       $discussion.= '<span class="LC_feedback_link">'.
                                     &mt('This discussion is closed.').'</span>';
                   }
             }              }
  }   }
     } else {          if (!(&discussion_open($status)) && ($outputtarget ne 'tex')) {
               $discussion.= '<span class="LC_feedback_link">'.
                             &mt('This discussion is closed.').'</span>';
           }
       } elsif ($outputtarget ne 'tex') {
         $discussion.='<div class="LC_feedback_link">';          $discussion.='<div class="LC_feedback_link">';
         if (&discussion_open($status) &&          if (&discussion_open($status) &&
             &Apache::lonnet::allowed('pch',              &Apache::lonnet::allowed('pch',
            $env{'request.course.id'}.             $env{'request.course.id'}.
         ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {          ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
     if ($outputtarget ne 'tex') {              $discussion.= &send_feedback_link($ressymb);
  $discussion.= &send_feedback_link($ressymb,$target);              if ($env{'request.role.adv'}) {
                   my $close = &Apache::lonnet::EXT('resource.0.discussend',$ressymb);
                   my $canvote = &Apache::lonnet::EXT('resource.0.discussvote',$ressymb);
                   if (defined($close) && $close ne '' && $close < time) {
                       if ($canvote eq 'notended') {
                           $discussion .= '&nbsp;'.&mt('(Posting and voting closed for [_1] roles)',
                                                       &Apache::lonnet::plaintext('st',$crstype));
                       } else {
                           $discussion .= '&nbsp;'.&mt('(Closed for [_1] roles)',
                                                       &Apache::lonnet::plaintext('st',$crstype));
                       }
                   }
             }              }
  }   } else {
         if ($outputtarget ne 'tex') {              $discussion.= '<span class="LC_feedback_link">'.&mt('This discussion is closed.').'</span>';
     $discussion.= &send_message_link($ressymb);  
         }          }
         $discussion.='</div>';   $discussion.= &send_message_link($ressymb).'</div>';
     }      }
     return $discussion;      return $discussion;
 }  }
   
   sub can_see_hidden {
       my ($mode,$ressymb,$feedurl,$group,$cdom,$cnum,$crs) = @_;
       my $seehidden;
       if ($env{'request.course.id'}) {
           unless ($cdom ne '' && $cnum ne '') {
               $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           }
           if ($crs eq '') {
               $crs = '/'.$env{'request.course.id'};
               if ($env{'request.course.sec'}) {
                   $crs.='_'.$env{'request.course.sec'};
               }
               $crs=~s{_}{/}g;
           }
           if ($mode eq '') {
               $mode='board';
               if ($feedurl =~ /$LONCAPA::assess_re/) {
                   $mode='problem';
               }
           }
           if (($group ne '') && ($mode eq 'board') &&
               ($ressymb =~ m{^bulletin___\d+\Q___adm/wrapper/adm/$cdom/$cnum/\E\d+/bulletinboard$})) {
               if (&check_group_priv($group,'dgp') eq 'ok') {
                   $seehidden = 1;
               }
           } else {
               $seehidden=&Apache::lonnet::allowed('rin',$crs);
           }
       }
       return $seehidden;
   }
   
   sub discussion_link {
      my ($ressymb,$linktext,$cmd,$item,$flag,$prev,$adds,$title)=@_;
      my $link='/adm/feedback?inhibitmenu=yes&amp;modal=yes&amp;'.$cmd.'='.&escape($ressymb).':::'.$item;
      if ($flag) { $link .= '&amp;previous='.$prev; }
      if ($adds) { $link .= $adds; }
      my $width=600;
      my $height=600;
      if (($cmd eq 'hide') || ($cmd eq 'unhide') || ($cmd eq 'like') || ($cmd eq 'unlike')) {
          $width=300;
          $height=200;
      }
      return &Apache::loncommon::modal_link($link,$linktext,$width,$height,undef,undef,$title);
   }
   
   
 sub send_feedback_link {  sub send_feedback_link {
     my ($ressymb,$target) = @_;      my ($ressymb) = @_;
     my $output = '<span class="LC_feedback_link">'.      return '<span class="LC_feedback_link">'.
                  ' <a href="/adm/feedback?replydisc='.                   &discussion_link($ressymb,
                  &escape($ressymb).':::" '.$target.'>'.                      '<img alt="" class="LC_noBorder" src="'.
                  '<img alt="" src="'.                      &Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').
                  &Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').                      '" /><span class="LC_menubuttons_inline_text">'.&mt('Post Discussion').'</span>',
                  '" border="0" />'.&mt('Post Discussion').'</a></span>';                      'replydisc').
     return $output;             '</span>';
 }  }
   
 sub send_message_link {  sub send_message_link {
     my ($ressymb) = @_;      my ($ressymb) = @_;
     my $output = '<span class="LC_message_link">'.      my $output = '<span class="LC_message_link">'.
                  '  <a href="/adm/feedback?sendmessageonly=1&amp;symb='.                   &discussion_link($ressymb,
                  &escape($ressymb).'"><img alt="" src="'.                      '<img alt="" class="LC_noBorder" src="'.
                  &Apache::loncommon::lonhttpdurl('/res/adm/pages/com.png').                      &Apache::loncommon::lonhttpdurl('/res/adm/pages/feedback.png').
                  '" border="0" />'.&mt('Send Feedback').'</a></span>';                      '" /><span class="LC_menubuttons_inline_text">'.&mt('Send Feedback').'</span>',
                       'sendmessageonly').
                    '</span>';
     return $output;      return $output;
 }  }
   
 sub action_links_bar {  sub action_links_bar {
     my ($colspan,$ressymb,$visible,$newpostsflag,$group,$prevread,$markondisp) = @_;      my ($colspan,$ressymb,$visible,$newpostsflag,$group,$prevread,$markondisp,
     my $discussion = '<tr><td class="LC_disc_action_links_bar" colspan="'.$colspan.'">'.          $seehidden) = @_;
                      '<table width="100%" class="LC_disc_action_table"><tr>'.      my $discussion = '<tr><td colspan="'.$colspan.'">'.
                        '<table width="100%"><tr>'.
                      '<td class="LC_disc_action_left">';                       '<td class="LC_disc_action_left">';
     my $escsymb=&escape($ressymb);      my $escsymb=&escape($ressymb);
     if ($visible>2) {      if ($visible) {
         $discussion .= '<a href="/adm/feedback?cmd=threadedon&amp;symb='.$escsymb;          $discussion .= '<a href="/adm/feedback?cmd=threadedon&amp;symb='.$escsymb;
         if ($newpostsflag) {          if ($newpostsflag) {
             $discussion .= '&previous='.$prevread;              $discussion .= '&amp;previous='.$prevread;
         }          }
         $discussion .= &group_args($group);          $discussion .= &group_args($group);
         $discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.          $discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.
                       '<a href="/adm/feedback?cmd=threadedoff&amp;symb='.$escsymb;                        '<a href="/adm/feedback?cmd=threadedoff&amp;symb='.$escsymb;
         if ($newpostsflag) {          if ($newpostsflag) {
             $discussion .= '&previous='.$prevread;              $discussion .= '&amp;previous='.$prevread;
         }          }
         $discussion .= &group_args($group);          $discussion .= &group_args($group);
         $discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;          $discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;';
                        <a href="/adm/feedback?cmd=sortfilter&amp;symb='.$escsymb;  
           my $otherviewurl='/adm/feedback?cmd=sortfilter&amp;symb='.$escsymb.'&amp;inhibitmenu=yes&amp;modal=yes';
         if ($newpostsflag) {          if ($newpostsflag) {
             $discussion .= '&previous='.$prevread;              $otherviewurl .= '&amp;previous='.$prevread;
         }          }
         $discussion .= &group_args($group);          $otherviewurl .= &group_args($group);
         $discussion .='">'.&mt('Sorting/Filtering options').'</a>'.('&nbsp;' x2);          $discussion .= &Apache::loncommon::modal_link($otherviewurl,&mt('Other Views ...'),800,340);
           $discussion .= '<br />';
     }      }
     $discussion .='<a href="/adm/feedback?export='.$escsymb;      $discussion .='<a href="/adm/feedback?export='.$escsymb;
     if ($newpostsflag) {      if ($newpostsflag) {
         $discussion .= '&previous='.$prevread;          $discussion .= '&amp;previous='.$prevread;
     }      }
     $discussion .= &group_args($group);      $discussion .= &group_args($group);
     $discussion .= '">'.&mt('Export').'?</a>&nbsp;&nbsp;</td>';      $discussion .= '">'.&mt('Export').'</a>';
       if ($seehidden) {
           $discussion .= '&nbsp;&nbsp;';
           $discussion .='<a href="/adm/feedback?undeleteall='.$escsymb;
           if ($newpostsflag) {
               $discussion .= '&amp;previous='.$prevread;
           }
           $discussion .= &group_args($group);
           $discussion .= '">'.&mt('Undelete all deleted entries').'</a>';
       }
       $discussion.='</td>';
     if ($newpostsflag) {      if ($newpostsflag) {
         if (!$markondisp) {          if (!$markondisp) {
             $discussion .='<td class="LC_disc_action_right"><a href="/adm/preferences?action=changediscussions';              $discussion .='<td class="LC_disc_action_right"><a href="/adm/preferences?action=changediscussions';
             $discussion .= &group_args($group);              $discussion .= &group_args($group);
             $discussion .= '">'.              $discussion .= '">'.
                            &mt('Preferences on what is marked as NEW').                             &mt('My general preferences on what is marked as NEW').
                            '</a><br /><a href="/adm/feedback?markread=1&amp;symb='.$escsymb;                             '</a><br /><a href="/adm/feedback?markread=1&amp;symb='.$escsymb;
             $discussion .= &group_args($group);              $discussion .= &group_args($group);
             $discussion .= '">'.&mt('Mark NEW posts no longer new').'</a></td>';              $discussion .= '">'.&mt('Mark NEW posts no longer new').'</a></td>';
Line 829  sub postingform_display { Line 941  sub postingform_display {
         $currnewattach,$currdelold,$group,$crstype) = @_;          $currnewattach,$currdelold,$group,$crstype) = @_;
     my $newattachmsg;      my $newattachmsg;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
               'note' => 'Note: in anonymous discussion, your name is visible only to course faculty',               'note' => 'Note: in anonymous discussion, your name is visible only to course faculty',
              'title' => 'Title',               'title' => 'Title',
              'podi' => 'Post Discussion',               'podi' => 'Post Discussion',
              'poan' => 'Post Anonymous Discussion',               'poan' => 'Post Anonymous Discussion',
Line 838  sub postingform_display { Line 950  sub postingform_display {
     if ($crstype eq 'Community') {      if ($crstype eq 'Community') {
         $lt{'note'} = &mt('Note: in anonymous discussion, your name is visible only to community facilitators');          $lt{'note'} = &mt('Note: in anonymous discussion, your name is visible only to community facilitators');
     }      }
     my $postingform = (<<ENDDISCUSS);      my ($postingform,$textareaclass);
       if (&Apache::lonhtmlcommon::htmlareabrowser()) {
           $postingform = &Apache::lonhtmlcommon::htmlareaselectactive();
           $textareaclass = 'class="LC_richDefaultOff"';
           if ($env{'request.course.id'}) {
               unless (($env{'course.'.$env{'request.course.id'}.'.allow_limited_html_in_feedback'} =~ /^\s*yes\s*$/i) || ($env{'form.sendmessageonly'})) {
                   undef($textareaclass);
               }
           }
       }
       my $postanon;
       if (&Apache::lonnet::allowed('pac',$env{'request.course.id'}.
          ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
           $postanon = '<input type="submit" name="anondiscuss" value="'.$lt{'poan'}.'" />';
       }
       $postingform .= (<<ENDDISCUSS);
 <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data"> <input type="submit" name="discuss" value="$lt{'podi'}" />  <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data"> <input type="submit" name="discuss" value="$lt{'podi'}" />
 <input type="submit" name="anondiscuss" value="$lt{'poan'}" /> <input type="hidden" name="symb" value="$ressymb" />  $postanon<input type="hidden" name="symb" value="$ressymb" />
 <input type="hidden" name="sendit" value="true" />  <input type="hidden" name="sendit" value="true" />
 <input type="hidden" name="timestamp" value="$now" />  <input type="hidden" name="timestamp" value="$now" />
 <br /><a name="newpost"></a>  <a name="newpost"></a>
 <font size="1">$lt{'note'}</font><br />  <font size="1">$lt{'note'}</font><br />
 <b>$lt{'title'}:</b>&nbsp;<input type="text" name="subject" value="$subject" size="30" /><br /><br />  <b>$lt{'title'}:</b>&nbsp;<input type="text" name="subject" value="$subject" size="30" /><br />
 <textarea name="comment" cols="80" rows="14" wrap="hard">$comment</textarea>  <textarea name="comment" cols="80" rows="14" id="comment" $textareaclass>$comment</textarea>
 ENDDISCUSS  ENDDISCUSS
     if ($env{'form.origpage'}) {      if ($env{'form.origpage'}) {
         $postingform .= '<input type="hidden" name="origpage" value="'.          $postingform .= '<input type="hidden" name="origpage" value="'.
Line 868  ENDDISCUSS Line 995  ENDDISCUSS
         $postingform .= &add_blog_checkbox($crstype);          $postingform .= &add_blog_checkbox($crstype);
     }      }
     $postingform .= "</form>\n";      $postingform .= "</form>\n";
     if ($outputtarget ne 'tex') {      $postingform .= &generate_attachments_button('',$attachnum,$ressymb,
         $postingform .= &generate_attachments_button('',$attachnum,$ressymb,  
                                                      $now,$currnewattach,                                                       $now,$currnewattach,
                                                      $currdelold,'',$mode,                                                       $currdelold,'',$mode,
                                                      $blockblog);                                                       $blockblog);
         if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) {      if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) {
             $newattachmsg = '<br /><b>'.$lt{'newa'}.'</b><br />';          $newattachmsg = '<br /><b>'.$lt{'newa'}.'</b><br />';
             if (@{$currnewattach} > 1) {          if (@{$currnewattach} > 1) {
                 $newattachmsg .= '<ol>';               $newattachmsg .= '<ol>';
                 foreach my $item (@{$currnewattach}) {               foreach my $item (@{$currnewattach}) {
                     $item =~ m#.*/([^/]+)$#;                  $item =~ m#.*/([^/]+)$#;
                     $newattachmsg .= '<li><a href="'.$item.'">'.$1.'</a></li>'."\n";                  $newattachmsg .= '<li><a href="'.$item.'">'.$1.'</a></li>'."\n";
                 }               }
                 $newattachmsg .= '</ol>'."\n";               $newattachmsg .= '</ol>'."\n";
             } else {           } else {
                 $$currnewattach[0] =~ m#.*/([^/]+)$#;               $$currnewattach[0] =~ m#.*/([^/]+)$#;
                 $newattachmsg .= '<a href="'.$$currnewattach[0].'">'.$1.'</a><br />'."\n";               $newattachmsg .= '<a href="'.$$currnewattach[0].'">'.$1.'</a><br />'."\n";
             }           }
         }  
         $postingform .= $newattachmsg;  
         $postingform .= &generate_preview_button();  
     }      }
       $postingform .= $newattachmsg;
       $postingform .= &generate_preview_button();
     return $postingform;      return $postingform;
 }  }
   
 sub build_posting_display {  sub build_posting_display {
     my ($usernamesort,$subjectsort,$namesort,$notshown,$newitem,$dischash,$shown,$alldiscussion,$imsitems,$imsfiles,$roleinfo,$discussionitems,$replies,$depth,$posters,$maxdepth,$visible,$newpostsflag,$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$ressymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,$anonhash,$anoncnt,$group) = @_;      my ($usernamesort,$subjectsort,$namesort,$notshown,$newitem,$dischash,$shown,$alldiscussion,$imsitems,$imsfiles,$roleinfo,$discussionitems,$replies,$depth,$posters,$maxdepth,$visible,$newpostsflag,$current,$status,$viewgrades,$seeid,$seehidden,$canvote,$prevread,$sortposts,$ressymb,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,$anonhash,$anoncnt,$group) = @_;
     my @original=();      my @original=();
     my @index=();      my @index=();
     my $skip_group_check = 0;      my $skip_group_check = 0;
     my $symb=&Apache::lonenc::check_decrypt($ressymb);      my $symb=&Apache::lonenc::check_decrypt($ressymb);
     my $escsymb=&escape($ressymb);      my $escsymb=&escape($ressymb);
   # These are the discussion contributions
     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},      my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
   $env{'course.'.$env{'request.course.id'}.'.domain'},    $env{'course.'.$env{'request.course.id'}.'.domain'},
   $env{'course.'.$env{'request.course.id'}.'.num'});    $env{'course.'.$env{'request.course.id'}.'.num'});
       my (%likes,%userlikes,%userunlikes,@theselikes,$oneplus,$twoplus,$oneminus,$twominus);
       my $thisuser=$env{'user.name'}.':'.$env{'user.domain'};
       if ($seeid || $canvote) {
   # And these are the likes/unlikes
           %likes=&Apache::lonnet::dump('disclikes',
                             $env{'course.'.$env{'request.course.id'}.'.domain'},
                             $env{'course.'.$env{'request.course.id'}.'.num'},
                             '^'.$symb.':');
   # Array with likes to figure out averages, etc.
           @theselikes=();
   # Hashes containing likes and unlikes for this user.
           %userlikes=();
           %userunlikes=();
       }
   # Is the user allowed to see the real name behind anonymous postings?
     my $see_anonymous =       my $see_anonymous = 
  &Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));   &Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
   
     if ((@{$grouppick} == 0) || (grep(/^all$/,@{$grouppick}))) {      if ((@{$grouppick} == 0) || (grep(/^all$/,@{$grouppick}))) {
         $skip_group_check = 1;          $skip_group_check = 1;
     }      }
   # Deletions and hiddens are just lists. Split them up into a hash for quicker lookup
       my (%deletions,%hiddens);
       if ($contrib{'deleted'}) {
          my $deleted = $contrib{'deleted'};
          $deleted =~ s/^\.//;
          $deleted =~ s/\.$//;
          %deletions = map { $_ => 1 } (split(/\.\./,$deleted));
       }
       if ($contrib{'hidden'}) {
          my $hidden = $contrib{'hidden'};
          $hidden =~ s/^\.//;
          $hidden =~ s/\.$//;
          %hiddens = map { $_ => 1 } (split(/\.\./,$hidden));
       }
   # Versions if store/restore are used to actually store the messages. 
     if ($contrib{'version'}) {      if ($contrib{'version'}) {
         my $oldest = $contrib{'1:timestamp'};          my $oldest = $contrib{'1:timestamp'};
         if ($prevread eq '0') {          if ($prevread eq '0') {
Line 920  sub build_posting_display { Line 1075  sub build_posting_display {
             ($skiptest,$roleregexp,$secregexp,$statusregexp) =               ($skiptest,$roleregexp,$secregexp,$statusregexp) = 
                      &filter_regexp($rolefilter,$sectionpick,$statusfilter);                       &filter_regexp($rolefilter,$sectionpick,$statusfilter);
             $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;              $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;
         }           }
           my %votestyle;
           if ($seeid || $canvote) {
   # We need to go through this twice, first to get the likes/dislikes, then to actually build the display
               for (my $id=1;$id<=$contrib{'version'};$id++) {
                   my $idx=$id;
                   next if ($contrib{$idx.':deleted'});
                   next if ($contrib{$idx.':hidden'});
                   unless ((($hiddens{$idx}) && (!$seehidden)) || ($deletions{$idx}) || (!$contrib{$idx.':message'})) {
                       push(@theselikes,$likes{$symb.':'.$idx.':likes'});
                       if ($likes{$symb.':'.$idx.':likes'} ne '') {
                           if (ref($likes{$symb.':'.$idx.':likers'}) eq 'HASH') {
                               if (exists($likes{$symb.':'.$idx.':likers'}{$thisuser})) {
                                   $userlikes{$idx} = 1;
                               }
                           }
                           if (ref($likes{$symb.':'.$idx.':unlikers'}) eq 'HASH') {
                               if (exists($likes{$symb.':'.$idx.':unlikers'}{$thisuser})) {
                                   $userunlikes{$idx} = 1;
                               }
                           }
                       }
                   }
               }
   # Figure out average likes and standard deviation if there are enough 
   # discussions to warrant that
               my $ave=0;
               my $stddev=10000;
               if ($#theselikes>1) {
                   my $sum=0;
                   my $num=$#theselikes+1;
                   foreach my $thislike (@theselikes) {
                       $sum+=$thislike;
                   }
                   $ave=$sum/$num;
                   my $sumsq=0;
                   foreach my $thislike (@theselikes) {
                       $sumsq+=($thislike-$ave)*($thislike-$ave);
                   }
                   $stddev=sqrt($sumsq/$num);
               }
   # Now we know the average likes $ave and the standard deviation $stddev
   # Get the boundaries for markup
               $oneplus=$ave+$stddev;
               $twoplus=$ave+2.*$stddev;
               $oneminus=$ave-$stddev;
               $twominus=$ave-2.*$stddev;
               if ($#theselikes>1) {
                   foreach my $class ('twoplus','oneplus','zero','oneminus','twominus') {
                       my $fontstyle = $env{'course.'.$env{'request.course.id'}.'.discussion_post_fonts_'.$class};
                       if ($fontstyle ne '') {
                           my ($size,$weight,$style,$other) = split(/,/,$fontstyle);
                           if ($size ne '') {
                               $votestyle{$class} .= 'font-size: '.$size.';';
                           }
                           if ($weight ne '') {
                               $votestyle{$class} .= 'font-weight: '.$weight.';';
                           }
                           if ($style ne '') {
                               $votestyle{$class} .= 'font-style: '.$style.';';
                           }
                           if ($other ne '') {
                               $votestyle{$class} .= $other;
                           }
                           if ($votestyle{$class} ne '') {
                               $votestyle{$class} = 'style="'.$votestyle{$class}.'"';
                           }
                       }
                   }
               }
           }
   #
   # This is now the real loop. Go through all entries, pick up what we need
   #
  for (my $id=1;$id<=$contrib{'version'};$id++) {   for (my $id=1;$id<=$contrib{'version'};$id++) {
     my $idx=$id;      my $idx=$id;
               next if ($contrib{$idx.':deleted'});
               next if ($contrib{$idx.':hidden'});
   # If we get here, we are actually going to display the message - we don't know where and we don't know if we display
   # previous edits, but it counts as one entry
             my $posttime = $contrib{$idx.':timestamp'};              my $posttime = $contrib{$idx.':timestamp'};
             if ($prevread <= $posttime) {              if ($prevread <= $posttime) {
                 $$newpostsflag = 1;                  $$newpostsflag = 1;
             }              }
     my $hidden=($contrib{'hidden'}=~/\.$idx\./);  
             my $studenthidden=($contrib{'studenthidden'}=~/\.$idx\./);              my $studenthidden=($contrib{'studenthidden'}=~/\.$idx\./);
     my $deleted=($contrib{'deleted'}=~/\.$idx\./);  
     my $origindex='0.';      my $origindex='0.';
             my $numoldver=0;              my $numoldver=0;
     if ($contrib{$idx.':replyto'}) {      if ($contrib{$idx.':replyto'}) {
                 if ( (($env{'environment.threadeddiscussion'}) && ($sortposts eq '')) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) {                  if ( ((!$env{'environment.unthreadeddiscussion'}) && ($sortposts eq '')) || 
                        ($sortposts eq 'thread') || ($outputtarget eq 'export')) {
 # this is a follow-up message  # this is a follow-up message
     $original[$idx]=$original[$contrib{$idx.':replyto'}];      $original[$idx]=$original[$contrib{$idx.':replyto'}];
     $$depth[$idx]=$$depth[$contrib{$idx.':replyto'}]+1;      $$depth[$idx]=$$depth[$contrib{$idx.':replyto'}]+1;
Line 953  sub build_posting_display { Line 1184  sub build_posting_display {
     } else {      } else {
  $$replies[$$depth[$idx]]=1;   $$replies[$$depth[$idx]]=1;
     }      }
     unless ((($hidden) && (!$seeid)) || ($deleted)) {              unless ((($hiddens{$idx}) && (!$seehidden)) || ($deletions{$idx})) {
  $$visible++;   $$visible++;
                 if ($contrib{$idx.':history'}) {                  if ($contrib{$idx.':history'}) {
                     if ($contrib{$idx.':history'} =~ /:/) {                      if ($contrib{$idx.':history'} =~ /:/) {
Line 968  sub build_posting_display { Line 1199  sub build_posting_display {
                 my %subjects = ();                  my %subjects = ();
                 my %attachtxt = ();                  my %attachtxt = ();
                 my %allattachments = ();                  my %allattachments = ();
                 my ($screenname,$plainname);                  my ($screenname,$plainname,$showaboutme);
                 my $sender = &mt('Anonymous');                  my $sender = &mt('Anonymous');
 # Anonymous users getting number within a discussion  # Anonymous users getting number within a discussion
 # Since idx is in static order, this should give the same sequence every time.   # Since idx is in static order, this should give the same sequence every time. 
Line 978  sub build_posting_display { Line 1209  sub build_posting_display {
     $$anonhash{$key}=&mt('Anonymous').' '.$anoncnt;      $$anonhash{$key}=&mt('Anonymous').' '.$anoncnt;
  }   }
                 my ($message,$subject,$vgrlink,$ctlink);                  my ($message,$subject,$vgrlink,$ctlink);
                 &get_post_contents(\%contrib,$idx,$seeid,$outputtarget,\%messages,\%subjects,\%allattachments,\%attachtxt,$imsfiles,\$screenname,\$plainname,$numoldver);                  &get_post_contents(\%contrib,$idx,$seeid,$seehidden,$outputtarget,\%messages,\%subjects,\%allattachments,\%attachtxt,$imsfiles,\$screenname,\$plainname,\$showaboutme,$numoldver);
   
   
 # Set up for sorting by subject  # Set up for sorting by subject
Line 987  sub build_posting_display { Line 1218  sub build_posting_display {
                     $message.=$attachtxt{$numoldver};                      $message.=$attachtxt{$numoldver};
                     $subject=$subjects{$numoldver};                      $subject=$subjects{$numoldver};
                     if ($message) {                      if ($message) {
           if ($hidden) {            if ($hiddens{$idx}) {
     $message='<font color="#888888">'.$message.'</font>';      $message='<font color="#888888">'.$message.'</font>';
                             if ($studenthidden) {                              if ($studenthidden) {
                                 $message .='<br /><br />Deleted by poster (student).';                                  $message .='<br /><br />Deleted by poster (student).';
Line 1008  sub build_posting_display { Line 1239  sub build_posting_display {
                             }                              }
                         }                          }
         if (!$contrib{$idx.':anonymous'} || $see_anonymous) {          if (!$contrib{$idx.':anonymous'} || $see_anonymous) {
     $sender=&Apache::loncommon::aboutmewrapper(                              if ($showaboutme) {
  $plainname,                                  $sender = &Apache::loncommon::aboutmewrapper(
  $contrib{$idx.':sendername'},                                                $plainname,
  $contrib{$idx.':senderdomain'}).' ('.                                                $contrib{$idx.':sendername'},
  $contrib{$idx.':sendername'}.':'.                                                $contrib{$idx.':senderdomain'});
  $contrib{$idx.':senderdomain'}.')';                              } else {
                                   $sender = $plainname;
                               }
                               if ($see_anonymous) {
                                   $sender .= ' ('.$contrib{$idx.':sendername'}.':'.
      $contrib{$idx.':senderdomain'}.')';
                               }
                             $sender = '<b>'.$sender.'</b>';                              $sender = '<b>'.$sender.'</b>';
     if ($contrib{$idx.':anonymous'}) {      if ($contrib{$idx.':anonymous'}) {
         $sender.=' <font color="red"><b>['.$$anonhash{$key}.']</b></font> '.          $sender.=' <font color="red"><b>['.$$anonhash{$key}.']</b></font> '.
Line 1022  sub build_posting_display { Line 1259  sub build_posting_display {
     if ($see_anonymous) {      if ($see_anonymous) {
  $sender.=&Apache::loncommon::student_image_tag($contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});   $sender.=&Apache::loncommon::student_image_tag($contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
     }      }
                             $sender = '<b>'.$sender.'</b>';  
 # Set up for sorting by domain, then username  # Set up for sorting by domain, then username
                             unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) {                              unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) {
                                 %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = ();                                  %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = ();
Line 1052  sub build_posting_display { Line 1288  sub build_posting_display {
                             } else {                              } else {
                                 @{$$namesort{$lastname}{$firstname}} = ("$idx");                                  @{$$namesort{$lastname}{$firstname}} = ("$idx");
                             }                              }
                             if (&editing_allowed($escsymb.':::'.$idx,$group)) {                              if ($outputtarget ne 'tex') {
                                 if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) {  # Add karma stars
                                     $sender.=' <a href="/adm/feedback?editdisc='.                                  my $karma=&userkarma($contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'});
                                          $escsymb.':::'.$idx;                                  for (my $i=1;$i<=$karma;$i++) {
                                     if ($$newpostsflag) {                                      $sender.='<img border="0" src="/res/adm/pages/star.gif" alt="'.&mt('Contributor Kudos').'" />';
                                         $sender .= '&previous='.$prevread;  
                                     }  
     $sender .= &group_args($group);  
                                     $sender .= '" '.$target.'>'.&mt('Edit').'</a>';  
                                       
                                     unless ($seeid) {  
                                         my $grpargs = &group_args($group);  
                                         $sender.=" <a href=\"javascript:verifydelete('studentdelete','$escsymb','$idx','$$newpostsflag','$prevread','$grpargs')";  
                                         $sender .= '">'.&mt('Delete').'</a>';  
                                     }  
                                 }                                  }
                             }   # Can people edit this?
     if ($seeid) {                                  if (&editing_allowed($escsymb.':::'.$idx,$group)) {
         if ($hidden) {                                      if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) {
                                     unless ($studenthidden) {                                          $sender.=' '.
                 $sender.=' <a href="/adm/feedback?unhide='.                                           &discussion_link($ressymb,&mt('Edit'),'editdisc',$idx,$$newpostsflag,$prevread,&group_args($group));
                 $escsymb.':::'.$idx;                                          unless ($seehidden) {
                                         if ($$newpostsflag) {                                              my $grpargs = &group_args($group);
                                             $sender .= '&previous='.$prevread;                                              $sender.=" <a href=\"javascript:verifydelete('studentdelete','$escsymb','$idx','$$newpostsflag','$prevread','$grpargs')";
                                               $sender .= '">'.&mt('Delete').'</a>';
                                         }                                          }
                                         $sender .= '">'.&mt('Make Visible').'</a>';  
                                     }  
         } else {  
     $sender.=' <a href="/adm/feedback?hide='.  
         $escsymb.':::'.$idx;  
                                     if ($$newpostsflag) {  
                                         $sender .= '&previous='.$prevread;  
                                     }                                      }
     $sender .= &group_args($group);                                  }
                                     $sender .= '">'.&mt('Hide').'</a>';          if ($seehidden) {
         }              if ($hiddens{$idx}) {
                                 my $grpargs = &group_args($group);                                          unless ($studenthidden) {
         $sender.=                               $sender.=' '.
                                     " <a href=\"javascript:verifydelete('seeiddelete','$escsymb','$idx','$$newpostsflag','$prevread','$grpargs')\">";                                              &discussion_link($ressymb,&mt('Make Visible'),'unhide',$idx,$$newpostsflag,$prevread,&group_args($group));
                                 $sender .= &mt('Delete').'</a>';                                          }
               } else {
                                           $sender.=' '.
                                            &discussion_link($ressymb,&mt('Hide'),'hide',$idx,$$newpostsflag,$prevread,&group_args($group));
               }
                                       my $grpargs = &group_args($group);
               $sender.= 
                                           " <a href=\"javascript:verifydelete('seeiddelete','$escsymb','$idx','$$newpostsflag','$prevread','$grpargs')\">";
                                       $sender .= &mt('Delete').'</a>';
                                   }
                             }                              }
         } else {                          } else {
     if ($screenname) {      if ($screenname) {
         $sender='<i>'.$screenname.'</i>';          $sender='<i>'.$screenname.'</i>';
     } else {      } else {
  $sender='<i>'.$$anonhash{$key}.'</i>';   $sender='<i>'.$$anonhash{$key}.'</i>';
     }      }
                               $sender = '<b>'.$sender.'</b>';
 # Set up for sorting by domain, then username for anonymous  # Set up for sorting by domain, then username for anonymous
                             unless (defined($$usernamesort{'__anon'})) {                              unless (defined($$usernamesort{'__anon'})) {
                                 %{$$usernamesort{'__anon'}} = ();                                  %{$$usernamesort{'__anon'}} = ();
Line 1118  sub build_posting_display { Line 1348  sub build_posting_display {
                                 @{$$namesort{'__anon'}{'__anon'}} = ("$idx");                                  @{$$namesort{'__anon'}{'__anon'}} = ("$idx");
                             }                              }
         }          }
         if (&discussion_open($status)) {                          if ($outputtarget ne 'tex') {
                             if (($group ne '') &&               if (&discussion_open($status)) {
                                 (&check_group_priv($group,'pgd') eq 'ok')) {                                  if (($group ne '') && 
                                  $sender.=' <a href="/adm/feedback?replydisc='.                                      (&check_group_priv($group,'pgd') eq 'ok')) {
                                           $escsymb.':::'.$idx;                                       $sender.=' '.
                                 if ($$newpostsflag) {                                           &discussion_link($ressymb,&mt('Reply'),'replydisc',$idx,$$newpostsflag,$prevread,&group_args($group));
                                     $sender .= '&previous='.$prevread;                                  } elsif (&Apache::lonnet::allowed('pch', 
                                 }       $env{'request.course.id'}.
                                 $sender .= &group_args($group);       ($env{'request.course.sec'}?'/'.
                                 $sender .= '" '.$target.'>'.&mt('Reply').'</a>';                                        $env{'request.course.sec'}:''))) {
                             } elsif (&Apache::lonnet::allowed('pch',                $sender.=' '.
  $env{'request.course.id'}.                                           &discussion_link($ressymb,&mt('Reply'),'replydisc',$idx,$$newpostsflag,$prevread);
  ($env{'request.course.sec'}?'/'.  
                                   $env{'request.course.sec'}:''))) {  
          $sender.=' <a href="/adm/feedback?replydisc='.  
                   $escsymb.':::'.$idx;  
                                 if ($$newpostsflag) {  
                                     $sender .= '&previous='.$prevread;  
                                 }                                  }
                                 $sender .= '" '.$target.'>'.&mt('Reply').'</a>';  
                             }                              }
                         }              if ($viewgrades) {
         if ($viewgrades) {          $vgrlink=&Apache::loncommon::submlink(&mt('Submissions'),
         $vgrlink=&Apache::loncommon::submlink('Submissions',                                  $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);
                             $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);              }
         }                              if ($$dischash{$readkey}=~/\.$idx\./) { 
                         if ($$dischash{$readkey}=~/\.$idx\./) {                                   $ctlink = '<label><b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" /></label>';
                             $ctlink = '<label><b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" /></label>';                              } else {
                         } else {                                  $ctlink = '<label><b>'.&mt('Mark read').'?</b>&nbsp;<input type="checkbox" name="postread_'.$idx.'" /></label>';
                             $ctlink = '<label><b>'.&mt('Mark read').'?</b>&nbsp;<input type="checkbox" name="postread_'.$idx.'" /></label>';                              }
                         }                          }
                     }                      }
 #figure out at what position this needs to print  #figure out at what position this needs to print
                 }                  }
                 if ($outputtarget eq 'export' || $message) {                  if ($outputtarget eq 'export' || $message) {
     my $thisindex=$idx;      my $thisindex=$idx;
     if ( (($env{'environment.threadeddiscussion'}) && ($sortposts eq '')) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) {      if ( ((!$env{'environment.unthreadeddiscussion'}) && ($sortposts eq '')) || 
                            ($sortposts eq 'thread') || ($outputtarget eq 'export')) {
  $thisindex=$origindex.substr('00'.$$replies[$$depth[$idx]],-2,2);   $thisindex=$origindex.substr('00'.$$replies[$$depth[$idx]],-2,2);
     }      }
     $$alldiscussion{$thisindex}=$idx;      $$alldiscussion{$thisindex}=$idx;
Line 1164  sub build_posting_display { Line 1388  sub build_posting_display {
                 if ($outputtarget eq 'export') {                  if ($outputtarget eq 'export') {
                     %{$$imsitems{$idx}} = ();                      %{$$imsitems{$idx}} = ();
                     $$imsitems{$idx}{'isvisible'}='true';                      $$imsitems{$idx}{'isvisible'}='true';
                     if ($hidden) {                      if ($hiddens{$idx}) {
                         $$imsitems{$idx}{'isvisible'}='false';                          $$imsitems{$idx}{'isvisible'}='false';
                     }                      }
                     $$imsitems{$idx}{'title'}=$subjects{$numoldver};                      $$imsitems{$idx}{'title'}=$subjects{$numoldver};
Line 1172  sub build_posting_display { Line 1396  sub build_posting_display {
                     $$imsitems{$idx}{'attach'}=$attachtxt{$numoldver};                      $$imsitems{$idx}{'attach'}=$attachtxt{$numoldver};
                     $$imsitems{$idx}{'timestamp'}=$contrib{$idx.':timestamp'};                      $$imsitems{$idx}{'timestamp'}=$contrib{$idx.':timestamp'};
                     $$imsitems{$idx}{'sender'}=$plainname.' ('.                      $$imsitems{$idx}{'sender'}=$plainname.' ('.
                                          $contrib{$idx.':sendername'}.' at '.                                           $contrib{$idx.':sendername'}.':'.
                                          $contrib{$idx.':senderdomain'}.')';                                           $contrib{$idx.':senderdomain'}.')';
                     $$imsitems{$idx}{'isanonymous'}='false';                      $$imsitems{$idx}{'isanonymous'}='false';
                     if ($contrib{$idx.':anonymous'}) {                      if ($contrib{$idx.':anonymous'}) {
Line 1186  sub build_posting_display { Line 1410  sub build_posting_display {
                 } else {                  } else {
                     if ($message) {                      if ($message) {
                         my $spansize = 2;                          my $spansize = 2;
                           my ($uname,$udom);
                         if ($showonlyunread && $prevread > $posttime) {                          if ($showonlyunread && $prevread > $posttime) {
                             $$notshown{$idx} = 1;                              $$notshown{$idx} = 1;
                         } elsif ($showunmark && $$dischash{$readkey}=~/\.$idx\./) {                          } elsif ($showunmark && $$dischash{$readkey}=~/\.$idx\./) {
                             $$notshown{$idx} = 1;                              $$notshown{$idx} = 1;
                         } else {                          } else {
 # apply filters  # apply filters
                             my $uname = $contrib{$idx.':sendername'};                              $uname = $contrib{$idx.':sendername'};
                             my $udom = $contrib{$idx.':senderdomain'};                              $udom = $contrib{$idx.':senderdomain'};
                             my $poster = $uname.':'.$udom;                              my $poster = $uname.':'.$udom;
                             if ($env{'form.totposters'} ne '') {                              if ($env{'form.totposters'} ne '') {
                                 if ($totposters == 0) {                                  if ($totposters == 0) {
Line 1244  sub build_posting_display { Line 1469  sub build_posting_display {
                         unless ($$notshown{$idx} == 1) {                          unless ($$notshown{$idx} == 1) {
                             if ($prevread > 0 && $prevread <= $posttime) {                              if ($prevread > 0 && $prevread <= $posttime) {
                                 $$newitem{$idx} = 1;                                  $$newitem{$idx} = 1;
                                 $$discussionitems[$idx] .= '                                  $$discussionitems[$idx] .= '<font color="#FF0000"><b>'.&mt('NEW').'&nbsp;&nbsp;</b></font>';
                                  <p><table border="0" width="100%">  
                                   <tr><td align="left"><font color="#FF0000"><b>'.&mt('NEW').'</b></font></td>';  
                             } else {                              } else {
                                 $$newitem{$idx} = 0;                                  $$newitem{$idx} = 0;
                                 $$discussionitems[$idx] .= '  
                                  <p><table border="0" width="100%">  
                                   <tr><td align="left">&nbsp;</td>';  
                             }                              }
                             $$discussionitems[$idx] .= '<td align="left">&nbsp;&nbsp;'.                              $$discussionitems[$idx] .= '<b>'.$subject.'</b>&nbsp;&nbsp;'.
                                 '<b>'.$subject.'</b>&nbsp;&nbsp;'.  
                                 $sender.' '.$vgrlink.' ('.                                  $sender.' '.$vgrlink.' ('.
                                 &Apache::lonlocal::locallocaltime($posttime).')</td>';                                  &Apache::lonlocal::locallocaltime($posttime).')';
                             if ($$dischash{$toggkey}) {                              if ($$dischash{$toggkey}) {
                                 $$discussionitems[$idx].='<td align="right">&nbsp;&nbsp;'.                                  $$discussionitems[$idx].='&nbsp;&nbsp;'.$ctlink;
                                   $ctlink.'</td>';                              }
                               my $thislikes=$likes{$symb.':'.$idx.':likes'};
                               my $likestyle;
                               if ($seeid || $canvote) {
   # Figure out size based on likes
                                   my $class = 'zero';
                                   my $thislikes=$likes{$symb.':'.$idx.':likes'};
                                   if ($thislikes>$twoplus) {
                                       $class = 'twoplus';
                                   } elsif ($thislikes>$oneplus) {
                                       $class = 'oneplus';
                                   }
                                   if ($thislikes<$twominus) {
                                       $class = 'twominus';
                                   } elsif ($thislikes<$oneminus) {
                                       $class = 'oneminus';
                                   }
                                   $likestyle = $votestyle{$class};
                             }                              }
                             $$discussionitems[$idx].= '</tr></table><blockquote>'.  # Actually glue in the message itself
                                     $message.'</blockquote></p>';                              $$discussionitems[$idx].= '<br /><blockquote>'.
                                       "<div $likestyle>".
                                       $message.
                                       '</div></blockquote>';
                               if ($canvote) {
                                   my $ownpost;
                                   if (($uname eq $env{'user.name'}) &&
                                       ($udom eq $env{'user.domain'})) {
                                       $ownpost = 1;
                                   }   
   # Put in the like and unlike buttons
                                   if ($ownpost || (($hiddens{$idx}) && ($seehidden))) { 
                                       my $novote;
                                       if ($ownpost) { 
                                           $novote = &mt('No voting for your own posts.');
                                       } else {
                                           $novote = &mt('No voting for hidden posts.');
                                       }
                                       &html_escape(\$novote);
                                       $$discussionitems[$idx].=
                                           '<a href="javascript:alert('."'$novote'".');" style="text-decoration: none;">'.
                                           '<img border="0" src="/res/adm/pages/thumbsup_novote.png" alt="'.$novote.'" />&nbsp;'.
                                           '<img border="0" src="/res/adm/pages/thumbsdown_novote.png" alt="'.$novote.'" /></a>'; 
   
                                   } else {
                                       if ($userlikes{$idx}) {
                                           $$discussionitems[$idx].='<img border="0" src="/res/adm/pages/thumbsup_gray.png" alt="'.&mt('You like this posting').'" />';
                                       } else {
                                           $$discussionitems[$idx].='&nbsp;'.&discussion_link($ressymb,'<img border="0" src="/res/adm/pages/thumbsup.png" alt="'.&mt('Like').'" />','like',$idx,$$newpostsflag,$prevread,&group_args($group),&mt("Like this posting"));
                                       }
                                       if ($userunlikes{$idx}) {
                                           $$discussionitems[$idx].='<img border="0" src="/res/adm/pages/thumbsdown_gray.png" alt="'.&mt('You unlike this posting').'" />';
                                       } else {
                                           $$discussionitems[$idx].='&nbsp;'.&discussion_link($ressymb,'<img border="0" src="/res/adm/pages/thumbsdown.png" alt="'.&mt('Unlike').'" />','unlike',$idx,$$newpostsflag,$prevread,&group_args($group),&mt("Unlike this posting"));
                                       }
                                   }
                               }
                               if ($seeid || $canvote) {
                                   my $thislikes=$likes{$symb.':'.$idx.':likes'};
                                   if ($thislikes>0) {
                                       $$discussionitems[$idx].='&nbsp;('.&mt("[_1] likes",$thislikes).')';
                                   } elsif ($thislikes<0) {
                                       $$discussionitems[$idx].='&nbsp;('.&mt("[_1] unlikes",abs($thislikes)).')';
                                   }
                               }
   # If there is any history to this post, inform the reader
                             if ($contrib{$idx.':history'}) {                              if ($contrib{$idx.':history'}) {
                                 my @postversions = ();                                  my @postversions = ();
                                 $$discussionitems[$idx] .= &mt('This post has been edited by the author.');                                  $$discussionitems[$idx] .= '&nbsp;&nbsp;'.&mt('This post has been edited by the author.');
                                 if ($seeid) {                                  if ($seehidden) {
                                     $$discussionitems[$idx] .= '&nbsp;&nbsp;<a href="/adm/feedback?allversions='.$escsymb.':::'.$idx;                                      $$discussionitems[$idx] .= '&nbsp;&nbsp;'.
     $$discussionitems[$idx] .= &group_args($group);                                           &discussion_link($ressymb,&mt('Display all versions'),'allversions',$idx,$$newpostsflag,$prevread,&group_args($group));
                                     $$discussionitems[$idx] .= '">'.&mt('Display all versions').'</a>';  
                                 }                                  }
                                 $$discussionitems[$idx].='<br/>'.&mt('Earlier version(s) were posted on: ');                                  $$discussionitems[$idx].='<br/>'.&mt('Earlier version(s) were posted on: ');
                                 if ($contrib{$idx.':history'} =~ m/:/) {                                  if ($contrib{$idx.':history'} =~ m/:/) {
Line 1282  sub build_posting_display { Line 1562  sub build_posting_display {
                                     $$discussionitems[$idx] .= '<b>'.$version.'.</b> - '.&Apache::lonlocal::locallocaltime($postversions[$i]).'  ';                                      $$discussionitems[$idx] .= '<b>'.$version.'.</b> - '.&Apache::lonlocal::locallocaltime($postversions[$i]).'  ';
                                 }                                  }
                             }                              }
   # end of unless ($$notshown ...)
                         }                          }
   # end of if ($message) ...
                     }                      }
   # end of the else-branch of target being export
                 }                  }
   # end of unless hidden or deleted
             }              }
   # end of the loop over all discussion entries
  }   }
   # end of "if there actually are any discussions
     }      }
   # end of subroutine "build_posting_display" 
 }  }
   
 sub filter_regexp {  sub filter_regexp {
Line 1346  sub filter_regexp { Line 1633  sub filter_regexp {
   
   
 sub get_post_contents {  sub get_post_contents {
     my ($contrib,$idx,$seeid,$type,$messages,$subjects,$allattachments,$attachtxt,$imsfiles,$screenname,$plainname,$numver) = @_;      my ($contrib,$idx,$seeid,$seehidden,$type,$messages,$subjects,$allattachments,$attachtxt,$imsfiles,$screenname,$plainname,$showaboutme,$numver) = @_;
     my $discussion = '';      my $discussion = '';
     my $start=$numver;      my $start=$numver;
     my $end=$numver + 1;      my $end=$numver + 1;
     %{$$imsfiles{$idx}}=();      %{$$imsfiles{$idx}}=();
     if ($type eq 'allversions') {      if ($type eq 'allversions') {
        unless($seeid) {         unless($seehidden) {
            $discussion=&mt('You do not have privileges to view all versions of posts.').' '.&mt('Please select a different role.');             $discussion=&mt('You do not have privileges to view all versions of posts.').' '.&mt('Please select a different role.');
            return $discussion;             return $discussion;
        }          } 
Line 1364  sub get_post_contents { Line 1651  sub get_post_contents {
                                         $$contrib{$idx.':sendername'},                                          $$contrib{$idx.':sendername'},
                                         $$contrib{$idx.':senderdomain'});                                          $$contrib{$idx.':senderdomain'});
     $$screenname=$$contrib{$idx.':screenname'};      $$screenname=$$contrib{$idx.':screenname'};
       $$showaboutme = &Apache::lonnet::usertools_access($$contrib{$idx.':sendername'},
     my $sender=&Apache::loncommon::aboutmewrapper(                                                        $$contrib{$idx.':senderdomain'},
                                                         'aboutme');
       my $sender = $$plainname;
       if ($$showaboutme) {
           $sender = &Apache::loncommon::aboutmewrapper(
                                  $$plainname,                                   $$plainname,
                                  $$contrib{$idx.':sendername'},                                   $$contrib{$idx.':sendername'},
                                  $$contrib{$idx.':senderdomain'}).' ('.                                   $$contrib{$idx.':senderdomain'});
                                  $$contrib{$idx.':sendername'}.' at '.      }
                                  $$contrib{$idx.':senderdomain'}.')';      if ($seeid) {
           $sender .= ' ('.$$contrib{$idx.':sendername'}.':'.
                      $$contrib{$idx.':senderdomain'}.')';
       }
     my $attachmenturls = $$contrib{$idx.':attachmenturl'};      my $attachmenturls = $$contrib{$idx.':attachmenturl'};
     my @postversions = ();      my @postversions = ();
     if ($type eq 'allversions' || $type eq 'export') {      if ($type eq 'allversions' || $type eq 'export') {
Line 1397  sub get_post_contents { Line 1691  sub get_post_contents {
         my ($timesent,$attachmsg);          my ($timesent,$attachmsg);
         my %currattach = ();          my %currattach = ();
         $timesent = &Apache::lonlocal::locallocaltime($postversions[$i]);          $timesent = &Apache::lonlocal::locallocaltime($postversions[$i]);
  &newline_to_br(\$messages->{$i});          unless (&contains_block_html($messages->{$i})) {
               &newline_to_br(\$messages->{$i});
           }
         $$messages{$i}=&Apache::lontexconvert::msgtexconverted($$messages{$i});          $$messages{$i}=&Apache::lontexconvert::msgtexconverted($$messages{$i});
         $$subjects{$i}=~s/\n/\<br \/\>/g;          $$subjects{$i}=~s/\n/\<br \/\>/g;
         $$subjects{$i}=&Apache::lontexconvert::msgtexconverted($$subjects{$i});          $$subjects{$i}=&Apache::lontexconvert::msgtexconverted($$subjects{$i});
Line 1411  sub get_post_contents { Line 1707  sub get_post_contents {
                 foreach my $key (sort(keys(%currattach))) {                  foreach my $key (sort(keys(%currattach))) {
                     if ($$allattachments{$key}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {                      if ($$allattachments{$key}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {
                         my $fname = $1.$3.'/'.$4;                          my $fname = $1.$3.'/'.$4;
                         $$imsfiles{$idx}{$i} .= '<file href="'.$fname.'">'."\n";                          $$imsfiles{$idx}{$i} .= '<file href="'.$fname.'" />'."\n";
                         $$attachtxt{$i}.= '<a href="'.$fname.'">'.$4.'</a><br />';                          $$attachtxt{$i}.= '<a href="'.$fname.'">'.$4.'</a><br />';
                     }                      }
                 }                  }
Line 1484  sub mail_screen { Line 1780  sub mail_screen {
   }    }
   
   my %lt = &Apache::lonlocal::texthash(    my %lt = &Apache::lonlocal::texthash(
             'myqu' => 'My question/comment/feedback:',              'myqu' => 'Question/comment/feedback:',
             'title' => 'Title',  
             'reta' => 'Retained attachments',              'reta' => 'Retained attachments',
             'atta' => 'Attachment',              'atta' => 'Attachment',
            );             );
     if ($env{'form.editdisc'} || $env{'form.replydisc'}){
         $lt{'myqu'} = &mt('Post Discussion');
     }
   my $restitle = &get_resource_title($caller_symb,$feedurl);    my $restitle = &get_resource_title($caller_symb,$feedurl);
   my $quote='';    my $quote='';
   my $subject = '';    my $subject = '';
Line 1553  END Line 1851  END
    $env{'course.'.$env{'request.course.id'}.'.domain'},     $env{'course.'.$env{'request.course.id'}.'.domain'},
    $env{'course.'.$env{'request.course.id'}.'.num'});     $env{'course.'.$env{'request.course.id'}.'.num'});
       unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {        unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {
             my $numoldver = 0;
           if ($contrib{$idx.':history'}) {            if ($contrib{$idx.':history'}) {
               if ($contrib{$idx.':history'} =~ /:/) {                if ($contrib{$idx.':history'} =~ /:/) {
                   my @oldversions = split(/:/,$contrib{$idx.':history'});                    my @oldversions = split(/:/,$contrib{$idx.':history'});
Line 1561  END Line 1860  END
                   $numoldver = 1;                    $numoldver = 1;
               }                }
           }            }
           if ($env{'form.replydisc'}) {            if ($idx > 0) {
               if ($contrib{$idx.':history'}) {                my (%msgversions,%subversions,$htmldecode);
                   if ($contrib{$idx.':history'} =~ /:/) {                $htmldecode = 0;
                       my @oldversions = split(/:/,$contrib{$idx.':history'});                if ($env{'form.replydisc'}) {
                       $numoldver = @oldversions;                    $htmldecode = 1;
                   } else {  
                       $numoldver = 1;  
                   }  
               }                }
               if ($idx > 0) {                &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);
                   my %msgversions = ();                &get_post_versions(\%subversions,$contrib{$idx.':subject'},$htmldecode,
                   &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);                                   $numoldver);
                 $subject = $subversions{$numoldver};
                 if ($env{'form.replydisc'}) {
                   $quote = $msgversions{$numoldver};                    $quote = $msgversions{$numoldver};
               }                    $subject = &HTML::Entities::encode(&mt('Re: ').$subject,'<>&"');
               if ($idx > 0) {                } else {
                   my %subversions = ();  
                   &get_post_versions(\%subversions,$contrib{$idx.':subject'},1,$numoldver);  
                   $subject = &mt('Re: ').$subversions{$numoldver};  
               }  
               $subject = &HTML::Entities::encode($subject,'<>&"');  
           } else {  
               $attachmenturls = $contrib{$idx.':attachmenturl'};  
               if ($idx > 0) {  
                   my %msgversions = ();  
                   &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);  
                   $comment = $msgversions{$numoldver};                    $comment = $msgversions{$numoldver};
                   my %subversions = ();  
                   &get_post_versions(\%subversions,$contrib{$idx.':subject'},0,$numoldver);  
                   $subject = $subversions{$numoldver};   
               }                }
             }
             if ($env{'form.editdisc'}) {
                 $attachmenturls = $contrib{$idx.':attachmenturl'};
               if (defined($contrib{$idx.':replyto'})) {                if (defined($contrib{$idx.':replyto'})) {
                   $parentmsg = $contrib{$idx.':replyto'};                    $parentmsg = $contrib{$idx.':replyto'};
               }                }
Line 1623  END Line 1911  END
       $comment = &unescape($env{'form.comment'});        $comment = &unescape($env{'form.comment'});
       &process_attachments(\@currnewattach,\@currdelold,\@keepold);        &process_attachments(\@currnewattach,\@currdelold,\@keepold);
   }    }
   my $latexHelp=&Apache::loncommon::helpLatexCheatsheet(undef,undef,1);    my $latexHelp=&Apache::loncommon::helpLatexCheatsheet(undef,undef,1,($env{'form.modal'}?'popup':0));
   my $send=&mt('Send');    my $send=&mt('Send');
   my $alert = &mt('Please select a feedback type.');    my $alert = &mt('Please select a feedback type.');
     &js_escape(\$alert);
   my $js= <<END;    my $js= <<END;
 <script type="text/javascript">  <script type="text/javascript">
 //<!--  //<!--
Line 1663  END Line 1952  END
     $anonscript      $anonscript
 //-->  //-->
 </script>  </script>
   <script type="text/javascript" src="/res/adm/includes/file_upload.js"></script>
 END  END
   
     my ($textareaheader,$textareaclass);
     if (&Apache::lonhtmlcommon::htmlareabrowser()) {
         $textareaheader = &Apache::lonhtmlcommon::htmlareaselectactive();
         $textareaclass = 'class="LC_richDefaultOff"';
         if ($env{'request.course.id'}) {
             unless (($env{'course.'.$env{'request.course.id'}.'.allow_limited_html_in_feedback'} =~ /^\s*yes\s*$/i) || ($env{'form.sendmessageonly'})) {
                 undef($textareaclass);
             }
         }
     }
   
     # Breadcrumbs
     my $brcrum = [{'href' => '',
                    'text' => 'Resource Feedback and Discussion'}];
   
   my %onload = ('onload' => 'window.focus();setposttype();');    my %onload = ('onload' => 'window.focus();setposttype();');
     my %parms=('add_entries' => \%onload);
     if ($env{'form.modal'} ne 'yes') { $parms{'bread_crumbs'} = $brcrum; }
   my $start_page=    my $start_page=
       &Apache::loncommon::start_page('Resource Feedback and Discussion',$js,        &Apache::loncommon::start_page('Resource Feedback and Discussion',$js,\%parms);
      {'add_entries' => \%onload});  
   
   if ($quote ne '') {    if ($quote ne '') {
       &newline_to_br(\$quote);        $quote = &HTML::Entities::decode($quote);
       $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($quote).'</blockquote>';        unless (&contains_block_html($quote)) {
             &newline_to_br(\$quote);
         }
           $quote=&Apache::lonhtmlcommon::start_pick_box().
                  &Apache::lonhtmlcommon::row_title(&mt('Quote')).
                  &Apache::lontexconvert::msgtexconverted($quote).
                  &Apache::lonhtmlcommon::row_closure(1).
                  &Apache::lonhtmlcommon::end_pick_box();
     }
     my $header='';
     unless ($env{'form.modal'}) {
        $header="<h2><tt>$restitle</tt></h2>";
   }    }
   
   $r->print(<<END);    $r->print(<<END);
 $start_page  $start_page
 <h2><tt>$restitle</tt></h2>  <h1>$lt{'myqu'}</h1>
   $header
 <form action="/adm/feedback" method="post" name="mailform"  <form action="/adm/feedback" method="post" name="mailform"
 enctype="multipart/form-data">  enctype="multipart/form-data">
 $prevtag  $prevtag
 <input type="hidden" name="postdata" value="$feedurl" />  <input type="hidden" name="postdata" value="$feedurl" />
   <input type="hidden" name="modal" value="$env{'form.modal'}" />
 END  END
   if ($env{'form.replydisc'}) {    if ($env{'form.replydisc'}) {
       $r->print(<<END);        $r->print(<<END);
Line 1694  END Line 2012  END
 END  END
   }    }
   $r->print(<<END);    $r->print(<<END);
 $options<hr />  $options
   <br />
   END
   $r->print(&Apache::lonhtmlcommon::start_pick_box());
   $r->print(<<END);
 $quote  $quote
 <p>$lt{'myqu'}</p>  
 <p>  <p>
 $latexHelp  $textareaheader
 </p>  </p>
 <p>  <p>
 $lt{'title'}: <input type="text" name="subject" size="30" value="$subject" /></p>  $latexHelp
 <p>  </p>
 <textarea name="comment" id="comment" cols="60" rows="10" wrap="hard">$comment  
 </textarea></p>  
 <p>  <p>
 END  END
   
       
       $r->print(&Apache::lonhtmlcommon::row_title(&mt('Subject')));
       $r->print('<input type="text" name="subject" size="30" value="'.
                 $subject.'" /></p>');
       $r->print(&Apache::lonhtmlcommon::row_closure());
       $r->print(&Apache::lonhtmlcommon::row_title(&mt('Message')));
       $r->print('<textarea name="comment" id="comment" cols="55" rows="10" '.
                 $textareaclass.'>'.$comment.
                 '</textarea>');
       $r->print(&Apache::lonhtmlcommon::row_closure(1));
       $r->print(&Apache::lonhtmlcommon::end_pick_box());
   
     if ( ($env{'form.editdisc'}) || ($env{'form.replydisc'}) ) {      if ( ($env{'form.editdisc'}) || ($env{'form.replydisc'}) ) {
         if ($env{'form.origpage'}) {          if ($env{'form.origpage'}) {
             foreach my $attach (@currnewattach) {              foreach my $attach (@currnewattach) {
Line 1727  END Line 2059  END
         }          }
     } else {      } else {
         $r->print(<<END);          $r->print(<<END);
 $lt{'atta'} $attachmaxtext: <input type="file" name="attachment" />  <p>
   $lt{'atta'} $attachmaxtext: <input type="file" name="attachment" class="LC_flUpload" />
   <input type="hidden" id="LC_free_space" value="131072" />
 </p>  </p>
 END  END
     }      }
Line 1738  END Line 2072  END
         $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.'" />');          $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.'" />');
     }      }
     $r->print(<<END);      $r->print(<<END);
 <p>  <input type="hidden" name="sendit" value="1" /><br /><br />
 <input type="hidden" name="sendit" value="1" />  <input type="button" value="$send" onclick='gosubmit();' />
 <input type="button" value="$send" onClick='gosubmit();' />  
 </p>  
 </form>  </form>
 END  END
     if ($env{'form.editdisc'} || $env{'form.replydisc'}) {      if ($env{'form.editdisc'} || $env{'form.replydisc'}) {
Line 1756  END Line 2088  END
             $attachnum += @currnewattach;              $attachnum += @currnewattach;
         }          }
         my $blockblog = &Apache::loncommon::blocking_status('blogs');          my $blockblog = &Apache::loncommon::blocking_status('blogs');
         $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver,'',$blockblog));  
         if ($attachnum > 0) {          if ($attachnum > 0) {
             if (@currnewattach > 0) {              if (@currnewattach > 0) {
                 $newattachmsg .= '<br /><b>'.&mt('New attachments').'</b><br />';                  $newattachmsg .= '<br /><b>'.&mt('New attachments').'</b><br />';
Line 1776  END Line 2107  END
                 $r->print("<br /><b>$lt{'reta'}</b>:$attachmsg<br />\n");                  $r->print("<br /><b>$lt{'reta'}</b>:$attachmsg<br />\n");
             }              }
             if ($newattachmsg) {              if ($newattachmsg) {
                 $r->print("$newattachmsg<br />");                  $r->print("$newattachmsg");
             }              }
         }          }
           $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver,'',$blockblog));
     }      }
     $r->print(&generate_preview_button().      $r->print(&generate_preview_button().
               &Apache::lonhtmlcommon::htmlareaselectactive('comment').  
       &Apache::loncommon::end_page());        &Apache::loncommon::end_page());
   
 }  }
Line 1819  sub print_display_options { Line 2150  sub print_display_options {
         'yhni' => 'You have not indicated that you wish to change any of the discussion settings',          'yhni' => 'You have not indicated that you wish to change any of the discussion settings',
         'ywbr' => 'You will be returned to the previous page if you click OK.'          'ywbr' => 'You will be returned to the previous page if you click OK.'
     );      );
       my %js_lt = &Apache::lonlocal::texthash(
           'yhni' => 'You have not indicated that you wish to change any of the discussion settings',
           'ywbr' => 'You will be returned to the previous page if you click OK.'
       );
       &js_escape(\%js_lt);
   
     my $dispchangeA = $lt{'unread'};      my $dispchangeA = $lt{'unread'};
     my $dispchangeB = $lt{'unmark'};      my $dispchangeB = $lt{'unmark'};
Line 1912  function setDisp() { Line 2248  function setDisp() {
     if (chktotal > 0) {       if (chktotal > 0) { 
         document.modifydisp.submit()          document.modifydisp.submit()
     } else {      } else {
         if(confirm("$lt{'yhni'}. \\n$lt{'ywbr'}"))      {          if(confirm("$js_lt{'yhni'}. \\n$js_lt{'ywbr'}"))      {
             if (prev > 0) {              if (prev > 0) {
                 location.href = "$feedurl?previous=$previous"                  location.href = "$feedurl?previous=$previous"
             } else {              } else {
Line 1947  END Line 2283  END
     $r->print(<<END);      $r->print(<<END);
        <td>$lt{'disa'}</td>         <td>$lt{'disa'}</td>
        <td>$lt{$discdisp}</td>         <td>$lt{$discdisp}</td>
        <td><label><input type="checkbox" name="discdisp" onClick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"</label>         <td><label><input type="checkbox" name="discdisp" onclick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"</label>
            <br />             <br />
            <label><input type="checkbox" name="discdisp" onClick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"</label>             <label><input type="checkbox" name="discdisp" onclick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"</label>
        </td>         </td>
 END  END
     $r->print(&Apache::loncommon::end_data_table_row());      $r->print(&Apache::loncommon::end_data_table_row());
Line 1964  END Line 2300  END
     $r->print(<<END);      $r->print(<<END);
        <td>$lt{'dotm'}</td>         <td>$lt{'dotm'}</td>
        <td>$lt{$disctogg}</td>         <td>$lt{$disctogg}</td>
        <td><label><input type="checkbox" name="disctogg" onClick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</label></td>         <td><label><input type="checkbox" name="disctogg" onclick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</label></td>
 END  END
     my $save = &mt('Save');      my $save = &mt('Save');
     $r->print(&Apache::loncommon::end_data_table_row());      $r->print(&Apache::loncommon::end_data_table_row());
Line 1978  END Line 2314  END
 <input type="hidden" name="$dispchgB" value="" />  <input type="hidden" name="$dispchgB" value="" />
 <input type="hidden" name="$markchg" value="" />  <input type="hidden" name="$markchg" value="" />
 <input type="hidden" name="$toggchg" value="" />  <input type="hidden" name="$toggchg" value="" />
 <input type="button" name="sub" value="$save" onClick="javascript:setDisp()" />  <input type="button" name="sub" value="$save" onclick="javascript:setDisp()" />
 END  END
     if (exists($env{'form.group'})) {      if (exists($env{'form.group'})) {
         $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');          $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');
Line 2016  sub print_sortfilter_options { Line 2352  sub print_sortfilter_options {
         $ccrole = 'co';          $ccrole = 'co';
     }      }
     push(@courseroles,$ccrole);      push(@courseroles,$ccrole);
       
     if ($env{'request.course.sec'} !~ /^\s*$/) {  #Restrict section choice to current section       if ($env{'request.course.sec'} !~ /^\s*$/) {  #Restrict section choice to current section 
         @sections = ('all',$env{'request.course.sec'});          @sections = ('all',$env{'request.course.sec'});
         $numvisible = 2;          $numvisible = 2;
Line 2128  END Line 2464  END
 $start_page  $start_page
 <form name="modifyshown" method="post" action="/adm/feedback">  <form name="modifyshown" method="post" action="/adm/feedback">
 <b>$lt{'diso'}</b><br/> $lt{'prca'}  <b>$lt{'diso'}</b><br/> $lt{'prca'}
 <br /><br />  <br />
 <table border="0">  <table border="0">
  <tr>   <tr>
   <th>$lt{'soor'}</th>    <th>$lt{'soor'}</th>
Line 2193  $start_page Line 2529  $start_page
  </tr>   </tr>
 </table>  </table>
 <br />  <br />
 <br />  <input type="hidden" name="inhibitmenu" value="$env{'form.inhibitmenu'}" />
   <input type="hidden" name="modal" value="$env{'form.modal'}" />
 <input type="hidden" name="previous" value="$previous" />  <input type="hidden" name="previous" value="$previous" />
 <input type="hidden" name="applysort" value="$symb" />  <input type="hidden" name="applysort" value="$symb" />
 <input type="button" name="sub" value="$lt{'stor'}" onClick="verifyFilter()" />  <input type="button" name="sub" value="$lt{'stor'}" onclick="verifyFilter()" />
 END  END
     if (exists($env{'form.group'})) {      if (exists($env{'form.group'})) {
         $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');          $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');
Line 2219  sub print_showposters { Line 2556  sub print_showposters {
     $r->send_http_header;      $r->send_http_header;
   
     &Apache::lonenc::check_encrypt(\$symb);      &Apache::lonenc::check_encrypt(\$symb);
     my $crs='/'.$env{'request.course.id'};  
     if ($env{'request.course.sec'}) {  
         $crs.='_'.$env{'request.course.sec'};  
     }  
     $crs=~s/\_/\//g;  
     my $seeid;  
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};      my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
     my $group = $env{'form.group'};      my $group = $env{'form.group'};
     my $ressymb = &wrap_symb($symb);      my $ressymb = &wrap_symb($symb);
     if (($group ne '') &&      my $seehidden = &can_see_hidden('',$ressymb,$feedurl,$group,$cdom,$cnum);
         ($ressymb =~ m|^bulletin___ \d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|)) {  
         if (&check_group_priv($group,'dgp') eq 'ok') {  
             $seeid = 1;  
         }  
     } else {  
         $seeid=&Apache::lonnet::allowed('rin',$crs);  
     }  
     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},      my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                                          $cdom,$cnum);                                           $cdom,$cnum);
     my %namesort = ();      my %namesort = ();
Line 2252  sub print_showposters { Line 2576  sub print_showposters {
         for (my $idx=1;$idx<=$contrib{'version'};$idx++) {          for (my $idx=1;$idx<=$contrib{'version'};$idx++) {
             my $hidden=($contrib{'hidden'}=~/\.$idx\./);              my $hidden=($contrib{'hidden'}=~/\.$idx\./);
             my $deleted=($contrib{'deleted'}=~/\.$idx\./);              my $deleted=($contrib{'deleted'}=~/\.$idx\./);
             unless ((($hidden) && (!$seeid)) || ($deleted)) {              unless ((($hidden) && (!$seehidden)) || ($deleted)) {
                 if ((!$contrib{$idx.':anonymous'}) || (&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')))) {                  if ((!$contrib{$idx.':anonymous'}) || (&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')))) {
                     my %names = &Apache::lonnet::get('environment',['firstname','lastname'],$contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});                      my %names = &Apache::lonnet::get('environment',['firstname','lastname'],$contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
                     my $lastname = $names{'lastname'};                      my $lastname = $names{'lastname'};
Line 2277  sub print_showposters { Line 2601  sub print_showposters {
                     }                      }
                 }                  }
             }              }
         }          }       
     }      }
   
     my $start_page = &Apache::loncommon::start_page('Discussion options');      my $start_page = &Apache::loncommon::start_page('Discussion options');
     my $table_start =&Apache::loncommon::start_data_table();      my $table_start =&Apache::loncommon::start_data_table();
     $r->print(<<END);      $r->print(<<END);
 $start_page  $start_page
  <form name="pickpostersform" method="post">   <form name="pickpostersform" method="post" action="">
  <br />   <br />
     $table_start      $table_start
       <tr>        <tr>
Line 2318  END Line 2642  END
     $r->print(<<END);      $r->print(<<END);
 <br />  <br />
 <input type="hidden" name="sortposts" value="$sortposts" />  <input type="hidden" name="sortposts" value="$sortposts" />
   <input type="hidden" name="modal" value="$env{'form.modal'}" />
 <input type="hidden" name="userpick" value="$symb" />  <input type="hidden" name="userpick" value="$symb" />
 <input type="button" name="store" value="Display posts" onClick="javascript:document.pickpostersform.submit()" />  <input type="button" name="store" value="Display posts" onclick="javascript:document.pickpostersform.submit()" />
 </form>  </form>
 $end_page  $end_page
 END  END
Line 2391  sub fail_redirect { Line 2716  sub fail_redirect {
   my ($r,$feedurl) = @_;    my ($r,$feedurl) = @_;
   if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };    if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
   my %lt = &Apache::lonlocal::texthash(    my %lt = &Apache::lonlocal::texthash(
                  'sorr' => 'Sorry, no recipients  ...',                   'sorr' => 'Sorry, no recipients ...',
   );    );
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   $r->print(&Apache::loncommon::start_page('Feedback not sent',undef,    $r->print(&Apache::loncommon::start_page('Feedback not sent',undef,
Line 2399  sub fail_redirect { Line 2724  sub fail_redirect {
     'only_body' => 1,}));      'only_body' => 1,}));
   $r->print(<<ENDFAILREDIR);    $r->print(<<ENDFAILREDIR);
 <img align="right" src="$logo" />  <img align="right" src="$logo" />
 <b>$lt{'sorr'}</b>  <p class="LC_warning">$lt{'sorr'}</p>
 ENDFAILREDIR  ENDFAILREDIR
   $r->print(&Apache::loncommon::end_page());    $r->print(&Apache::loncommon::end_page());
 }  }
Line 2422  sub redirect_back { Line 2747  sub redirect_back {
   if ($previous > 0) {    if ($previous > 0) {
       $qrystr = 'previous='.$previous;        $qrystr = 'previous='.$previous;
       if ($feedurl =~ /\?register=1/) {        if ($feedurl =~ /\?register=1/) {
           $feedurl .= '&'.$qrystr;            $feedurl .= '&amp;'.$qrystr;
       } else {        } else {
           $feedurl .= '?'.$qrystr;            $feedurl .= '?'.$qrystr;
       }        }
Line 2431  sub redirect_back { Line 2756  sub redirect_back {
   if (defined($sort)) {    if (defined($sort)) {
       my $sortqry = 'sortposts='.$sort;        my $sortqry = 'sortposts='.$sort;
       if (($feedurl =~ /\?register=1/) || ($feedurl =~ /\?previous=/)) {        if (($feedurl =~ /\?register=1/) || ($feedurl =~ /\?previous=/)) {
           $feedurl .= '&'.$sortqry;            $feedurl .= '&amp;'.$sortqry;
       } else {        } else {
           $feedurl .= '?'.$sortqry;            $feedurl .= '?'.$sortqry;
       }        }
       $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';        $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';
       if (defined($numpicks)) {        if (defined($numpicks)) {
           my $userpickqry = 'totposters='.$numpicks;            my $userpickqry = 'totposters='.$numpicks;
           $feedurl .= '&'.$userpickqry;            $feedurl .= '&amp;'.$userpickqry;
           $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';            $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';
       } else {        } else {
           if (ref($sectionpick) eq 'ARRAY') {            if (ref($sectionpick) eq 'ARRAY') {
               $feedurl .= '&sectionpick=';                $feedurl .= '&amp;sectionpick=';
               $sectag .=  '<input type="hidden" name="sectionpick" value="';                $sectag .=  '<input type="hidden" name="sectionpick" value="';
               foreach my $sec (@{$sectionpick}) {                foreach my $sec (@{$sectionpick}) {
                   $feedurl .= $sec.',';                    $feedurl .= $sec.',';
Line 2452  sub redirect_back { Line 2777  sub redirect_back {
               $sectag =~ s/,$//;                $sectag =~ s/,$//;
               $sectag .= '" />';                $sectag .= '" />';
           } else {            } else {
               $feedurl .= '&sectionpick='.$sectionpick;                $feedurl .= '&amp;sectionpick='.$sectionpick;
               $sectag = '<input type="hidden" name="sectionpick" value="'.$sectionpick.'" />';                $sectag = '<input type="hidden" name="sectionpick" value="'.$sectionpick.'" />';
           }            }
           if (ref($grouppick) eq 'ARRAY') {            if (ref($grouppick) eq 'ARRAY') {
               $feedurl .= '&grouppick=';                $feedurl .= '&amp;grouppick=';
               $sectag .=  '<input type="hidden" name="grouppick" value="';                $sectag .=  '<input type="hidden" name="grouppick" value="';
               foreach my $grp (@{$grouppick}) {                foreach my $grp (@{$grouppick}) {
                   $feedurl .= $grp.',';                    $feedurl .= $grp.',';
Line 2466  sub redirect_back { Line 2791  sub redirect_back {
               $grptag =~ s/,$//;                $grptag =~ s/,$//;
               $grptag .= '" />';                $grptag .= '" />';
           } else {            } else {
               $feedurl .= '&grouppick='.$grouppick;                $feedurl .= '&amp;grouppick='.$grouppick;
               $grptag = '<input type="hidden" name="grouppick" value="'.$grouppick.'" />';                $grptag = '<input type="hidden" name="grouppick" value="'.$grouppick.'" />';
           }            }
           if (ref($rolefilter) eq 'ARRAY') {            if (ref($rolefilter) eq 'ARRAY') {
               $feedurl .= '&rolefilter=';                $feedurl .= '&amp;rolefilter=';
               $roletag .=  '<input type="hidden" name="rolefilter" value="';                $roletag .=  '<input type="hidden" name="rolefilter" value="';
               foreach my $role (@{$rolefilter}) {                foreach my $role (@{$rolefilter}) {
                   $feedurl .= $role.',';                    $feedurl .= $role.',';
Line 2480  sub redirect_back { Line 2805  sub redirect_back {
               $roletag =~ s/,$//;                $roletag =~ s/,$//;
               $roletag .= '" />';                $roletag .= '" />';
           } else {            } else {
               $feedurl .= '&rolefilter='.$rolefilter;                $feedurl .= '&amp;rolefilter='.$rolefilter;
               $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';                $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';
           }            }
           $feedurl .= '&statusfilter='.$statusfilter;            $feedurl .= '&amp;statusfilter='.$statusfilter;
           $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';            $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';
       }        }
   }    }
Line 2503  sub redirect_back { Line 2828  sub redirect_back {
   }     } 
   &Apache::lonenc::check_encrypt(\$feedurl);    &Apache::lonenc::check_encrypt(\$feedurl);
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   my %onload;    my %parms=('only_body'   => 1);
   if ($env{'environment.remote'} ne 'off') {    if ($env{'form.modal'}) {
       $onload{'onload'} =        $parms{'add_entries'}={'onLoad' => 'document.forms.reldt.submit()'};
   "if (window.name!='loncapaclient') { this.document.reldt.submit(); self.window.close(); }";    } else {
         $parms{'redirect'}=[0,$feedurl];
   }    }
   my $start_page=    my $start_page=
       &Apache::loncommon::start_page('Feedback sent',undef,        &Apache::loncommon::start_page('Feedback sent',undef,\%parms);
      {'redirect'    => [0,$feedurl],  
       'only_body'   => 1,  
       'add_entries' => \%onload});  
   my $end_page = &Apache::loncommon::end_page();    my $end_page = &Apache::loncommon::end_page();
     my $windowname = 'loncapaclient';
     if ($env{'request.lti.login'}) {
        $windowname .= 'lti';
     }
   $r->print(<<ENDREDIR);    $r->print(<<ENDREDIR);
 $start_page  $start_page
 <img align="right" src="$logo" />  <img align="right" src="$logo" />
Line 2522  $typestyle Line 2849  $typestyle
 $blog  $blog
 $toolarge  $toolarge
 <font color="red">$status</font>  <font color="red">$status</font>
 <form name="reldt" action="$feedurl" target="loncapaclient">  <form name="reldt" action="$feedurl" target="$windowname">
 $prevtag  $prevtag
 $sorttag  $sorttag
 $statustag  $statustag
Line 2538  ENDREDIR Line 2865  ENDREDIR
   
 sub no_redirect_back {  sub no_redirect_back {
   my ($r,$feedurl) = @_;    my ($r,$feedurl) = @_;
   my $nofeed=&mt('Sorry, no feedback possible on this resource  ...');    my $nofeed=&mt('Sorry, no feedback possible on this resource ...');
     
   my %onload;    my %onload;
   if ($env{'environment.remote'} ne 'off') {  
       $onload{'onload'} =   
   "if (window.name!='loncapaclient') { self.window.close(); }";  
   }  
   
   my %body_options = ('only_body'   => 1,    my %body_options = ('only_body'   => 1,
       'bgcolor'     => '#FFFFFF',        'bgcolor'     => '#FFFFFF',
       'add_entries' => \%onload,);        'add_entries' => \%onload,);
   
   if ($feedurl !~ m{^/adm/feedback}) {     if ($feedurl !~ m{^/adm/feedback}) { 
       $body_options{'rediect'} = [2,$feedurl];        $body_options{'redirect'} = [2,$feedurl];
   }    }
   my $start_page=    my $start_page=
       &Apache::loncommon::start_page('Feedback not sent',undef,        &Apache::loncommon::start_page('Feedback not sent',undef,
Line 2571  ENDNOREDIRTWO Line 2894  ENDNOREDIRTWO
 }  }
   
 sub screen_header {  sub screen_header {
     my ($feedurl,$symb) = @_;      my ($feedurl,$symb,$group) = @_;
     my $crscontent = &mt('Question/Comment/Feedback about course content');      my $crscontent = &mt('Question/Comment/Feedback about course content');
     my $crspolicy = &mt('Question/Comment/Feedback about course policy');      my $crspolicy = &mt('Question/Comment/Feedback about course policy');
     my $contribdisc = &mt('Contribution to course discussion of resource');      my $contribdisc = &mt('Contribution to course discussion of resource');
Line 2593  sub screen_header { Line 2916  sub screen_header {
     unless (($env{'form.replydisc'}) || ($env{'form.editdisc'})) {      unless (($env{'form.replydisc'}) || ($env{'form.editdisc'})) {
  if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/) && ($env{'user.adv'})) {   if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/) && ($env{'user.adv'})) {
     $msgoptions=       $msgoptions= 
  '<p><label><input type="radio" name="discuss" value="author" /> '.   '<label><input type="radio" name="discuss" value="author" /> '.
  &mt('Feedback to resource author').'</label></p>';   &mt('Feedback to resource author').'</label><br />';
  }   }
         my %optionhash=();          my %optionhash=();
         foreach my $type ('question','comment','policy') {          foreach my $type ('question','comment','policy') {
Line 2602  sub screen_header { Line 2925  sub screen_header {
  }   }
  if (&feedback_available(1)) {   if (&feedback_available(1)) {
     $msgoptions.=      $msgoptions.=
  '<p><label><input type="radio" name="discuss" value="question" /> '.   '<label><input type="radio" name="discuss" value="question" /> '.
  ($optionhash{'question'}?$optionhash{'question'}:&mt('Question about resource content')).'</label></p>';   ($optionhash{'question'}?$optionhash{'question'}:&mt('Question about resource content')).'</label><br />';
  }   }
  if (&feedback_available(0,1)) {   if (&feedback_available(0,1)) {
     $msgoptions.=      $msgoptions.=
  '<p><label><input type="radio" name="discuss" value="course" /> '.   '<label><input type="radio" name="discuss" value="course" /> '.
  ($optionhash{'comment'}?$optionhash{'comment'}:$crscontent).   ($optionhash{'comment'}?$optionhash{'comment'}:$crscontent).
  '</label></p>';   '</label><br />';
  }   }
  if (&feedback_available(0,0,1)) {   if (&feedback_available(0,0,1)) {
     $msgoptions.=      $msgoptions.=
  '<p><label><input type="radio" name="discuss" value="policy" /> '.   '<label><input type="radio" name="discuss" value="policy" /> '.
  ($optionhash{'policy'}?$optionhash{'policy'}:$crspolicy).   ($optionhash{'policy'}?$optionhash{'policy'}:$crspolicy).
  '</label></p>';   '</label><br />';
  }   }
     }      }
     if (($env{'request.course.id'}) && (!$env{'form.sendmessageonly'})) {      if (($env{'request.course.id'}) && (!$env{'form.sendmessageonly'})) {
         my ($blocked,$blocktext) = &Apache::loncommon::blocking_status('boards');          my ($blocked,$blocktext) = &Apache::loncommon::blocking_status('boards');
         if (!$blocked && &discussion_open(undef,$symb) &&           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     &Apache::lonnet::allowed('pch',          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
      $env{'request.course.id'}.          my $realsymb = &get_realsymb($symb);
      ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {          if (!$blocked && &discussion_open(undef,$realsymb) && 
     $discussoptions='<label><input type="radio" name="discuss" value="nonanon" checked="checked" /> '.      (&Apache::lonnet::allowed('pch',
                 $contribdisc.        $env{'request.course.id'}.
                 '</label><br /><label><input type="radio" name="discuss" value="anon" /> '.        ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')) || 
                 $anoncontrib.              (($group ne '') && ($symb =~ m{^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$}) && (&check_group_priv($group,'pgd') eq 'ok')))) {
                 ' <i>('.$namevis.')</i></label> '.              $discussoptions='<label><input type="radio" name="discuss" value="nonanon" checked="checked" /> '.
                               $contribdisc.
  '<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';                              '</label>'; 
               if (&Apache::lonnet::allowed('pac',$env{'request.course.id'}.
                  ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
           $discussoptions .= '<br /><label><input type="radio" name="discuss" value="anon" /> '.
                      $anoncontrib.
                      ' <i>('.$namevis.')</i></label> '.
                      '<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';
               }
             my $blockblog = &Apache::loncommon::blocking_status('blogs');              my $blockblog = &Apache::loncommon::blocking_status('blogs');
             if (!$blockblog) {              if (!$blockblog) {
                 $discussoptions.= &add_blog_checkbox($crstype);                  $discussoptions.= &add_blog_checkbox($crstype);
Line 2638  sub screen_header { Line 2968  sub screen_header {
         }          }
     }      }
     if ($msgoptions) {      if ($msgoptions) {
         $msgoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/res/adm/pages/com.png').'" />'          $msgoptions='<tr><th><img src="'.&Apache::loncommon::lonhttpdurl('/res/adm/pages/feedback.png').'" />'
                    .' '.&mt('Send Feedback').'</h2><p>'.&Apache::lonhtmlcommon::coursepreflink(&mt('Feedback Settings'),'feedback').'</p>'                     .'<br />'.&mt('Send Feedback').'<br />'.&Apache::lonhtmlcommon::coursepreflink(&mt('Feedback Settings'),'feedback').'</th>'.
                    .$msgoptions;                     '<td>'.$msgoptions.'</td></tr>';
     }      }
     if ($discussoptions) {       if ($discussoptions) { 
  $discussoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" />'   $discussoptions='<tr><th><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" alt="" />'
                         .' '.&mt('Discussion Contributions').'</h2><p>'.&Apache::lonhtmlcommon::coursepreflink(&mt('Discussion Settings'),'discussion').'</p>'                          .'<br />'.&mt('Discussion Contributions').'<br />'.&Apache::lonhtmlcommon::coursepreflink(&mt('Discussion Settings'),'discussion').'</th>'.
                         .$discussoptions;                          '<td>'.$discussoptions.'</td></tr>';
     }      }
     return $msgoptions.$discussoptions;      return  &Apache::loncommon::start_data_table().$msgoptions.$discussoptions.&Apache::loncommon::end_data_table();
 }  }
   
 sub resource_output {  sub resource_output {
Line 2664  sub resource_output { Line 2994  sub resource_output {
 }  }
   
 sub clear_out_html {  sub clear_out_html {
   my ($message,$override,$ignore_htmlarea)=@_;    my ($message,$override)=@_;
   if (!$ignore_htmlarea  
       && !&Apache::lonhtmlcommon::htmlareablocked()) { return $message; }  
 # Always allow the <m>-tag  # Always allow the <m>-tag
   my %html=(M=>1);    my %html=(M=>1);
 # Check if more is allowed  # Check if more is allowed
Line 2675  sub clear_out_html { Line 3003  sub clear_out_html {
       ($override)) {        ($override)) {
       # allows <B> <I> <P> <A> <LI> <OL> <UL> <EM> <BR> <TT> <STRONG>         # allows <B> <I> <P> <A> <LI> <OL> <UL> <EM> <BR> <TT> <STRONG> 
       # <BLOCKQUOTE> <DIV .*> <DIV> <IMG> <M> <SPAN> <H1> <H2> <H3> <H4> <SUB>        # <BLOCKQUOTE> <DIV .*> <DIV> <IMG> <M> <SPAN> <H1> <H2> <H3> <H4> <SUB>
       # <SUP>        # <SUP> <TABLE> <TR> <TD> <TH> <TBODY>
       %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1,        %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1,
      BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, DIV=>1, IMG=>1,       BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, PRE=>1, DIV=>1, IMG=>1,
      M=>1, ALGEBRA=>1, SUB=>1, SUP=>1, SPAN=>1,        M=>1, CHEM=>1, ALGEBRA=>1, SUB=>1, SUP=>1, SPAN=>1,  
      H1=>1, H2=>1, H3=>1, H4=>1, H5=>1);       H1=>1, H2=>1, H3=>1, H4=>1, H5=>1, H6=>1, 
        TABLE=>1, TR=>1, TD=>1, TH=>1, TBODY=>1);
   }    }
 # Do the substitution of everything that is not explicitly allowed  # Do the substitution of everything that is not explicitly allowed
   $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/    $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/
Line 2696  sub assemble_email { Line 3025  sub assemble_email {
              'orig' => 'Original screen output (if applicable)',               'orig' => 'Original screen output (if applicable)',
              'corr' => 'Correct Answer(s) (if applicable)',               'corr' => 'Correct Answer(s) (if applicable)',
   );    );
     if (&Apache::loncommon::course_type() eq 'Community') {
         $lt{'prev'} = &mt('Previous attempts of member (if applicable)');
     }
   my $email=<<"ENDEMAIL";    my $email=<<"ENDEMAIL";
 $message  $message
 ENDEMAIL  ENDEMAIL
Line 2745  sub send_msg { Line 3077  sub send_msg {
  }   }
     }      }
   
   # Records of number of feedback messages are kept under the "symb" called "_feedback"
     my %record=&Apache::lonnet::restore('_feedback');  # There are two entries within the framework of a course:
     my ($temp)=keys(%record);  # - the URLs for which feedback was provided
     unless ($temp=~/^error\:/) {  # - the total number of contributions
  my %newrecord=();      if ($sendsomething) {
  $newrecord{'resource'}=$feedurl;          my %record=&getfeedbackrecords();
  $newrecord{'subnumber'}=$record{'subnumber'}+1;          my ($temp)=keys(%record);
  unless (&Apache::lonnet::cstore(\%newrecord,'_feedback') eq 'ok') {          unless ($temp=~/^error\:/) {
     $status.='<br />'.&mt('Not registered').'<br />';      my %newrecord=();
  }      $newrecord{'resource'}=$feedurl;
       $newrecord{'subnumber'}=$record{'subnumber'}+1;
       unless (&Apache::lonnet::cstore(\%newrecord,'_feedback') eq 'ok') {
           $status.='<br />'.&mt('Not registered').'<br />';
       }
           }
     }      }
       
     return ($status,$sendsomething);      return ($status,$sendsomething);
 }  }
   
   # Routine to get the complete feedback records
   
   sub getfeedbackrecords {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&Apache::lonnet::restore('_feedback',$course,$udom,$uname);
       return %record;
   }
   
   # Routine to get feedback statistics
   
   sub getfeedbackstats {
       my %record=&getfeedbackrecords(@_);
       return ($record{'subnumber'},$record{'points'},$record{'totallikes'});
   }
   
   # Store feedback credit
   
   sub storefeedbackpoints {
       my ($points,$uname,$udom,$course)=@_;
       unless ($points) { $points=0; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=('grader_user'   => $env{'user.name'},
                   'grader_domain' => $env{'user.domain'},
                   'points' => $points);
       return &Apache::lonnet::cstore(\%record,'_feedback',$course,$udom,$uname);
   }
   
   # Store feedback "likes"
   
   sub storefeedbacklikes {
       my ($likes,$uname,$udom,$course)=@_;
       unless ($likes) { $likes=0; }
       if ($likes>0) { $likes=1; }
       if ($likes<0) { $likes=-1; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&getfeedbackrecords($uname,$udom,$course);
       my $totallikes=$record{'totallikes'};
       $totallikes+=$likes;
       my %newrecord=('likes_user'   => $env{'user.name'},
                      'likes_domain' => $env{'user.domain'},
                      'likes' => $likes,
                      'totallikes' => $totallikes);
       return &Apache::lonnet::cstore(\%newrecord,'_feedback',$course,$udom,$uname);
   }
   
   
 sub adddiscuss {  sub adddiscuss {
     my ($symb,$email,$anon,$attachmenturl,$subject)=@_;      my ($symb,$email,$anon,$attachmenturl,$subject,$group)=@_;
     my $status='';      my $status='';
     my $realsymb;      my $realsymb = &get_realsymb($symb);
     if ($symb=~/^bulletin___/) {      my ($cnum,$cdom);
  my $filename=(&Apache::lonnet::decode_symb($symb))[2];      if ($env{'request.course.id'}) {
  $filename=~s|^adm/wrapper/||;          $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
  $realsymb=&Apache::lonnet::symbread($filename);          $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
     }      }
     if (&discussion_open(undef,$realsymb) &&      if (&discussion_open(undef,$realsymb) &&
  &Apache::lonnet::allowed('pch',$env{'request.course.id'}.   (&Apache::lonnet::allowed('pch',$env{'request.course.id'}.
         ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {           ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')) || 
            (($group ne '') && (&check_group_priv($group,'pgd') eq 'ok') && 
            ($symb =~ m{^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$})))) {
   
     my %contrib=('message'      => $email,      my %contrib=('message'      => $email,
                  'sendername'   => $env{'user.name'},                   'sendername'   => $env{'user.name'},
Line 2851  sub adddiscuss { Line 3242  sub adddiscuss {
                      $env{'course.'.$env{'request.course.id'}.'.domain'},                       $env{'course.'.$env{'request.course.id'}.'.domain'},
      $env{'course.'.$env{'request.course.id'}.'.num'});       $env{'course.'.$env{'request.course.id'}.'.num'});
     }      }
     my %record=&Apache::lonnet::restore('_discussion');      my %record=&getdiscussionrecords();
     my ($temp)=keys(%record);      my ($temp)=keys(%record);
     unless ($temp=~/^error\:/) {      unless ($temp=~/^error\:/) {
        my %newrecord=();         my %newrecord=();
Line 2859  sub adddiscuss { Line 3250  sub adddiscuss {
        $newrecord{'subnumber'}=$record{'subnumber'}+1;         $newrecord{'subnumber'}=$record{'subnumber'}+1;
        $status.='<br />'.&mt('Registering').': '.         $status.='<br />'.&mt('Registering').': '.
                &Apache::lonnet::cstore(\%newrecord,'_discussion');                 &Apache::lonnet::cstore(\%newrecord,'_discussion');
          &updatekarma();
     }      }
     } else {      } else {
  $status.='Failed.';   $status.='Failed.';
Line 2866  sub adddiscuss { Line 3258  sub adddiscuss {
     return $status.'<br />';         return $status.'<br />';   
 }  }
   
   
   # Routine to get the complete discussion records
   
   sub getdiscussionrecords {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&Apache::lonnet::restore('_discussion',$course,$udom,$uname);
       return %record;
   }
   
   # Routine to get discussion statistics
   
   sub getdiscussionstats {
       my %record=&getdiscussionrecords(@_);
       my $totalvotes = $record{'totallikes'} + $record{'totalunlikes'};
       return ($record{'subnumber'},$record{'points'},$record{'totallikes'},$totalvotes);
   }
   
   # Calculate discussion karma
   
   sub calcdiscussionkarma {    
       my ($subs,$pts,$likes,$votes)=&getdiscussionstats(@_);
       my $karma=0;
       if ($votes>0) {
           $karma=int(.1+5.*(1.-exp(-$subs/10.))*$likes/$votes);
           if ($karma<0) { $karma=0; }
           if ($karma>5) { $karma=5; }
       }
       return $karma;
   }
   
   # Update karma
   
   sub updatekarma {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my $karma=&calcdiscussionkarma($uname,$udom,$course);
       &Apache::lonnet::cstore({ 'karma' => $karma },'_discussion',$course,$udom,$uname);
       &Apache::lonnet::do_cache_new('karma',$uname.':'.$udom.':'.$course,$karma,3600);
       return $karma;
   }
   
   # Retrieve karma
   
   sub userkarma {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my $hashkey=$uname.':'.$udom.':'.$course;
       my ($karma,$cached)=&Apache::lonnet::is_cached_new('karma',$hashkey);
       if ($cached) {
           return $karma;
       }
       my %userdisc=&getdiscussionrecords($uname,$udom,$course);
       $karma=$userdisc{'karma'};
       &Apache::lonnet::do_cache_new('karma',$hashkey,$karma,3600);
       return $karma;
   }
   
   # Store discussion credit
   
   sub storediscussionpoints {
       my ($points,$uname,$udom,$course)=@_;
       unless ($points) { $points=0; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=('grader_user'   => $env{'user.name'},
                   'grader_domain' => $env{'user.domain'},
                   'points' => $points);
       return &Apache::lonnet::cstore(\%record,'_discussion',$course,$udom,$uname);
   }
   
   # Store discussion "likes"
   
   sub storediscussionlikes {
       my ($chglikes,$chgunlikes,$uname,$udom,$course,$context)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&getdiscussionrecords($uname,$udom,$course);
       my $totallikes=$record{'totallikes'};
       my $totalunlikes=$record{'totalunlikes'};
       $totallikes += $chglikes;
       $totalunlikes += $chgunlikes;
       my %newrecord=('likes_user'   => $env{'user.name'},
                      'likes_domain' => $env{'user.domain'},
                      'totallikes'   => $totallikes,
                      'totalunlikes' => $totalunlikes,
                      'context'      => $context);
       my $status=&Apache::lonnet::cstore(\%newrecord,'_discussion',$course,$udom,$uname);
       if ($status eq 'ok') {
           &updatekarma($uname,$udom,$course);
       }
       return $status;
   }
   
 sub get_discussion_info {  sub get_discussion_info {
     my ($idx,%contrib) = @_;      my ($idx,%contrib) = @_;
     my $changelast = 0;      my $changelast = 0;
Line 2922  sub show_preview { Line 3416  sub show_preview {
     &newline_to_br(\$message);      &newline_to_br(\$message);
     $message=&Apache::lonspeller::markeduptext($message);      $message=&Apache::lonspeller::markeduptext($message);
     $message=&Apache::lontexconvert::msgtexconverted($message);      $message=&Apache::lontexconvert::msgtexconverted($message);
     my $subject=&clear_out_html($env{'form.subject'},undef,1);      my $subject=&clear_out_html($env{'form.subject'});
     $subject=~s/\n/\<br \/\>/g;      $subject=~s/\n/\<br \/\>/g;
     $subject=&Apache::lontexconvert::msgtexconverted($subject);      $subject=&Apache::lontexconvert::msgtexconverted($subject);
   
Line 2945  sub show_preview { Line 3439  sub show_preview {
 sub contains_block_html {  sub contains_block_html {
     my ($message)=@_;      my ($message)=@_;
     return ($message =~ m{      return ($message =~ m{
         <(br|h1|h2|h3|h4|h5|h6|p|ol|ul|table|pre|address|blockquote|center|div)          <(br|h1|h2|h3|h4|h5|h6|p|ol|ul|table|pre|address|blockquote|center|div) 
           \s*    \s*
          (\w+\=['"]\w+['"])*   (\w+\=['"]\w+['"])*
           \s*    \s*
         (   (
           \s*/>|    \s*/>|
           >.*</\1\s*>    >.*</\1\s*>
         )}xs   )}xs 
     );      );
 }  }
   
   sub tidy_html {
    my ($message)=@_;
   # my $tidy = HTML::Tidy::libXML->new();
   # my $xhtml = $tidy->clean($message, 'utf-8', 1);
   # $xhtml =~ m/<body>(.*)<\/body>/is;
   # my $clean = $1;
   # # remove any empty block-level tags
   # $clean =~ s/<(table|p|div|tbody|blockquote|m|pre|algebra|center|ol|ul|span|h1|h2|h3|h4|h5|h6)\s*\/>//i;
   # $message=$clean;
    return $message;
   }
   
 sub newline_to_br {  sub newline_to_br {
     my ($message)=@_;      my ($message)=@_;
     my $newmessage;      my $newmessage;
Line 2988  sub generate_preview_button { Line 3494  sub generate_preview_button {
 <input type="hidden" name="subject" />  <input type="hidden" name="subject" />
 <input type="hidden" name="comment" />  <input type="hidden" name="comment" />
 <input type="button" value="$pre"  <input type="button" value="$pre"
 onClick="if (typeof(document.$formname.onsubmit)=='function') {document.$formname.onsubmit();};this.form.comment.value=document.$formname.$fieldname.value;this.form.subject.value=document.$formname.subject.value;this.form.submit();" />  onclick="if (typeof(document.$formname.onsubmit)=='function') {document.$formname.onsubmit();};this.form.comment.value=document.$formname.$fieldname.value;this.form.subject.value=document.$formname.subject.value;this.form.submit();" />
 </form>  </form>
 ENDPREVIEW  ENDPREVIEW
 }  }
Line 2999  sub modify_attachments { Line 3505  sub modify_attachments {
   
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                'subj' => 'Subject',                 'subj' => 'Subject',
                'thfo' => 'The following attachments were part of the most recent saved version of this posting.',  
                'chth' => 'Check the checkboxes for any you wish to remove.',                 'chth' => 'Check the checkboxes for any you wish to remove.',
                'thef' => 'The following attachments have been uploaded for inclusion with this posting.',                 'thef' => 'The following attachments have been uploaded for inclusion with this posting.',
                'adda' => 'Add a new attachment to this post.',                 'adda' => 'Add a new attachment to this post',
                'stch' => 'Save Changes',                 'stch' => 'Save Changes',
                  'clic' => 'Add/remove attachments',
              );               );
     my $js = <<END;      my $js = <<END;
 <script type="text/javascript">  <script type="text/javascript">
Line 3012  sub modify_attachments { Line 3518  sub modify_attachments {
    document.modattachments.submit();     document.modattachments.submit();
  }   }
 </script>   </script> 
   <script type="text/javascript" src="/res/adm/includes/file_upload.js"></script>
 END  END
   
       # Breadcrumbs
       my $brcrum = [{'href' => '',
                      'text' => 'Discussion Post Attachments'}];
       my %parms=('only_body' => 1);
       if ($env{'form.modal'} ne 'yes') { $parms{'bread_crumbs'} = $brcrum; }
   
     my $start_page =       my $start_page = 
  &Apache::loncommon::start_page('Discussion Post Attachments',$js);   &Apache::loncommon::start_page('Discussion Post Attachments',$js,\%parms);
   
     my $orig_subject = &unescape($env{'form.subject'});      my $orig_subject = &unescape($env{'form.subject'});
     my $subject=&clear_out_html($orig_subject,undef,1);      my $subject=&clear_out_html($orig_subject);
     $subject=~s/\n/\<br \/\>/g;      $subject=~s/\n/\<br \/\>/g;
     $subject=&Apache::lontexconvert::msgtexconverted($subject);      $subject=&Apache::lontexconvert::msgtexconverted($subject);
     my $timestamp=$env{'form.timestamp'};      my $timestamp=$env{'form.timestamp'};
Line 3039  END Line 3552  END
 $start_page  $start_page
 $toolarge  $toolarge
 <form name="modattachments" method="post" enctype="multipart/form-data" action="/adm/feedback?attach=$symb">  <form name="modattachments" method="post" enctype="multipart/form-data" action="/adm/feedback?attach=$symb">
  <br />  
  <table class="LC_data_table">   <h1>$lt{'clic'}</h1>
   <tr>  
    <td colspan="2">  
     <b>Subject:</b> <b>$subject</b><br /><br />  
 END  END
     if ($idx) {      $r->print(&Apache::lonhtmlcommon::start_pick_box());
         if ($attachmenturls) {      $r->print(&Apache::lonhtmlcommon::row_title(&mt('Subject')));
             my @currold = keys(%currattach);      $r->print('<b>'.$subject.'</b>');
             if (@currold > 0) {      $r->print(&Apache::lonhtmlcommon::row_closure());
                 $r->print($lt{'thfo'}.'<br />'.$lt{'chth'}.'<br />'."\n");        $r->print(&Apache::lonhtmlcommon::row_title($lt{'adda'}));
                 foreach my $id (@currold) {      $r->print('<input type="file" name="addnewattach" class="LC_flUpload" />'
                     my $attachurl = &HTML::Entities::decode($attachments{$id}{'filename'});           .'<input type="hidden" id="LC_free_space" value="131072" />'
                     $attachurl =~ m#/([^/]+)$#;          .'<input type="button" name="upload" value="Upload" '
                     $r->print('<label><input type="checkbox" name="deloldattach" value="'.$id.'" />&nbsp;'.$1.'</label><br />'."\n");          .'onclick="this.form.submit()" />  '.$attachmaxtext);
       if(($idx)||(ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)){
           $r->print(&Apache::lonhtmlcommon::row_closure());
           $r->print(&Apache::lonhtmlcommon::row_title(&mt('Attachments')));
           if ($idx) {
               if ($attachmenturls) {
                   my @currold = keys(%currattach);
                   if (@currold > 0) {
                       $r->print($lt{'thfo'}.'<br />'.$lt{'chth'}.'<br />'."\n");
                       foreach my $id (@currold) {
                           my $attachurl = &HTML::Entities::decode($attachments{$id}{'filename'});
                           $attachurl =~ m#/([^/]+)$#;
                           $r->print('<label><input type="checkbox" name="deloldattach" value="'.$id.'" />&nbsp;'.$1.'</label><br />'."\n");
                       }
                       $r->print("<br />");
                 }                  }
                 $r->print("<br />");  
             }              }
         }          }
     }          if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) {
     if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) {              $r->print($lt{'chth'}.'<br />'."\n");
         $r->print($lt{'thef'}.'<br />'.$lt{'chth'}.'<br />'."\n");              foreach my $attach (@{$currnewattach}) {
         foreach my $attach (@{$currnewattach}) {                  $attach =~ m#/([^/]+)$#;
             $attach =~ m#/([^/]+)$#;                  $r->print('<label><input type="checkbox" name="delnewattach" value="'.$attach.'" />&nbsp;'.$1.'</label><br />'."\n");
             $r->print('<label><input type="checkbox" name="delnewattach" value="'.$attach.'" />&nbsp;'.$1.'</label><br />'."\n");              }
         }          }
         $r->print("<br />");   
     }      }
       $r->print(&Apache::lonhtmlcommon::row_closure(1));
       $r->print(&Apache::lonhtmlcommon::end_pick_box());
     $r->print(<<END);      $r->print(<<END);
    </td></tr>  
    <tr>  
     <td>  
    $lt{'adda'}</td><td><input type="file" name="addnewattach" /><input type="button" name="upload" value="Upload" onClick="this.form.submit()" />      
    </td>  
   </tr>  
   <tr>  
    <td colspan="2">$attachmaxtext</td>  
   </tr>  
  </table>  
 <input type="hidden" name="subject" value="$env{'form.subject'}" />  <input type="hidden" name="subject" value="$env{'form.subject'}" />
 <input type="hidden" name="comment" value="$env{'form.comment'}" />  <input type="hidden" name="comment" value="$env{'form.comment'}" />
 <input type="hidden" name="timestamp" value="$env{'form.timestamp'}" />  <input type="hidden" name="timestamp" value="$env{'form.timestamp'}" />
Line 3094  END Line 3608  END
         $r->print('<input type="hidden" name="deloldattach" value="'.$item.'" />'."\n");          $r->print('<input type="hidden" name="deloldattach" value="'.$item.'" />'."\n");
     }      }
     $r->print(<<END);      $r->print(<<END);
  <input type="button" name="rtntoedit" value="$lt{'stch'}" onClick="setAction()" />   <input type="button" name="rtntoedit" value="$lt{'stch'}" onclick="setAction()" />
 </form>  </form>
 $end_page  $end_page
 END  END
Line 3135  sub generate_attachments_button { Line 3649  sub generate_attachments_button {
     my $origpage = $ENV{'REQUEST_URI'};      my $origpage = $ENV{'REQUEST_URI'};
     my $att=$attachnum.' '.&mt("attachments");      my $att=$attachnum.' '.&mt("attachments");
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                 'clic' => 'Click to add/remove attachments',                  'clic' => 'Add/remove attachments',
     );       ); 
     my $response = (<<END);      my $response = (<<END);
 <br />  <br />
 <form name="attachment" action="/adm/feedback?attach=$ressymb" method="post">  <form name="attachment" action="/adm/feedback?attach=$ressymb" method="post">
 $lt{'clic'}:&nbsp;<input type="button" value="$att"  <input type="button" value="$lt{'clic'}"
 onClick="if (typeof(document.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=escape(document.mailform.comment.value);this.form.subject.value=escape(document.mailform.subject.value);  onclick="if (typeof(document.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=escape(document.mailform.comment.value);this.form.subject.value=escape(document.mailform.subject.value);
 END  END
     if (!$blockblog) {      if (!$blockblog) {
         $response .= 'setblogvalue();';          $response .= 'setblogvalue();';
Line 3357  sub sort_filter_names { Line 3871  sub sort_filter_names {
     }      }
     if (ref($status_types) eq 'HASH') {      if (ref($status_types) eq 'HASH') {
         %{$status_types} = (          %{$status_types} = (
                       all     => 'Roles of any status',                       all     => 'Roles of any status',
                       Active  => 'Only active roles',                       Active  => 'Only active roles',
                       Expired => 'Only past roles',                       Expired => 'Only past roles',
                       Future  => 'Only future roles',                       Future  => 'Only future roles',
                     );                     );
     }      }
 }  }
     
 sub handler {  sub handler {
   my $r = shift;    my $r = shift;
   if ($r->header_only) {    if ($r->header_only) {
Line 3376  sub handler { Line 3890  sub handler {
 # --------------------------- Get query string for limited number of parameters  # --------------------------- Get query string for limited number of parameters
   
   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
          ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','groupick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export','sendmessageonly','group','ref']);           ['like','unlike','modal','hide','unhide','deldisc','undeleteall','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','groupick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export','sendmessageonly','group','ref']);
   my $group = $env{'form.group'};    my $group = $env{'form.group'};
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
   
   my %attachmax = (    my %attachmax = (
                     text => &mt('(128 KB max size)'),                      text => &mt('(128 KB max size)'),
                     num  => 131072,                      num  => 131072,
                   );                    );
   if ($env{'form.editdisc'}) {    if ($env{'form.editdisc'}) {
       if (!(&editing_allowed($env{'form.editdisc'},$env{'form.group'}))) {        if (!(&editing_allowed($env{'form.editdisc'},$group))) {
           my $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];            my $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
           my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);            my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
           my $feedurl=&Apache::lonnet::clutter($url);            my $feedurl=&Apache::lonnet::clutter($url);
Line 3424  sub handler { Line 3941  sub handler {
       &Apache::loncommon::no_cache($r);        &Apache::loncommon::no_cache($r);
       $r->send_http_header;        $r->send_http_header;
   
       $r->print(&Apache::loncommon::start_page('Discussion Post Versions'));        # Breadcrumbs
         my $brcrum = [{'href' => '',
                        'text' => 'Discussion Post Versions'}];
         
         my %parms=();
         if ($env{'form.modal'} ne 'yes') { $parms{'bread_crumbs'} = $brcrum; }
   
         $r->print(&Apache::loncommon::start_page('Discussion Post Versions',undef,\%parms));
   
       my $crs='/'.$env{'request.course.id'};  
       if ($env{'request.course.sec'}) {  
           $crs.='_'.$env{'request.course.sec'};  
       }  
       $crs=~s|_|/|g;  
       my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};  
       my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};  
       my ($symb,$idx)=split(/\:\:\:/,$env{'form.allversions'});        my ($symb,$idx)=split(/\:\:\:/,$env{'form.allversions'});
       ($symb)=&get_feedurl_and_clean_symb($symb);        ($symb, my $feedurl)=&get_feedurl_and_clean_symb($symb);
       my $ressymb = &wrap_symb($symb);        my $ressymb = &wrap_symb($symb);
       my $group = $env{'form.group'};  
       my $seeid;        my $seeid;
       if (($group ne '') && (($ressymb =~ m|^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|))) {        if (&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
           if (&check_group_priv($group,'dgp') eq 'ok') {            $seeid = 1;
               $seeid = 1;  
           }  
       } else {  
           $seeid = &Apache::lonnet::allowed('rin',$crs);  
       }        }
         my $seehidden = &can_see_hidden('',$ressymb,$feedurl,$group,$cdom,$cnum);
       if ($idx > 0) {        if ($idx > 0) {
           my %messages = ();            my %messages = ();
           my %subjects = ();            my %subjects = ();
           my %attachmsgs = ();            my %attachmsgs = ();
           my %allattachments = ();            my %allattachments = ();
           my %imsfiles = ();            my %imsfiles = ();
           my ($screenname,$plainname);            my ($screenname,$plainname,$showaboutme);
           my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},            my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                            $env{'course.'.$env{'request.course.id'}.'.domain'},                                                 $cdom,$cnum);
                            $env{'course.'.$env{'request.course.id'}.'.num'});            $r->print(&get_post_contents(\%contrib,$idx,$seeid,$seehidden,'allversions',\%messages,\%subjects,\%allattachments,\%attachmsgs,\%imsfiles,\$screenname,\$plainname,\$showaboutme));
           $r->print(&get_post_contents(\%contrib,$idx,$seeid,'allversions',\%messages,\%subjects,\%allattachments,\%attachmsgs,\%imsfiles,\$screenname,\$plainname));  
       }        }
       $r->print(&Apache::loncommon::end_page());        $r->print(&Apache::loncommon::end_page());
       return OK;        return OK;
Line 3507  sub handler { Line 4019  sub handler {
       my $feedurl = '/adm/navmaps';        my $feedurl = '/adm/navmaps';
       if ($env{'form.navurl'}) { $feedurl .= '?'.$env{'form.navurl'}; }        if ($env{'form.navurl'}) { $feedurl .= '?'.$env{'form.navurl'}; }
       my %lt = &Apache::lonlocal::texthash(        my %lt = &Apache::lonlocal::texthash(
           'mnpa' => 'Marked "New" posts as read in a total of',  
           'robb' => 'resources/bulletin boards.',  
           'twnp' => 'There are currently no resources or discussion boards with unread discussion postings.'            'twnp' => 'There are currently no resources or discussion boards with unread discussion postings.'
       );               );       
       foreach my $res (@resources) {        foreach my $res (@resources) {
Line 3517  sub handler { Line 4027  sub handler {
           my $lastkey = $ressymb.'_lastread';            my $lastkey = $ressymb.'_lastread';
           $discinfo{$lastkey} = $env{'form.navtime'};            $discinfo{$lastkey} = $env{'form.navtime'};
       }        }
       my $textline = "<b>$lt{'mnpa'} $numitems $lt{'robb'}</b>";        my $textline = '<b>'.
                        &mt('Marked "New" posts as read in a total of [_1] resources/discussion boards.',
                            $numitems).
                        '</b>';
       if ($numitems > 0) {        if ($numitems > 0) {
           &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',            &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',
      \%discinfo,$env{'user.domain'},$env{'user.name'});       \%discinfo,$env{'user.domain'},$env{'user.name'});
Line 3528  sub handler { Line 4041  sub handler {
       $r->send_http_header;        $r->send_http_header;
       my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');        my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
       my %onload;        my %onload;
       if ($env{'environment.remote'} ne 'off') {  
   $onload{'onload'} =  
       "if (window.name!='loncapaclient') { this.document.reldt.submit(); self.window.close(); }";  
       }  
   
       my $start_page=        my $start_page=
   &Apache::loncommon::start_page('New posts marked as read',undef,    &Apache::loncommon::start_page('New posts marked as read',undef,
Line 3539  sub handler { Line 4048  sub handler {
   'only_body'   => 1,    'only_body'   => 1,
   'add_entries' => \%onload});    'add_entries' => \%onload});
       my $end_page = &Apache::loncommon::end_page();        my $end_page = &Apache::loncommon::end_page();
         my $windowname = 'loncapaclient';
         if ($env{'request.lti.login'}) {
             $windowname .= 'lti';
         }
       $r->print (<<ENDREDIR);        $r->print (<<ENDREDIR);
 $start_page  $start_page
 <img align="right" src="$logo" />  <img align="right" src="$logo" />
 $textline  $textline
 <form name="reldt" action="$feedurl" target="loncapaclient">  <form name="reldt" action="$feedurl" target="$windowname">
 </form>  </form>
 <br />  <br />
 $end_page  $end_page
Line 3597  ENDREDIR Line 4110  ENDREDIR
       my $entry=$env{'form.hide'}?$env{'form.hide'}:$env{'form.unhide'};        my $entry=$env{'form.hide'}?$env{'form.hide'}:$env{'form.unhide'};
       my ($symb,$idx)=split(/\:\:\:/,$entry);        my ($symb,$idx)=split(/\:\:\:/,$entry);
       ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);        ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
         my $ressymb = &wrap_symb($symb);
   
       my $crs='/'.$env{'request.course.id'};        my $seehidden = &can_see_hidden('',$ressymb,$feedurl,$group,$cdom,$cnum);
       if ($env{'request.course.sec'}) {        unless (($seehidden) || (&editing_allowed($env{'form.hide'},$group))) {
           $crs.='_'.$env{'request.course.sec'};            &redirect_back($r,$feedurl,&mt('Hiding not permitted').'<br />',
       }                           '0','0','','',$env{'form.previous'},'','','','',
       $crs=~s/\_/\//g;                           undef,undef,$group,);
       my $seeid=&Apache::lonnet::allowed('rin',$crs);  
   
       if ($env{'form.hide'} && !$seeid && !(&editing_allowed($env{'form.hide'},$env{'form.group'}))) {  
           &redirect_back($r,$feedurl,&mt('Deletion not permitted').'<br />',                 '0','0','','',$env{'form.previous'},'','','','',  
                  undef,undef,$group,);  
           return OK;            return OK;
       }        }
   
       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},        my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                           $env{'course.'.$env{'request.course.id'}.'.domain'},                                             $cdom,$cnum);
           $env{'course.'.$env{'request.course.id'}.'.num'});  
   
       my $currenthidden=$contrib{'hidden'};        my $currenthidden=$contrib{'hidden'};
       my $currentstudenthidden=$contrib{'studenthidden'};        my $currentstudenthidden=$contrib{'studenthidden'};
   
       if ($env{'form.hide'}) {        if ($env{'form.hide'}) {
   $currenthidden.='.'.$idx.'.';    $currenthidden.='.'.$idx.'.';
   unless ($seeid) {    unless ($seehidden) {
       $currentstudenthidden.='.'.$idx.'.';        $currentstudenthidden.='.'.$idx.'.';
   }    }
       } else {        } else {
   $currenthidden=~s/\.$idx\.//g;    $currenthidden=~s/\.$idx\.//g;
       }        }
       my %newhash=('hidden' => $currenthidden);        my %newhash=('hidden' => $currenthidden);
       if ( ($env{'form.hide'}) && (!$seeid) ) {        if ( ($env{'form.hide'}) && (!$seehidden) ) {
   $newhash{'studenthidden'} = $currentstudenthidden;    $newhash{'studenthidden'} = $currentstudenthidden;
       }        }
       if ($env{'form.hide'}) {        if ($env{'form.hide'}) {
Line 3636  ENDREDIR Line 4144  ENDREDIR
           ($changelast,$newlast) = &get_discussion_info($idx,%contrib);            ($changelast,$newlast) = &get_discussion_info($idx,%contrib);
           if ($changelast) {            if ($changelast) {
               &Apache::lonnet::put('discussiontimes',{$symb => $newlast},                &Apache::lonnet::put('discussiontimes',{$symb => $newlast},
                      $env{'course.'.$env{'request.course.id'}.'.domain'},                                     $cdom,$cnum);
                      $env{'course.'.$env{'request.course.id'}.'.num'});  
           }            }
       }        }
       &Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},        my $result;
                            $env{'course.'.$env{'request.course.id'}.'.domain'},        if (&Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},
    $env{'course.'.$env{'request.course.id'}.'.num'});                                   $cdom,$cnum) eq 'ok') {
             my $prefix=$symb.':'.$idx.':';
       &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',            my %likes=&Apache::lonnet::dump('disclikes',$cdom,$cnum,
      '0','0','','',$env{'form.previous'},undef,undef,undef,                                            '^'.$prefix);
             my ($totallikes,$totalunlikes);
             if (ref($likes{$prefix.'likers'}) eq 'HASH') {
                 $totallikes = scalar(keys(%{$likes{$prefix.'likers'}}));
             }
             if (ref($likes{$prefix.'unlikers'}) eq 'HASH') {
                 $totalunlikes = scalar(keys(%{$likes{$prefix.'unlikers'}}));
             }
             if ($totallikes || $totalunlikes) {
                 my ($chglikes,$chgunlikes,$context);
                 if ($env{'form.hide'}) {
                     $chglikes = -1 * $totallikes;
                     $chgunlikes = -1 * $totalunlikes;
                     $context = 'hide';
                 } else {
                     $chglikes = $totallikes;
                     $chgunlikes = $totalunlikes;
                     $context = 'unhide';
                 }
                 &storediscussionlikes($chglikes,$chgunlikes,
                                       $contrib{$idx.':sendername'},
                                       $contrib{$idx.':senderdomain'},
                                       $env{'request.course.id'},
                                       $context);
             
             }
             $result = &mt('Changed discussion status');
         } else {
             $result = &mt('Discussion status unchanged'); 
         }
         &redirect_back($r,$feedurl,$result.'<br />','0','0','','',
        $env{'form.previous'},undef,undef,undef,
                        undef,undef,undef,$group);
         return OK;
     } elsif (($env{'form.like'}) || ($env{'form.unlike'})) {
   # ----------------------------------------------------------------- Like/unlike
         my $entry=$env{'form.like'}?$env{'form.like'}:$env{'form.unlike'};
         my ($symb,$idx)=split(/\:\:\:/,$entry);
         ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
         my $result;
         if ($idx > 0) {
             my $realsymb = &get_realsymb($symb);
             my $status='OPEN';
             if ($Apache::lonhomework::parsing_a_problem ||
                 $Apache::lonhomework::parsing_a_task) {
                 $status=$Apache::inputtags::status[-1];
             }
             if (&discussion_vote_available($status,$realsymb)) {
                 my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                                                      $cdom,$cnum);
                 my $ownpost;
                 if (($contrib{$idx.':sendername'} eq $env{'user.name'}) && 
                     ($contrib{$idx.':senderdomain'} eq $env{'user.domain'})) {
                     $ownpost = 1;
                 }
                 if ($ownpost || $contrib{$idx.':hidden'} || $contrib{$idx.':deleted'}) {
                     $result = &mt('Vote not registered.').' ';
                 }
                 if ($ownpost) {
                     $result .= &mt('No voting for your own posts.');
                 } elsif ($contrib{$idx.':hidden'}) {
                     $result .= &mt('No voting for hidden posts.');
                 } elsif ($contrib{$idx.':deleted'}) {
                     $result .= &mt('No voting for deleted posts.');
                 } else {
   #
   # Likes and unlikes are in db-file "disclikes" of the course
   # The prefix is the $symb to identify the resource discussion,
   # and the $idx to identify the entry
   #
                     my $prefix=$symb.':'.$idx.':';
                     my %likes=&Apache::lonnet::dump('disclikes',$cdom,$cnum,
                                                     '^'.$prefix);
   
   # Get current like or unlike status for the $idx for this user.
                     my $thisuser=$env{'user.name'}.':'.$env{'user.domain'};
                     my ($userlikes,$userunlikes);
                     if (ref($likes{$prefix.'likers'}) eq 'HASH') {
                         if (exists($likes{$prefix.'likers'}{$thisuser})) {
                             $userlikes = 1;
                         }
                     }
                     if (ref($likes{$prefix.'unlikers'}) eq 'HASH') {
                         if (exists($likes{$prefix.'unlikers'}{$thisuser})) {
                             $userunlikes = 1;
                         }
                     }
   # Get the current "likes" count
                     my $likescount=$likes{$prefix.'likes'};
   # Find out if they already voted
   # Users cannot like a post twice, or unlike it twice.
   # They can change their mind, though.
                     my $alreadyflag=0;
                     my $votetype;
                     if ($env{'form.like'}) {
                         if ($userlikes) {
                             $alreadyflag=1;
                         } elsif ($userunlikes) {
                             delete($likes{$prefix.'unlikers'}{$thisuser});
                             $votetype = 'switch';
                             $likescount++;
                         } else {
                             if (ref($likes{$prefix.'likers'}) eq 'HASH') {
                                 $likes{$prefix.'likers'}{$thisuser} = 1;
                             } else {
                                 $likes{$prefix.'likers'} = {$thisuser => 1};
                             }
                             $likescount++;
                         }
                     } else {
                         if ($userunlikes) {
                             $alreadyflag=1;
                         } elsif ($userlikes) {
                             delete($likes{$prefix.'likers'}{$thisuser});
                             $votetype = 'switch';
                             $likescount--;
                         } else {
                             if (ref($likes{$prefix.'unlikers'}) eq 'HASH') {
                                 $likes{$prefix.'unlikers'}{$thisuser} = 1;
                             } else {
                                 $likes{$prefix.'unlikers'} = {$thisuser => 1};
                             }
                             $likescount--;
                         }
                     }
   # $alreadyflag would be 1 if they tried to double-like or double-unlike
                     if ($alreadyflag) {
                         if ($env{'form.like'}) {
                             $result= &mt("'Like' already registered");
                         } else {
                             $result= &mt("'Unlike' already registered");
                         }
                     } else {
                         my %newhash=($prefix.'likes'    => $likescount,
                                      $prefix.'likers'   => $likes{$prefix.'likers'},
                                      $prefix.'unlikers' => $likes{$prefix.'unlikers'});
   # Store data in db-file "disclikes"
                         if (&Apache::lonnet::put('disclikes',\%newhash,$cdom,$cnum) eq 'ok') {
   # Also store with the person who posted the liked/unliked entry
                             my ($chglike,$chgunlike);
                             if ($env{'form.like'}) {
                                 if ($votetype eq 'switch') {
                                     $chglike = 0;
                                     $chgunlike = -1;
                                 } else {
                                     $chglike = 1;
                                     $chgunlike = 0;
                                 } 
                                 &storediscussionlikes($chglike,$chgunlike,
                                                       $contrib{$idx.':sendername'},
                                                       $contrib{$idx.':senderdomain'},
                                                       $env{'request.course.id'},'like');
                                 $result=&mt("Registered 'Like'");
                             } else {
                                 if ($votetype eq 'switch') {
                                     $chglike = -1;
                                     $chgunlike = 0;
                                 } else {
                                     $chglike = 0;
                                     $chgunlike = 1;
                                 }
                                &storediscussionlikes($chglike,$chgunlike,
                                                      $contrib{$idx.':sendername'},
                                                      $contrib{$idx.':senderdomain'},
                                                      $env{'request.course.id'},'unlike');
                                $result=&mt("Registered 'Unlike'");
                             }
                         } else {
   # Oops, something went wrong
                             $result=&mt("Failed to register vote");
                         }
                     }
                 }
             } else {
                 $result=&mt('Voting unavailable for this discussion');
             }
         } else {
             $result=&mt('Invalid post number'); 
         }
         &redirect_back($r,$feedurl,$result.'<br />',
                        '0','0','','',$env{'form.previous'},undef,undef,undef,
                      undef,undef,undef,$group);                       undef,undef,undef,$group);
       return OK;        return OK;
   } elsif ($env{'form.cmd'}=~/^(threadedoff|threadedon)$/) {    } elsif ($env{'form.cmd'}=~/^(threadedoff|threadedon)$/) {
       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
       if ($env{'form.cmd'} eq 'threadedon') {        if ($env{'form.cmd'} eq 'threadedoff') {
     &Apache::lonnet::put('environment',{'unthreadeddiscussion' => 'on'});
     &Apache::lonnet::appenv({'environment.unthreadeddiscussion' => 'on'});
     &Apache::lonnet::del('environment',['threadeddiscussion']);
     &Apache::lonnet::delenv('environment.threadeddiscussion');
         } else {
   &Apache::lonnet::put('environment',{'threadeddiscussion' => 'on'});    &Apache::lonnet::put('environment',{'threadeddiscussion' => 'on'});
   &Apache::lonnet::appenv({'environment.threadeddiscussion' => 'on'});    &Apache::lonnet::appenv({'environment.threadeddiscussion' => 'on'});
       } else {    &Apache::lonnet::del('environment',['unthreadeddiscussion']);
    &Apache::lonnet::del('environment',['threadeddiscussion']);    &Apache::lonnet::delenv('environment.unthreadeddiscussion');
   &Apache::lonnet::delenv('environment.threadeddiscussion');  
       }        }
       &redirect_back($r,$feedurl,&mt('Changed discussion view mode').'<br />',        &redirect_back($r,$feedurl,&mt('Changed discussion view mode').'<br />',
      '0','0','','',$env{'form.previous'},undef,undef,undef,       '0','0','','',$env{'form.previous'},undef,undef,undef,
Line 3665  ENDREDIR Line 4356  ENDREDIR
 # --------------------------------------------------------------- Hide for good  # --------------------------------------------------------------- Hide for good
       my ($symb,$idx)=split(/\:\:\:/,$env{'form.deldisc'});        my ($symb,$idx)=split(/\:\:\:/,$env{'form.deldisc'});
       ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);        ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
         my $ressymb=&wrap_symb($symb);
   
         unless (&can_see_hidden('',$ressymb,$feedurl,$group,$cdom,$cnum)) {
             &redirect_back($r,$feedurl,&mt('Deletion not permitted').'<br />',
                            '0','0','','',$env{'form.previous'},'','','','',
                            undef,undef,$group);
             return OK;
         }
       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},        my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                           $env{'course.'.$env{'request.course.id'}.'.domain'},                                             $cdom,$cnum);
           $env{'course.'.$env{'request.course.id'}.'.num'});  
       my ($changelast,$newlast) = &get_discussion_info($idx,%contrib);        my ($changelast,$newlast) = &get_discussion_info($idx,%contrib);
       if ($changelast) {        if ($changelast) {
           &Apache::lonnet::put('discussiontimes',{$symb => $newlast},            &Apache::lonnet::put('discussiontimes',{$symb => $newlast},
                    $env{'course.'.$env{'request.course.id'}.'.domain'},                   $env{'course.'.$env{'request.course.id'}.'.num'});                                 $cdom,$cnum);
       }        }
       my %newhash=('deleted' => $contrib{'deleted'}.".$idx.");        my %newhash=('deleted' => $contrib{'deleted'}.".$idx.");
       &Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},  
    $env{'course.'.$env{'request.course.id'}.'.domain'},        my $result;
    $env{'course.'.$env{'request.course.id'}.'.num'});        if (&Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},
       &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',                               $cdom,$cnum) eq 'ok') {
      '0','0','','',$env{'form.previous'},undef,undef,undef,            $result = &mt('Changed discussion status');
             my $prefix=$symb.':'.$idx.':';
             my %likes=&Apache::lonnet::dump('disclikes',$cdom,$cnum,
                                             '^'.$prefix);
             my ($totallikes,$totalunlikes);
             if (ref($likes{$prefix.'likers'}) eq 'HASH') {
                 $totallikes = scalar(keys(%{$likes{$prefix.'likers'}}));
             }
             if (ref($likes{$prefix.'unlikers'}) eq 'HASH') {
                 $totalunlikes = scalar(keys(%{$likes{$prefix.'unlikers'}}));
             }
             if ($totallikes || $totalunlikes) {
                 my $chglikes = -1 * $totallikes;
                 my $chgunlikes = -1 * $totalunlikes;
                 &storediscussionlikes($chglikes,$chgunlikes,
                                       $contrib{$idx.':sendername'},
                                       $contrib{$idx.':senderdomain'},
                                       $env{'request.course.id'},
                                       'delete');
             }
         } else {
             $result = &mt('Discussion status unchanged');
         } 
         &redirect_back($r,$feedurl,$result.'<br />','0','0','','',
        $env{'form.previous'},undef,undef,undef,
                      undef,undef,undef,$group);                       undef,undef,undef,$group);
       return OK;        return OK;
   } elsif ($env{'form.preview'}) {    } elsif ($env{'form.preview'}) {
Line 3706  ENDREDIR Line 4428  ENDREDIR
       my $idx = $env{'form.idx'};        my $idx = $env{'form.idx'};
       if ($idx) {        if ($idx) {
           my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},            my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                          $env{'course.'.$env{'request.course.id'}.'.domain'},                                                 $cdom,$cnum);
                          $env{'course.'.$env{'request.course.id'}.'.num'});  
           $attachmenturls = $contrib{$idx.':attachmenturl'};            $attachmenturls = $contrib{$idx.':attachmenturl'};
       }        }
       &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,        &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,
Line 3720  ENDREDIR Line 4441  ENDREDIR
       my $mode='board';        my $mode='board';
       my $status='OPEN';        my $status='OPEN';
       my $previous=$env{'form.previous'};        my $previous=$env{'form.previous'};
       if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {        if ($feedurl =~ /$LONCAPA::assess_re/) {
           $mode='problem';            $mode='problem';
           $status=$Apache::inputtags::status[-1];            $status=$Apache::inputtags::status[-1];
       }        }
          
       my $discussion = &list_discussion($mode,$status,$symb);         my $discussion = &list_discussion($mode,$status,$symb); 
       my $start_page =         my $start_page = 
   &Apache::loncommon::start_page('Resource Feedback and Discussion');    &Apache::loncommon::start_page('Resource Feedback and Discussion');
Line 3731  ENDREDIR Line 4453  ENDREDIR
   &Apache::loncommon::end_page();    &Apache::loncommon::end_page();
       $r->print($start_page.$discussion.$end_page);        $r->print($start_page.$discussion.$end_page);
       return OK;        return OK;
   
     } elsif ($env{'form.undeleteall'}) {
         &Apache::loncommon::content_type($r,'text/html');
         $r->send_http_header;
         my ($symb,$feedurl) = &get_feedurl_and_clean_symb($env{'form.undeleteall'});
         my $ressymb=&wrap_symb($symb);
         $r->print(&Apache::loncommon::start_page('Undelete all deleted discussion entries'));
         if (&can_see_hidden('',$ressymb,$feedurl,$group,$cdom,$cnum)) {
             my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                                                   $cdom,$cnum);
             $contrib{'deleted'} =~ s/^\.//;
             $contrib{'deleted'} =~ s/\.$//;
             my $confirm_msg;
             if ($contrib{'deleted'} ne '') {
                 if (&Apache::lonnet::store({'deleted' => ''},$symb,$env{'request.course.id'},
                                             $cdom,$cnum) eq 'ok') {
                     my %likes=&Apache::lonnet::dump('disclikes',$cdom,$cnum,'^'.$symb.':');
                     my @ids = split(/\.\./,$contrib{'deleted'});
                     my (%chglikes,%chgunlikes);
                     foreach my $idx (@ids) {
                         my $uname = $contrib{$idx.':sendername'};
                         my $udom = $contrib{$idx.':senderdomain'};
                         my ($totallikes,$totalunlikes);
                         if (ref($likes{$symb.':'.$idx.':likers'}) eq 'HASH') {
                             $totallikes = scalar(keys(%{$likes{$symb.':'.$idx.':likers'}}));
                         }
                         if (ref($likes{$symb.':'.$idx.':unlikers'}) eq 'HASH') {
                             $totalunlikes = scalar(keys(%{$likes{$symb.':'.$idx.':unlikers'}}));
                         }
                         if ($totallikes || $totalunlikes) {
                             $chglikes{$uname.':'.$udom} += $totallikes;
                             $chgunlikes{$uname.':'.$udom} += $totalunlikes;
                         }
                     }
                     foreach my $user (keys(%chglikes)) {
                         my ($uname,$udom) = split(/:/,$user);
                         &storediscussionlikes($chglikes{$user},$chgunlikes{$user},
                                               $uname,$udom,$env{'request.course.id'},
                                               'undelete');
                     }
                     $confirm_msg = &Apache::lonhtmlcommon::confirm_success(&mt("Undeleted all entries"));
                 } else {
                     $confirm_msg = &Apache::lonhtmlcommon::confirm_success(&mt("Failed to undelete entries"),1);
                 }
             } else {
                 $confirm_msg = &Apache::lonhtmlcommon::confirm_success(&mt("No entries to undelete"),1);
             }
             $r->print(
                 '<br />'
                .&Apache::loncommon::confirmwrapper($confirm_msg)
                .&Apache::lonhtmlcommon::actionbox(
                     ["<a href='$feedurl'>".&mt("Return and reload")."</a>"])
             );
         }
         $r->print(&Apache::loncommon::end_page());
         return OK;
   } else {    } else {
 # ------------------------------------------------------------- Normal feedback  # ------------------------------------------------------------- Normal feedback
       my $feedurl=$env{'form.postdata'};        my $feedurl=$env{'form.postdata'};
Line 3746  ENDREDIR Line 4524  ENDREDIR
   $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];    $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
       } elsif ($env{'form.origpage'}) {        } elsif ($env{'form.origpage'}) {
   $symb="";     $symb=""; 
         } elsif ($env{'form.sendmessageonly'}) {
             $symb=(split(/\:\:\:/,$env{'form.sendmessageonly'}))[0];
       } else {        } else {
   $symb=&Apache::lonnet::symbread($feedurl);    $symb=&Apache::lonnet::symbread($feedurl);
       }        }
Line 3760  ENDREDIR Line 4540  ENDREDIR
           &dewrapper(\$feedurl);            &dewrapper(\$feedurl);
       }        }
       my $goahead=1;        my $goahead=1;
       if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form|task)$/) {        if ($feedurl=~/$LONCAPA::assess_re/) {
   unless ($symb) { $goahead=0; }    unless ($symb) { $goahead=0; }
       }        }
       if (!$goahead) {        if (!$goahead) {
Line 3777  ENDREDIR Line 4557  ENDREDIR
   ($env{'request.course.id'} && ($feedurl!~m:^/adm:))    ($env{'request.course.id'} && ($feedurl!~m:^/adm:))
   ||    ||
   ($env{'request.course.id'} && ($symb=~/^bulletin\_\_\_/))    ($env{'request.course.id'} && ($symb=~/^bulletin\_\_\_/))
             ||
             (($env{'request.course.id'} && ($feedurl =~ /ext\.tool$/)))
   ) {    ) {
   &Apache::loncommon::content_type($r,'text/html');    &Apache::loncommon::content_type($r,'text/html');
   $r->send_http_header;    $r->send_http_header;
Line 3798  ENDREDIR Line 4580  ENDREDIR
                   return OK;                    return OK;
               }                }
           }            }
   my $options=&screen_header($feedurl,$symb);    my $options=&screen_header($feedurl,$symb,$group);
   if ($options) {    if ($options) {
       &mail_screen($r,$feedurl,$options,$symb,$attachmax{'text'});        &mail_screen($r,$feedurl,$options,$symb,$attachmax{'text'});
   } else {    } else {
Line 3854  ENDREDIR Line 4636  ENDREDIR
           }            }
       }        }
 # Filter HTML out of message (could be nasty)  # Filter HTML out of message (could be nasty)
       my $message=&clear_out_html($env{'form.comment'});        my $override;
         if ($env{'form.discuss'} =~ /^(?:author|question|course|policy)$/) {
             $override = 1;
         }
         my $message=&clear_out_html($env{'form.comment'},$override);
   
 # Assemble email  # Assemble email
       my ($email,$citations)=&assemble_email($message,$prevattempts,        my ($email,$citations)=&assemble_email($message,$prevattempts,
Line 3864  ENDREDIR Line 4650  ENDREDIR
       my ($typestyle,%to) = &Apache::lonmsg::decide_receiver($feedurl);        my ($typestyle,%to) = &Apache::lonmsg::decide_receiver($feedurl);
   
 # Actually send mail  # Actually send mail
       my ($status,$numsent)=&send_msg(&clear_out_html($env{'form.subject'},        my ($status,$numsent)=&send_msg(&clear_out_html($env{'form.subject'}),
       undef,1),  
       $feedurl,$email,$citations,        $feedurl,$email,$citations,
       $attachmenturl,$usersymb,%to);        $attachmenturl,$usersymb,%to);
   
Line 3874  ENDREDIR Line 4659  ENDREDIR
       if (  ($env{'form.discuss'} ne ''        if (  ($env{'form.discuss'} ne ''
      && $env{'form.discuss'} !~ /^(?:author|question|course|policy)/)       && $env{'form.discuss'} !~ /^(?:author|question|course|policy)/)
    || $env{'form.anondiscuss'} ne '') {     || $env{'form.anondiscuss'} ne '') {
   my $subject = &clear_out_html($env{'form.subject'},undef,1);    my $subject = &clear_out_html($env{'form.subject'});
   my $anonmode=($env{'form.discuss'} eq 'anon' || $env{'form.anondiscuss'} );            my $anonmode;
             if (&Apache::lonnet::allowed('pac',$env{'request.course.id'}.
                ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
         $anonmode=($env{'form.discuss'} eq 'anon' || $env{'form.anondiscuss'} );
             }
   $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,    $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,
   $subject);    $subject,$group);
   $numpost++;    $numpost++;
       }        }
   
Line 3885  ENDREDIR Line 4674  ENDREDIR
   
       my $blog='';        my $blog='';
       if ($env{'form.blog'}) {        if ($env{'form.blog'}) {
   my $subject = &clear_out_html($env{'form.subject'},undef,1);    my $subject = &clear_out_html($env{'form.subject'});
   $status.=&Apache::lonrss::addentry($env{'user.name'},    $status.=&Apache::lonrss::addentry($env{'user.name'},
     $env{'user.domain'},      $env{'user.domain'},
     'CourseBlog_'.$env{'request.course.id'},      'CourseBlog_'.$env{'request.course.id'},
Line 3921  sub wrap_symb { Line 4710  sub wrap_symb {
     }      }
     return $ressymb;      return $ressymb;
 }  }
   
 sub dewrapper {  sub dewrapper {
     my ($feedurl)=@_;      my ($feedurl)=@_;
     if ($$feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {      if ($$feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
Line 4074  None Line 4864  None
   
 =item discussion_visible()  =item discussion_visible()
   
   =item discussion_vote_available()
   
   =item get_realsymb()
   
 =item list_discussion()  =item list_discussion()
   
   =item can_see_hidden()
   
   =item discussion_link()
   
 =item send_feedback_link()  =item send_feedback_link()
   
 =item send_message_link()  =item send_message_link()
Line 4130  None Line 4928  None
   
 =item newline_to_br()  =item newline_to_br()
   
   =item tidy_html()
   
 =item generate_preview_button()  =item generate_preview_button()
   
 =item modify_attachments()  =item modify_attachments()

Removed from v.1.273.4.5  
changed lines
  Added in v.1.383


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.