Diff for /loncom/interface/lonfeedback.pm between versions 1.127 and 1.143

version 1.127, 2004/09/21 20:44:16 version 1.143, 2004/11/20 20:40:51
Line 36  use Apache::loncommon(); Line 36  use Apache::loncommon();
 use Apache::lontexconvert();  use Apache::lontexconvert();
 use Apache::lonlocal; # must not have ()  use Apache::lonlocal; # must not have ()
 use Apache::lonhtmlcommon();  use Apache::lonhtmlcommon();
   use Apache::lonnavmaps;
   use Apache::lonenc();
 use HTML::LCParser();  use HTML::LCParser();
 use Apache::lonspeller();  use Apache::lonspeller();
 use Cwd;  use Cwd;
Line 66  sub discussion_visible { Line 68  sub discussion_visible {
 }  }
   
 sub list_discussion {  sub list_discussion {
     my ($mode,$status,$symb)=@_;      my ($mode,$status,$ressymb)=@_;
     my $outputtarget=$ENV{'form.grade_target'};      my $outputtarget=$ENV{'form.grade_target'};
     if (defined($ENV{'form.export'})) {      if (defined($ENV{'form.export'})) {
  if($ENV{'form.export'}) {   if($ENV{'form.export'}) {
             $outputtarget = 'export';              $outputtarget = 'export';
         }          }
     }          }
     if (not &discussion_visible($status)) { return ''; }      if (not &discussion_visible($status)) { return ''; }
     my @bgcols = ("#cccccc","#eeeeee");      my @bgcols = ("#cccccc","#eeeeee");
     my $discussiononly=0;      my $discussiononly=0;
Line 82  sub list_discussion { Line 84  sub list_discussion {
     my $cid=$ENV{'request.course.id'};      my $cid=$ENV{'request.course.id'};
     if ($ENV{'request.course.sec'}) {      if ($ENV{'request.course.sec'}) {
  $crs.='_'.$ENV{'request.course.sec'};   $crs.='_'.$ENV{'request.course.sec'};
     }                   
     $crs=~s/\_/\//g;  
     unless ($symb) {  
  $symb=&Apache::lonnet::symbread();  
     }      }
     unless ($symb) { return ''; }      $crs=~s/\_/\//g;
       unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }
       unless ($ressymb) { return ''; }
       $ressymb=&wrap_symb($ressymb);
       my $encsymb=&Apache::lonenc::check_encrypt($ressymb);
       my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
     && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form)$/));
       
     my %usernamesort = ();      my %usernamesort = ();
     my %namesort =();      my %namesort =();
     my %subjectsort = ();      my %subjectsort = ();
 # backward compatibility (bulletin boards used to be 'wrapped')  
     my $ressymb=$symb;  
     if ($mode eq 'board') {  
         unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
             $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
         }  
     }  
   
 # Get discussion display settings for this discussion  # Get discussion display settings for this discussion
     my $lastkey = $ressymb.'_lastread';      my $lastkey = $ressymb.'_lastread';
Line 108  sub list_discussion { Line 106  sub list_discussion {
     my $userpickkey = $ressymb.'_userpick';      my $userpickkey = $ressymb.'_userpick';
     my $toggkey = $ressymb.'_readtoggle';      my $toggkey = $ressymb.'_readtoggle';
     my $readkey = $ressymb.'_read';      my $readkey = $ressymb.'_read';
       $ressymb=$encsymb;
     my %dischash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$lastkey,$showkey,$markkey,$visitkey,$ondispkey,$userpickkey,$toggkey,$readkey],$ENV{'user.domain'},$ENV{'user.name'});      my %dischash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$lastkey,$showkey,$markkey,$visitkey,$ondispkey,$userpickkey,$toggkey,$readkey],$ENV{'user.domain'},$ENV{'user.name'});
     my %discinfo = ();      my %discinfo = ();
     my $showonlyunread = 0;      my $showonlyunread = 0;
Line 123  sub list_discussion { Line 121  sub list_discussion {
 # Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts.  # Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts.
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','totposters']);      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','totposters']);
     my $sortposts = $ENV{'form.sortposts'};      my $sortposts = $ENV{'form.sortposts'};
     my $rolefilter = $ENV{'form.rolefilter'};  
     my $statusfilter = $ENV{'form.statusfilter'};      my $statusfilter = $ENV{'form.statusfilter'};
     my $sectionpick = $ENV{'form.sectionpick'};      my @sectionpick = ();
       if ($ENV{'form.sectionpick'} =~ /,/) {
           @sectionpick = split/,/,$ENV{'form.sectionpick'};
       } else {
           $sectionpick[0] = $ENV{'form.sectionpick'};
       }
       my @rolefilter = ();
       if ($ENV{'form.rolefilter'} =~ /,/) {
           @rolefilter = split/,/,$ENV{'form.rolefilter'};
       } else {
           $rolefilter[0] = $ENV{'form.rolefilter'};
       }
     my $totposters = $ENV{'form.totposters'};      my $totposters = $ENV{'form.totposters'};
     $previous = $ENV{'form.previous'};      $previous = $ENV{'form.previous'};
     if ($previous > 0) {      if ($previous > 0) {
Line 139  sub list_discussion { Line 147  sub list_discussion {
 # 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 = ();
     if ($rolefilter) {      if ($ENV{'form.rolefilter'}) {
         %roleshash = &Apache::lonnet::dump('nohist_userroles',$ENV{'course.'.$ENV{'request.course.id'}.'.domain'},$ENV{'course.'.$ENV{'request.course.id'}.'.num'});          %roleshash = &Apache::lonnet::dump('nohist_userroles',$ENV{'course.'.$ENV{'request.course.id'}.'.domain'},$ENV{'course.'.$ENV{'request.course.id'}.'.num'});
         foreach (keys %roleshash) {          foreach (keys %roleshash) {
             my ($role,$uname,$udom,$sec) = split/:/,$_;              my ($role,$uname,$udom,$sec) = split/:/,$_;
Line 202  sub list_discussion { Line 210  sub list_discussion {
     $visit ++;      $visit ++;
   
     my $seeid=&Apache::lonnet::allowed('rin',$crs);      my $seeid=&Apache::lonnet::allowed('rin',$crs);
     my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)  
  && ($symb=~/\.(problem|exam|quiz|assess|survey|form)$/));  
     my @discussionitems=();      my @discussionitems=();
     my %shown = ();      my %shown = ();
     my @posteridentity=();      my @posteridentity=();
Line 229  sub list_discussion { Line 235  sub list_discussion {
     $discinfo{$visitkey} = $visit;      $discinfo{$visitkey} = $visit;
   
     &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});      &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_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,$ressymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$statusfilter,$toggkey,$outputtarget);      &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,$statusfilter,$toggkey,$outputtarget);
   
     my $discussion='';      my $discussion='';
     my $manifestfile;      my $manifestfile;
Line 359  imscp_v1p1.xsd http://www.imsglobal.org/ Line 365  imscp_v1p1.xsd http://www.imsglobal.org/
    }     }
 </script>  </script>
             |;              |;
     $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$symb.'"><table bgcolor="#AAAAAA" cellpadding="2" cellspacing="2" border="0">';      $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$ressymb.'" ><table bgcolor="#AAAAAA" cellpadding="2" cellspacing="2" border="0">';
     $discussion .='<tr><td bgcolor="#DDDDBB" colspan="'.$colspan.'">'.      $discussion .='<tr><td bgcolor="#DDDDBB" colspan="'.$colspan.'">'.
  '<table border="0" width="100%" bgcolor="#DDDDBB"><tr>';   '<table border="0" width="100%" bgcolor="#DDDDBB"><tr>';
     if ($visible>2) {      if ($visible>2) {
  $discussion.='<td align="left">'.   $discussion.='<td align="left">'.
     '<a href="/adm/feedback?threadedon='.$ressymb;      '<a href="/adm/feedback?cmd=threadedon&amp;symb='.$ressymb;
  if ($newpostsflag) {   if ($newpostsflag) {
     $discussion .= '&previous='.$prevread;      $discussion .= '&previous='.$prevread;
  }   }
  $discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.   $discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.
     '<a href="/adm/feedback?threadedoff='.$ressymb;      '<a href="/adm/feedback?cmd=threadedoff&amp;symb='.$ressymb;
  if ($newpostsflag) {   if ($newpostsflag) {
     $discussion .= '&previous='.$prevread;      $discussion .= '&previous='.$prevread;
  }   }
  $discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;   $discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;
                               <a href= "/adm/feedback?sortfilter='.$ressymb;                                <a href= "/adm/feedback?cmd=sortfilter&amp;symb='.$ressymb;
                 if ($newpostsflag) {                  if ($newpostsflag) {
                     $discussion .= '&previous='.$prevread;                      $discussion .= '&previous='.$prevread;
                 }                  }
Line 389  imscp_v1p1.xsd http://www.imsglobal.org/ Line 395  imscp_v1p1.xsd http://www.imsglobal.org/
             $discussion .= '">'.&mt('Export').'?</a>&nbsp;&nbsp;</td>';              $discussion .= '">'.&mt('Export').'?</a>&nbsp;&nbsp;</td>';
     if ($newpostsflag) {      if ($newpostsflag) {
  if (!$markondisp) {   if (!$markondisp) {
     $discussion .='<td align="right"><a href="/adm/feedback?markread='.$ressymb.'">'.&mt('Mark NEW posts no longer new').'</a>&nbsp;&nbsp;';      $discussion .='<td align="right"><a href="/adm/feedback?markread=1&amp;symb='.$ressymb.'">'.&mt('Mark NEW posts no longer new').'</a>&nbsp;&nbsp;';
  } else {   } else {
     $discussion .= '<td>&nbsp;</td>';      $discussion .= '<td>&nbsp;</td>';
  }   }
Line 551  END Line 557  END
                  </table>                   </table>
                 </td>                  </td>
 END  END
               if ($sortposts) {
                   my %sort_types = ();
                   my %role_types = ();
                   my %status_types = ();
                   &sort_filter_names(\%sort_types,\%role_types,\%status_types);
   
                   $discussion .= '<td><font size="-1"><b>'.&mt('Sorted by').'</b>: '.$sort_types{$sortposts}.'<br />';
                   if (defined($ENV{'form.totposters'})) {
                       $discussion .= &mt('Posts by').': ';
                       if ($totposters > 0) {
                           foreach my $poster (@posters) {
                               $poster =~ s/:/\@/;
                               $discussion .= $poster.',';
                           }
                           $discussion =~ s/,//;
                       } else {
                           $discussion .= &mt('None selected');
                       }
                   } else {
                       my $filterchoice ='';
                       if (@sectionpick > 0) {
                           $filterchoice = '<i>'.&mt('sections').'</i>-&nbsp;'.$ENV{'form.sectionpick'};
                           $filterchoice .= '&nbsp;&nbsp;&nbsp; ';
                       }
                       if (@rolefilter > 0) {
                           $filterchoice .= '<i>'.&mt('roles').'</i>-&nbsp;';
                           foreach (@rolefilter) {
                               $filterchoice .= $role_types{$_}.',&nbsp;';
                           }
                           $filterchoice .= '&nbsp;&nbsp;&nbsp; ';
                       }
                       if ($statusfilter) {
                           $filterchoice .= '<i>'.&mt('status').'</i>-&nbsp;'.$status_types{$statusfilter};
                       }
                       if ($filterchoice) {
                           $discussion .= '<b>'.&mt('Filters').'</b>:&nbsp;'.$filterchoice;
                       }
                       $discussion .= '</font></td>';
                   }
               }
             if ($dischash{$toggkey}) {              if ($dischash{$toggkey}) {
                 my $storebutton = &mt('Store read/unread changes');                  my $storebutton = &mt('Store read/unread changes');
                 $discussion.='<td align="right">'.                  $discussion.='<td align="right">'.
Line 643  to course faculty</font><br /> Line 689  to course faculty</font><br />
 <b>Title:</b>&nbsp;<input type="text" name="subject" value="$subject" size="30" /><br /><br />  <b>Title:</b>&nbsp;<input type="text" name="subject" value="$subject" size="30" /><br /><br />
 <textarea name="comment" cols="80" rows="14" wrap="hard">$comment</textarea>  <textarea name="comment" cols="80" rows="14" wrap="hard">$comment</textarea>
 ENDDISCUSS  ENDDISCUSS
         if ($ENV{'form.origpage'}) {              if ($ENV{'form.origpage'}) {
             $discussion.='<input type="hidden" name="origpage" value="'.$ENV{'form.origpage'}.'" />'."\n";                  $discussion.='<input type="hidden" name="origpage" value="'.$ENV{'form.origpage'}.'" />'."\n";
             foreach (@currnewattach) {                  foreach (@currnewattach) {
                 $discussion.='<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";                      $discussion.='<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";
             }                  }
         }              }
         $discussion.="</form>\n";              $discussion.="</form>\n";
         if ($outputtarget ne 'tex') {              if ($outputtarget ne 'tex') {
             $discussion.=&generate_attachments_button('',$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,'',$mode);                  $discussion.=&generate_attachments_button('',$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,'',$mode);
             if (@currnewattach > 0) {                  if (@currnewattach > 0) {
                 $newattachmsg .= '<b>New attachments</b><br />';                      $newattachmsg .= '<b>New attachments</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";
                       } else {
                           $currnewattach[0] =~ m#.*/([^/]+)$#;
                           $newattachmsg .= '<a href="'.$currnewattach[0].'">'.$1.'</a><br />'."\n";
                     }                      }
                     $newattachmsg .= '</ol>'."\n";  
                 } else {  
                     $currnewattach[0] =~ m#.*/([^/]+)$#;  
                     $newattachmsg .= '<a href="'.$currnewattach[0].'">'.$1.'</a><br />'."\n";  
                 }                  }
             }                  $discussion.=$newattachmsg;
             $discussion.=$newattachmsg;          $discussion.=&generate_preview_button();
     $discussion.=&generate_preview_button();      }
  }  
  }   }
         } else {      } else {
  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') {      if ($outputtarget ne 'tex') {
  $discussion.='<table bgcolor="#BBBBBB"><tr><td><a href="/adm/feedback?replydisc='.   $discussion.='<table bgcolor="#BBBBBB"><tr><td><a href="/adm/feedback?replydisc='.
     $symb.':::" '.$target.'>'.      $ressymb.':::" '.$target.'>'.
     '<img src="/adm/lonMisc/chat.gif" border="0" />'.      '<img src="/adm/lonMisc/chat.gif" border="0" />'.
     &mt('Post Discussion').'</a></td></tr></table>';      &mt('Post Discussion').'</a></td></tr></table>';
     }      }
Line 688  ENDDISCUSS Line 734  ENDDISCUSS
   
 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,$statusfilter,$toggkey,$outputtarget) = @_;      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,$statusfilter,$toggkey,$outputtarget) = @_;
   
     my @original=();      my @original=();
     my @index=();      my @index=();
       my $symb=&Apache::lonenc::check_decrypt($ressymb);
     my %contrib=&Apache::lonnet::restore($ressymb,$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'});
   
Line 701  sub build_posting_display { Line 746  sub build_posting_display {
         if ($prevread eq '0') {          if ($prevread eq '0') {
             $prevread = $oldest-1;              $prevread = $oldest-1;
         }          }
           my ($skiptest,$rolematch,$roleregexp,$secregexp,$statusregexp);
           if ($sortposts) {
               ($skiptest,$roleregexp,$secregexp,$statusregexp) = &filter_regexp($rolefilter,$sectionpick,$statusfilter);
               $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;
           } 
  for (my $id=1;$id<=$contrib{'version'};$id++) {   for (my $id=1;$id<=$contrib{'version'};$id++) {
     my $idx=$id;      my $idx=$id;
             my $posttime = $contrib{$idx.':timestamp'};              my $posttime = $contrib{$idx.':timestamp'};
Line 949  sub build_posting_display { Line 999  sub build_posting_display {
                             my $uname = $contrib{$idx.':sendername'};                              my $uname = $contrib{$idx.':sendername'};
                             my $udom = $contrib{$idx.':senderdomain'};                              my $udom = $contrib{$idx.':senderdomain'};
                             my $poster = $uname.':'.$udom;                              my $poster = $uname.':'.$udom;
                             my $rolematch = '';                              if (defined($ENV{'form.totposters'})) {
                             my $skiptest = 1;                                  if ($totposters == 0) {
                             if ($totposters > 0) {                                      $$shown{$idx} = 0;
                                 if (grep/^$poster$/,@{$posters}) {                                  } elsif ($totposters > 0) {
                                     $$shown{$idx} = 1;                                      if (grep/^$poster$/,@{$posters}) {
                                 }                                          $$shown{$idx} = 1;
                             } else {  
                                 if ($rolefilter) {  
                                     if ($rolefilter eq 'all') {  
                                         $rolematch = '([^:]+)';  
                                     } else {  
                                         $rolematch = $rolefilter;  
                                         $skiptest = 0;  
                                     }  
                                 }  
                                 if ($sectionpick) {  
                                     if ($sectionpick eq 'all') {  
                                         $rolematch .= ':([^:]*)';  
                                     } else {  
                                         $rolematch .= ':'.$sectionpick;  
                                         $skiptest = 0;  
                                     }  
                                 }  
                                 if ($statusfilter) {  
                                     if ($statusfilter eq 'all') {  
                                         $rolematch .= ':([^:]+)';  
                                     } else {  
                                         $rolematch .= ':'.$statusfilter;  
                                         $skiptest = 0;  
                                     }                                      }
                                 }                                  }
                               } elsif ($sortposts) {
                                 if ($skiptest) {                                  if ($skiptest) {
                                     $$shown{$idx} = 1;                                      $$shown{$idx} = 1;
                                 } else {                                  } else {
                                     foreach my $role (@{$$roleinfo{$poster}}) {                                      foreach my $role (@{$$roleinfo{$poster}}) {
                                         if ($role =~ m/^$rolematch$/) {                                          if ($role =~ /^cc:/) {
                                               my $cc_regexp = $roleregexp.':[^:]*:'.$statusregexp;
                                               if ($role =~ /$cc_regexp/) {
                                                   $$shown{$idx} = 1;
                                               }
                                           } elsif ($role =~ /^$rolematch$/) {
                                             $$shown{$idx} = 1;                                              $$shown{$idx} = 1;
                                             last;                                              last;
                                         }                                          }
                                     }                                      }
                                 }                                  }
                               } else {
                                   $$shown{$idx} = 1;
                             }                              }
                         }                          }
                         unless ($$notshown{$idx} == 1) {                          unless ($$notshown{$idx} == 1) {
Line 1039  sub build_posting_display { Line 1074  sub build_posting_display {
     }      }
 }  }
   
   sub filter_regexp {
       my ($rolefilter,$sectionpick,$statusfilter) = @_;
       my ($roleregexp,$secregexp,$statusregexp);
       my $skiptest = 1;
       if (@{$rolefilter} > 0) {
           my @okrolefilter = ();
           foreach (@{$rolefilter}) {
               unless ($_ eq '') {
                   push @okrolefilter, $_;
               }
           }
           if (@okrolefilter > 0) {
               if (grep/^all$/,@okrolefilter) {
                   $roleregexp='[^:]+';
               } else {
                   if (@okrolefilter == 1) {
                       $roleregexp=$okrolefilter[0];
                   } else {
                       $roleregexp='('.join('|',@okrolefilter).')';
                   }
                   $skiptest = 0;
               }
           }
       }
       if (@{$sectionpick} > 0) {
           my @oksectionpick = ();
           foreach (@{$sectionpick}) {
               unless ($_ eq '') {
                    push @oksectionpick, $_;
               }
           }
           if ((@oksectionpick > 0) && (!grep/^all$/,@oksectionpick)) {
               if (@oksectionpick == 1) {
                   $secregexp = $oksectionpick[0];
               } else {
                   $secregexp .= '('.join('|',@oksectionpick).')';
               }
               $skiptest = 0;
           } else {
               $secregexp .= '[^:]*';
           }
       }
       if (defined($statusfilter) && $statusfilter ne '') {
           if ($statusfilter eq 'all') {
               $statusregexp = '[^:]+';
           } else {
               $statusregexp = $statusfilter;
               $skiptest = 0;
           }
       }
       return ($skiptest,$roleregexp,$secregexp,$statusregexp);
   }
   
   
 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,$type,$messages,$subjects,$allattachments,$attachtxt,$imsfiles,$screenname,$plainname,$numver) = @_;
     my $discussion = '';      my $discussion = '';
Line 1478  END Line 1567  END
   
 sub print_display_options {  sub print_display_options {
     my ($r,$symb,$previous,$dispchgA,$dispchgB,$markchg,$toggchg,$feedurl) = @_;      my ($r,$symb,$previous,$dispchgA,$dispchgB,$markchg,$toggchg,$feedurl) = @_;
  # backward compatibility (bulletin boards used to be 'wrapped')      &Apache::loncommon::content_type($r,'text/html');
     if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {      $r->send_http_header;
         $feedurl=~s|^/adm/wrapper||;  
     }  
   
     my $function = &Apache::loncommon::get_users_function();      my $function = &Apache::loncommon::get_users_function();
     my $tabcolor = &Apache::loncommon::designparm($function.'.tabbg',      my $tabcolor = &Apache::loncommon::designparm($function.'.tabbg',
Line 1662  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l Line 1749  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l
 </table>  </table>
 <br />  <br />
 <br />  <br />
   <input type="hidden" name="symb" value="$symb" />
 <input type="hidden" name="previous" value="$previous" />  <input type="hidden" name="previous" value="$previous" />
 <input type="hidden" name="$dispchgA" value=""/>  <input type="hidden" name="$dispchgA" value=""/>
 <input type="hidden" name="$dispchgB" value=""/>  <input type="hidden" name="$dispchgB" value=""/>
Line 1679  END Line 1767  END
   
 sub print_sortfilter_options {  sub print_sortfilter_options {
     my ($r,$symb,$previous,$feedurl) = @_;      my ($r,$symb,$previous,$feedurl) = @_;
  # backward compatibility (bulletin boards used to be 'wrapped')  
     if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {      &Apache::loncommon::content_type($r,'text/html');
         $feedurl=~s|^/adm/wrapper||;      $r->send_http_header;
     }  
       &Apache::lonenc::check_encrypt(\$symb);
     my @sections = ();      my @sections = ();
     my $section_sel = '';      my $section_sel = '';
     my $numsections = 0;      my $numsections = 0;
Line 1732  sub print_sortfilter_options { Line 1821  sub print_sortfilter_options {
         'diop' => 'Display Options',          'diop' => 'Display Options',
         'curr' => 'Current setting ',          'curr' => 'Current setting ',
         'actn' => 'Action',          'actn' => 'Action',
         'prca' => 'Options can be set that control the sort order of the posts, in addition to which posts are displayed.',          'prca' => 'Set options that control the sort order of posts, and/or which posts are displayed.',
         'soor' => 'Sort order',          'soor' => 'Sort order',
         'disp' => 'Specific user roles',          'spur' => 'Specific user roles',
         'actv' => 'Specific role status',          'sprs' => 'Specific role status',
         'spse' => 'Specific sections',          'spse' => 'Specific sections',
         'psub' => 'Pick specific users (by name)',          'psub' => 'Pick specific users (by name)',
         'shal' => 'Show a list of current posters'          'shal' => 'Show a list of current posters'
     );      );
   
       my %sort_types = ();
       my %role_types = ();
       my %status_types = ();
       &sort_filter_names(\%sort_types,\%role_types,\%status_types);
   
     $r->print(<<END);      $r->print(<<END);
 <html>  <html>
 <head>  <head>
Line 1754  $bodytag Line 1849  $bodytag
  <tr>   <tr>
   <td><b>$lt{'soor'}</b></td>    <td><b>$lt{'soor'}</b></td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td><b>$lt{'disp'}</b></td>    <td><b>$lt{'sprs'}</b></td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td><b>$lt{'actv'}</b></td>    <td><b>$lt{'spur'}</b></td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td><b>$lt{'spse'}</b></td>    <td><b>$lt{'spse'}</b></td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td><b>$lt{'psub'}</b></td>    <td><b>$lt{'psub'}</b></td>
  </tr>   </tr>
  <tr>   <tr>
   <td>    <td align="center">
    <select name="sortposts">     <select name="sortposts">
     <option value="ascdate" />Date order - oldest first      <option value="ascdate" />$sort_types{'ascdate'}
     <option value="descdate" />Date order - newest first      <option value="descdate" />$sort_types{'descdate'}
     <option value="thread" />Threaded      <option value="thread" />$sort_types{'thread'}
     <option value="subject" />By subject      <option value="subject" />$sort_types{'subject'}
     <option value="username" />By domain and username      <option value="username" />$sort_types{'username'}
     <option value="lastfirst" />By last name, first name      <option value="lastfirst" />$sort_types{'lastfirst'}
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td>    <td align="center">
    <select name="rolefilter" multiple="true" size="5">     <select name="statusfilter">
     <option value="all" />All users      <option value="all" />$status_types{'all'}
     <option value="st" />Students      <option value="Active" />$status_types{'Active'}
     <option value="cc" />Course Coordinators      <option value="Expired" />$status_types{'Expired'}
     <option value="in" />Instructors  
     <option value="ta" />TAs  
     <option value="pr" />Exam proctors  
     <option value="cr" />Custom roles  
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td>    <td align="center">
    <select name="statusfilter">     <select name="rolefilter" multiple="true" size="5">
     <option value="all" />Roles of any status      <option value="all" />$role_types{'all'}
     <option value="Active" />Only active roles      <option value="st" />$role_types{'st'}
     <option value="Expired" />Only inactive roles      <option value="cc" />$role_types{'cc'}
       <option value="in" />$role_types{'in'}
       <option value="ta" />$role_types{'ta'}
       <option value="ep" />$role_types{'ep'}
       <option value="ad" />$role_types{'ad'}
       <option value="cr" />$role_types{'cr'}
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td>    <td align="center">
    <select name="sectionpick" multiple="true" size="$numvisible">     <select name="sectionpick" multiple="true" size="$numvisible">
     $section_sel      $section_sel
    </select>     </select>
Line 1818  END Line 1914  END
   
 sub print_showposters {  sub print_showposters {
     my ($r,$symb,$previous,$feedurl,$sortposts) = @_;      my ($r,$symb,$previous,$feedurl,$sortposts) = @_;
  # backward compatibility (bulletin boards used to be 'wrapped')  
     if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {      &Apache::lonenc::check_encrypt(\$symb);
         $feedurl=~s|^/adm/wrapper||;  
     }  
 # backward compatibility (bulletin boards used to be 'wrapped')  
     my $ressymb=$symb;  
     if ($ressymb =~ /bulletin___\d+___/) {  
         unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
             $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
         }  
     }  
     my $crs='/'.$ENV{'request.course.id'};      my $crs='/'.$ENV{'request.course.id'};
     if ($ENV{'request.course.sec'}) {      if ($ENV{'request.course.sec'}) {
         $crs.='_'.$ENV{'request.course.sec'};          $crs.='_'.$ENV{'request.course.sec'};
     }      }
     $crs=~s/\_/\//g;      $crs=~s/\_/\//g;
     my $seeid=&Apache::lonnet::allowed('rin',$crs);      my $seeid=&Apache::lonnet::allowed('rin',$crs);
     my %contrib=&Apache::lonnet::restore($ressymb,$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 %namesort = ();      my %namesort = ();
Line 2004  ENDFAILREDIR Line 2091  ENDFAILREDIR
 }  }
   
 sub redirect_back {  sub redirect_back {
   my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$status,$previous,$sort,$rolefilter,$statusfilter,$secpick,$numpicks) = @_;    my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$status,$previous,$sort,$rolefilter,$statusfilter,$sectionpick,$numpicks) = @_;
   my $sorttag = '';    my $sorttag = '';
   my $roletag = '';    my $roletag = '';
   my $statustag = '';    my $statustag = '';
Line 2012  sub redirect_back { Line 2099  sub redirect_back {
   my $userpicktag = '';    my $userpicktag = '';
   my $qrystr = '';    my $qrystr = '';
   my $prevtag = '';    my $prevtag = '';
  # backward compatibility (bulletin boards used to be 'wrapped')  
   if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {    &Apache::loncommon::content_type($r,'text/html');
       $feedurl=~s|^/adm/wrapper||;    $r->send_http_header;
   }  
     &dewrapper(\$feedurl);
   if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };    if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
   if ($previous > 0) {    if ($previous > 0) {
       $qrystr = 'previous='.$previous;        $qrystr = 'previous='.$previous;
Line 2034  sub redirect_back { Line 2122  sub redirect_back {
           $feedurl .= '?'.$sortqry;            $feedurl .= '?'.$sortqry;
       }        }
       $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';        $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';
       if ( (defined($numpicks)) && ($numpicks > 0) ) {        if (defined($numpicks)) {
           my $userpickqry = 'totposters='.$numpicks;            my $userpickqry = 'totposters='.$numpicks;
           $feedurl .= '&'.$userpickqry;            $feedurl .= '&'.$userpickqry;
           $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';            $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';
       } else {        } else {
           my $roleqry = 'rolefilter='.$rolefilter;            if (ref($sectionpick) eq 'ARRAY') {
           $feedurl .= '&'.$roleqry;                $feedurl .= '&sectionpick=';
           $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';                $sectag .=  '<input type="hidden" name="sectionpick" value="';
                 foreach (@{$sectionpick}) {
                     $feedurl .= $_.',';
                     $sectag .= $_.',';
                 }
                 $feedurl =~ s/,$//;
                 $sectag =~ s/,$//;
                 $sectag .= '" />';
             } else {
                 $feedurl .= '&sectionpick='.$sectionpick;
                 $sectag = '<input type="hidden" name="sectionpick" value="'.$sectionpick.'" />';
             }
             if (ref($rolefilter) eq 'ARRAY') {
                 $feedurl .= '&rolefilter=';
                 $roletag .=  '<input type="hidden" name="rolefilter" value="';
                 foreach (@{$rolefilter}) {
                     $feedurl .= $_.',';
                     $roletag .= $_.',';
                 }
                 $feedurl =~ s/,$//;
                 $roletag =~ s/,$//;
                 $roletag .= '" />';
             } else {
                 $feedurl .= '&rolefilter='.$rolefilter;
                 $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';
             }
           $feedurl .= '&statusfilter='.$statusfilter;            $feedurl .= '&statusfilter='.$statusfilter;
           $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';            $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';
           $feedurl .= '&sectionpick='.$secpick;  
           $sectag = '<input type="hidden" name="sectionpick" value="'.$secpick.'" />';  
       }        }
   }    }
     $feedurl=&Apache::lonenc::check_encrypt($feedurl);
   $r->print (<<ENDREDIR);    $r->print (<<ENDREDIR);
 <html>  <html>
 <head>  <head>
Line 2085  sub no_redirect_back { Line 2197  sub no_redirect_back {
 ENDNOREDIR  ENDNOREDIR
   
   if ($feedurl!~/^\/adm\/feedback/) {     if ($feedurl!~/^\/adm\/feedback/) { 
     $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2; url='.$feedurl.'">');        $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2; url='.
    &Apache::lonenc::check_encrypt($feedurl).'">');
   }    }
       $feedurl=&Apache::lonenc::check_encrypt($feedurl);
   $r->print (<<ENDNOREDIRTWO);    $r->print (<<ENDNOREDIRTWO);
 </head>  </head>
 <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { self.close(); }'>  <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { self.close(); }'>
Line 2100  ENDNOREDIRTWO Line 2213  ENDNOREDIRTWO
 }  }
   
 sub screen_header {  sub screen_header {
     my ($feedurl) = @_;      my ($feedurl,$symb) = @_;
     my $msgoptions='';      my $msgoptions='';
     my $discussoptions='';      my $discussoptions='';
     unless (($ENV{'form.replydisc'}) || ($ENV{'form.editdisc'})) {      unless (($ENV{'form.replydisc'}) || ($ENV{'form.editdisc'})) {
Line 2126  sub screen_header { Line 2239  sub screen_header {
  }   }
     }      }
     if ($ENV{'request.course.id'}) {      if ($ENV{'request.course.id'}) {
  if (&discussion_open() &&   if (&discussion_open(undef,$symb) &&
     &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'}:''))) {
Line 2136  sub screen_header { Line 2249  sub screen_header {
     $discussoptions.='<br /><input type="checkbox" name="anondiscuss" onClick="this.form.discuss.checked=false;" /> '.      $discussoptions.='<br /><input type="checkbox" name="anondiscuss" onClick="this.form.discuss.checked=false;" /> '.
  &mt('Anonymous contribution to course discussion of resource').   &mt('Anonymous contribution to course discussion of resource').
  ' <i>('.&mt('name only visible to course faculty').')</i>';   ' <i>('.&mt('name only visible to course faculty').')</i>';
       }          }
     }      }
     if ($msgoptions) { $msgoptions='<h2><img src="/adm/lonMisc/feedback.gif" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }      if ($msgoptions) { $msgoptions='<h2><img src="/adm/lonMisc/feedback.gif" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }
     if ($discussoptions) {       if ($discussoptions) { 
Line 2185  sub clear_out_html { Line 2298  sub clear_out_html {
 sub assemble_email {  sub assemble_email {
   my ($feedurl,$message,$prevattempts,$usersaw,$useranswer)=@_;    my ($feedurl,$message,$prevattempts,$usersaw,$useranswer)=@_;
   my $email=<<"ENDEMAIL";    my $email=<<"ENDEMAIL";
 Refers to <a href="$feedurl">$feedurl</a>  
   
 $message  $message
 ENDEMAIL  ENDEMAIL
     my $citations=<<"ENDCITE";      my $citations=<<"ENDCITE";
Line 2338  sub adddiscuss { Line 2449  sub adddiscuss {
             $contrib{'history'} = '';              $contrib{'history'} = '';
             my $numoldver = 0;              my $numoldver = 0;
             my ($oldsymb,$oldidx)=split(/\:\:\:/,$ENV{'form.editdisc'});              my ($oldsymb,$oldidx)=split(/\:\:\:/,$ENV{'form.editdisc'});
       &Apache::lonenc::check_decrypt(\$oldsymb);
             $oldsymb=~s|(bulletin___\d+___)adm/wrapper/|$1|;              $oldsymb=~s|(bulletin___\d+___)adm/wrapper/|$1|;
 # get timestamp for last post and history  # get timestamp for last post and history
             my %oldcontrib=&Apache::lonnet::restore($oldsymb,$ENV{'request.course.id'},              my %oldcontrib=&Apache::lonnet::restore($oldsymb,$ENV{'request.course.id'},
Line 2413  sub adddiscuss { Line 2525  sub adddiscuss {
   
 sub show_preview {  sub show_preview {
     my $r=shift;      my $r=shift;
       &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;
     my $message=&clear_out_html($ENV{'form.comment'});      my $message=&clear_out_html($ENV{'form.comment'});
     $message=~s/\n/\<br \/\>/g;      $message=~s/\n/\<br \/\>/g;
     $message=&Apache::lonspeller::markeduptext($message);      $message=&Apache::lonspeller::markeduptext($message);
Line 2453  sub modify_attachments { Line 2567  sub modify_attachments {
     if ($idx) {      if ($idx) {
         &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);          &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);
     }      }
       &Apache::lonenc::check_encrypt(\$symb);
     $r->print(<<END);      $r->print(<<END);
 <html>  <html>
 <head>  <head>
Line 2716  sub construct_attachmenturl { Line 2831  sub construct_attachmenturl {
     }      }
     return $newattachmenturl;       return $newattachmenturl; 
 }  }
   
   sub has_discussion {
       my $resourcesref = shift;
       my $navmap = Apache::lonnavmaps::navmap->new();
       my @allres=$navmap->retrieveResources();
       foreach my $resource (@allres) {
           if ($resource->hasDiscussion()) {
               my $ressymb;
               if ($resource->symb() =~ m-(___adm/\w+/\w+)/(\d+)/bulletinboard$-) {
                   $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
               } else {
                   $ressymb = $resource->symb();
               }
               push @{$resourcesref}, $ressymb;
           }
       }
       return;
   }
   
   sub sort_filter_names {
       my ($sort_types,$role_types,$status_types) = @_;
       %{$sort_types} = (
                        ascdate => 'Date order - oldest first',
                        descdate => 'Date order - newest first',
                        thread => 'Threaded',
                        subject => 'By subject',
                        username => 'By domain and username',
                        lastfirst => 'By last name, first name'
                      );
       %{$role_types} = (
                        all => 'All roles',
                        st  => 'Students',
                        cc  => 'Course Coordinators',
                        in  => 'Instructors',
                        ta  => 'TAs',
                        ep  => 'Exam proctors',
                        ad  => 'Administrators',
                        cr  => 'Custom roles'
                      );
       %{$status_types} = (
                        all     => 'Roles of any status',
                        Active => 'Only active roles',
                        Expired => 'Only inactive roles'
                      );
   }
       
 sub handler {  sub handler {
   my $r = shift;    my $r = shift;
Line 2728  sub handler { Line 2888  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','threadedon','threadedoff','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navmaps','navurl','navtime','sortfilter','sortposts','applysort','rolefilter','statusfilter','sectionpick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export']);           ['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','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export']);
   
   if ($ENV{'form.discsymb'}) {    if ($ENV{'form.discsymb'}) {
       my $symb = $ENV{'form.discsymb'};        my ($symb,$feedurl) = &get_feedurl_and_clean_symb($ENV{'form.discsymb'});
       my $readkey = $symb.'_read';        my $readkey = $symb.'_read';
       my %readinghash = ();  
       my $chgcount = 0;        my $chgcount = 0;
       %readinghash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$readkey],$ENV{'user.domain'},$ENV{'user.name'});        my %readinghash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$readkey],$ENV{'user.domain'},$ENV{'user.name'});
       foreach my $key (keys %ENV) {        foreach my $key (keys %ENV) {
           if ($key =~ m/^form\.postunread_(\d+)/) {            if ($key =~ m/^form\.postunread_(\d+)/) {
               if ($readinghash{$readkey} =~ /\.$1\./) {                if ($readinghash{$readkey} =~ /\.$1\./) {
Line 2749  sub handler { Line 2909  sub handler {
           }            }
       }        }
       if ($chgcount > 0) {        if ($chgcount > 0) {
           &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%readinghash,$ENV{'user.domain'},$ENV{'user.name'});            &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',
     \%readinghash,$ENV{'user.domain'},$ENV{'user.name'});
       }        }
       &Apache::loncommon::content_type($r,'text/html');        &redirect_back($r,$feedurl,&mt('Marked postings read/unread').'<br />',
       $r->send_http_header;       '0','0','',$ENV{'form.previous'},'','','',);
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
       my $previous=$ENV{'form.previous'};  
       my $feedurl = &Apache::lonnet::clutter($url);  
       &redirect_back($r,$feedurl,&mt('Marked postings read/unread').'<br />','0','0','',$previous,'','','',);  
       return OK;        return OK;
   }    }
   if ($ENV{'form.allversions'}) {    if ($ENV{'form.allversions'}) {
       &Apache::loncommon::content_type($r,'text/html');        &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;        $r->send_http_header;
       my $bodytag=&Apache::loncommon::bodytag('Discussion Post Versions',        my $bodytag=&Apache::loncommon::bodytag('Discussion Post Versions');
                                           '','');        $r->print(<<END);
       $r->print (<<END);  
 <html>  <html>
 <head>  <head>
 <title>Post Versions</title>  <title>Post Versions</title>
Line 2776  END Line 2932  END
       if ($ENV{'request.course.sec'}) {        if ($ENV{'request.course.sec'}) {
           $crs.='_'.$ENV{'request.course.sec'};            $crs.='_'.$ENV{'request.course.sec'};
       }        }
       $crs=~s/\_/\//g;        $crs=~s|_|/|g;
       my $seeid=&Apache::lonnet::allowed('rin',$crs);        my $seeid=&Apache::lonnet::allowed('rin',$crs);
       my ($symb,$idx)=split(/\:\:\:/,$ENV{'form.allversions'});        my ($symb,$idx)=split(/\:\:\:/,$ENV{'form.allversions'});
       my $ressymb=$symb;        ($symb)=&get_feedurl_and_clean_symb($symb);
       unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
           $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
       }  
       if ($idx > 0) {        if ($idx > 0) {
           my %messages = ();            my %messages = ();
           my %subjects = ();            my %subjects = ();
Line 2790  END Line 2943  END
           my %allattachments = ();            my %allattachments = ();
           my %imsfiles = ();            my %imsfiles = ();
           my ($screenname,$plainname);            my ($screenname,$plainname);
           my %contrib=&Apache::lonnet::restore($ressymb,$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 $discussion = &get_post_contents(\%contrib,$idx,$seeid,'allversions',\%messages,\%subjects,\%allattachments,\%attachmsgs,\%imsfiles,\$screenname,\$plainname);            $r->print(&get_post_contents(\%contrib,$idx,$seeid,'allversions',\%messages,\%subjects,\%allattachments,\%attachmsgs,\%imsfiles,\$screenname,\$plainname));
           $r->print($discussion);  
       }        }
       return OK;        return OK;
   }    }
   if ($ENV{'form.posterlist'}) {    if ($ENV{'form.posterlist'}) {
       &Apache::loncommon::content_type($r,'text/html');        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.applysort'});
       $r->send_http_header;        &print_showposters($r,$symb,$ENV{'form.previous'},$feedurl,
       my $symb=$ENV{'form.posterlist'};   $ENV{'form.sortposts'});
       my $sortposts = $ENV{'form.sortposts'};  
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
       my $previous=$ENV{'form.previous'};  
       my $feedurl = &Apache::lonnet::clutter($url);  
  # backward compatibility (bulletin boards used to be 'wrapped')  
       if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
           $feedurl=~s|^/adm/wrapper||;  
       }  
       &print_showposters($r,$symb,$previous,$feedurl,$sortposts);  
       return OK;        return OK;
   }    }
   if ($ENV{'form.userpick'}) {    if ($ENV{'form.userpick'}) {
       &Apache::loncommon::content_type($r,'text/html');        my @posters = &Apache::loncommon::get_env_multiple('form.stuinfo');
       $r->send_http_header;        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.userpick'});
       my $symb=$ENV{'form.userpick'};  
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
       my $previous=$ENV{'form.previous'};  
 # backward compatibility (bulletin boards used to be 'wrapped')  
       my $ressymb=$symb;  
       unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
           $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
       }  
       my $sort=$ENV{'form.sortposts'};  
       my @posters = ();  
       if (ref($ENV{'form.stuinfo'}) eq 'ARRAY') {  
           @posters = $ENV{'form.stuinfo'};  
       } else {  
           $posters[0] = $ENV{'form.stuinfo'};  
       }  
       my $numpicks = @posters;        my $numpicks = @posters;
       if (defined($ENV{'form.userpick'})) {        my %discinfo;
           my %discinfo = ();        $discinfo{$symb.'_userpick'} = join('&',@posters);
           $discinfo{$ressymb.'_userpick'} = join('&',@posters);        &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'});
       }        &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0',
       my $feedurl = &Apache::lonnet::clutter($url);       '',$ENV{'form.previous'},$ENV{'form.sortposts'},'','','',
  # backward compatibility (bulletin boards used to be 'wrapped')       $numpicks);
       if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
           $feedurl=~s|^/adm/wrapper||;  
       }  
       &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0','',$previous,$sort,'','','',$numpicks);  
       return OK;        return OK;
   }    }
   if ($ENV{'form.applysort'}) {    if ($ENV{'form.applysort'}) {
       &Apache::loncommon::content_type($r,'text/html');        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.applysort'});
       $r->send_http_header;        &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0',
       my $symb=$ENV{'form.applysort'};       '',$ENV{'form.previous'},$ENV{'form.sortposts'},
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);       $ENV{'form.rolefilter'},$ENV{'form.statusfilter'},
       my $previous=$ENV{'form.previous'};       $ENV{'form.sectionpick'});
       my $sort = $ENV{'form.sortposts'};  
       my $rolefilter = $ENV{'form.rolefilter'};  
       my $statusfilter = $ENV{'form.statusfilter'};  
       my $secpick = $ENV{'form.sectionpick'};  
       my $feedurl = &Apache::lonnet::clutter($url);  
  # backward compatibility (bulletin boards used to be 'wrapped')  
       if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
           $feedurl=~s|^/adm/wrapper||;  
       }  
       &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0','',$previous,$sort,$rolefilter,$statusfilter,$secpick);  
       return OK;        return OK;
   } elsif ($ENV{'form.sortfilter'}) {    } elsif ($ENV{'form.cmd'} eq 'sortfilter') {
       &Apache::loncommon::content_type($r,'text/html');        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.symb'});
       $r->send_http_header;        &print_sortfilter_options($r,$symb,$ENV{'form.previous'},$feedurl);
       my $symb=$ENV{'form.sortfilter'};  
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
       my $previous=$ENV{'form.previous'};  
       my $feedurl = &Apache::lonnet::clutter($url);  
  # backward compatibility (bulletin boards used to be 'wrapped')  
       if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
           $feedurl=~s|^/adm/wrapper||;  
       }  
       &print_sortfilter_options($r,$symb,$previous,$feedurl);  
       return OK;        return OK;
   } elsif ($ENV{'form.navmaps'}) {    } elsif ($ENV{'form.navtime'}) {
       my %discinfo = ();        my %discinfo = ();
       my @resources = ();        my @resources = ();
       if ($ENV{'form.navmaps'} =~ /:/) {        if (defined($ENV{'form.navmaps'})) {
           @resources = split/:/,$ENV{'form.navmaps'};            if ($ENV{'form.navmaps'} =~ /:/) {
                 @resources = split/:/,$ENV{'form.navmaps'};
             } else {
                 @resources = ("$ENV{'form.navmaps'}");
             }
       } else {        } else {
           @resources = ("$ENV{'form.navmaps'}");            &has_discussion(\@resources);
       }        }
       my $numitems = @resources;        my $numitems = @resources;
       my $feedurl = '/adm/navmaps';        my $feedurl = '/adm/navmaps';
       if ($ENV{'form.navurl'}) {        if ($ENV{'form.navurl'}) { $feedurl .= '?'.$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',            'mnpa' => 'Marked "New" posts as read in a total of',
           'robb' => 'resources/bulletin boards.'            'robb' => 'resources/bulletin boards.',
             'twnp' => 'There are currently no resources or bulletin boards with unread discussion postings.'
       );               );       
       foreach (@resources) {        foreach (@resources) {
 # backward compatibility (bulletin boards used to be 'wrapped')  # backward compatibility (bulletin boards used to be 'wrapped')
           my $ressymb=$_;            my $ressymb=$_;
     &Apache::lonenc::check_decrypt(\$ressymb);
           if ($ressymb =~ m/bulletin___\d+___/) {            if ($ressymb =~ m/bulletin___\d+___/) {
               unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {                unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
                   $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper/|;                    $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper/|;
Line 2903  END Line 3012  END
           my $lastkey = $ressymb.'_lastread';            my $lastkey = $ressymb.'_lastread';
           $discinfo{$lastkey} = $ENV{'form.navtime'};            $discinfo{$lastkey} = $ENV{'form.navtime'};
       }        }
       &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});        my $textline = "<b>$lt{'mnpa'} $numitems $lt{'robb'}</b>";
         if ($numitems > 0) {
             &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',
        \%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
         } else {
             $textline = "<b>$lt{'twnp'}</b>";
         }
       &Apache::loncommon::content_type($r,'text/html');        &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;        $r->send_http_header;
       $r->print (<<ENDREDIR);        $r->print (<<ENDREDIR);
Line 2915  END Line 3030  END
 </head>  </head>
 <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>  <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>
 <img align="right" src="/adm/lonIcons/lonlogos.gif" />  <img align="right" src="/adm/lonIcons/lonlogos.gif" />
 <b>$lt{'mnpa'} $numitems $lt{'robb'}</b>  $textline
 <form name="reldt" action="$feedurl" target="loncapaclient">  <form name="reldt" action="$feedurl" target="loncapaclient">
 </form>  </form>
 <br /><a href="$feedurl">Continue</a>  <br /><a href="$feedurl">Continue</a>
Line 2924  END Line 3039  END
 ENDREDIR  ENDREDIR
       return OK;        return OK;
   } elsif ($ENV{'form.modifydisp'}) {    } elsif ($ENV{'form.modifydisp'}) {
       &Apache::loncommon::content_type($r,'text/html');        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.modifydisp'});
       $r->send_http_header;        my ($dispchgA,$dispchgB,$markchg,$toggchg) = 
       my $symb=$ENV{'form.modifydisp'};    split(/_/,$ENV{'form.changes'});
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);        &print_display_options($r,$symb,$ENV{'form.previous'},$dispchgA,
       my $previous=$ENV{'form.previous'};       $dispchgB,$markchg,$toggchg,$feedurl);
       my ($dispchgA,$dispchgB,$markchg,$toggchg) = split/_/,$ENV{'form.changes'};  
       my $feedurl = &Apache::lonnet::clutter($url);  
  # backward compatibility (bulletin boards used to be 'wrapped')    
       if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
           $feedurl=~s|^/adm/wrapper||;  
       }  
       &print_display_options($r,$symb,$previous,$dispchgA,$dispchgB,$markchg,$toggchg,$feedurl);  
       return OK;        return OK;
   } elsif (($ENV{'form.markondisp'}) || ($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || $ENV{'form.onlyunmark'} || $ENV{'form.toggoff'} || $ENV{'form.toggon'} ) {    } elsif ($ENV{'form.markondisp'} || $ENV{'form.markonread'} ||
       &Apache::loncommon::content_type($r,'text/html');     $ENV{'form.allposts'}   || $ENV{'form.onlyunread'} ||
       $r->send_http_header;     $ENV{'form.onlyunmark'} || $ENV{'form.toggoff'}    ||
       my $previous=$ENV{'form.previous'};     $ENV{'form.toggon'}     || $ENV{'form.markread'}) {
       my ($map,$ind,$url);        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.symb'});
       if ( ($ENV{'form.toggoff'}) || ($ENV{'form.toggon'}) ) {        my %discinfo;
 # ------------------------------ Modify setting for read/unread toggle for each post   # ------------------------ Modify setting for read/unread toggle for each post 
           my $symb=$ENV{'form.toggoff'}?$ENV{'form.toggoff'}:$ENV{'form.toggon'};        if ($ENV{'form.toggoff'}) { $discinfo{$symb.'_readtoggle'}=0; }
           my $ressymb = $symb;        if ($ENV{'form.toggon'})  { $discinfo{$symb.'_readtoggle'}=1; }
           ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  # --------- Modify setting for identification of 'NEW' posts in this discussion
           unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {        if ($ENV{'form.markondisp'}) {
               $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;    $discinfo{$symb.'_lastread'} = time;
           }    $discinfo{$symb.'_markondisp'} = 1;
           my %discinfo = ();        }
           my $toggkey = $ressymb.'_readtoggle';        if ($ENV{'form.markonread'}) {
           if ($ENV{'form.toggon'}) {    if ( $ENV{'form.previous'} > 0 ) {
               $discinfo{$toggkey} = 1;        $discinfo{$symb.'_lastread'} = $ENV{'form.previous'};
           } elsif ($ENV{'form.toggoff'}) {    }
               $discinfo{$toggkey} = 0;    $discinfo{$symb.'_markondisp'} = 0;
           }  
           &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});  
       }  
       if (($ENV{'form.markondisp'}) || ($ENV{'form.markonread'})) {  
 # ---------------------- Modify setting for identification of 'NEW' posts in this discussion  
           my $symb=$ENV{'form.markondisp'}?$ENV{'form.markondisp'}:$ENV{'form.markonread'};  
           my $ressymb = $symb;  
           ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
           unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
               $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
           }  
           my %discinfo = ();  
           my $lastkey = $ressymb.'_lastread';  
           my $ondispkey = $ressymb.'_markondisp';  
           if ($ENV{'form.markondisp'}) {  
               $discinfo{$lastkey} = time;  
               $discinfo{$ondispkey} = 1;  
           } elsif ($ENV{'form.markonread'}) {  
               if ( $previous > 0 ) {  
                   $discinfo{$lastkey} = $previous;  
               }  
               $discinfo{$ondispkey} = 0;  
           }  
           &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});  
       }  
       if (($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || ($ENV{'form.onlyunmark'}) ) {  
 # ----------------------------------------------------------------- Modify display setting for this discussion   
           my $symb;  
           if ($ENV{'form.allposts'}) {  
               $symb = $ENV{'form.allposts'};  
           } elsif ($ENV{'form.onlyunread'}) {  
               $symb = $ENV{'form.onlyunread'};  
           } else {  
               $symb = $ENV{'form.onlyunmark'};  
           }  
           my $ressymb = $symb;  
           ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
           unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
               $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
           }  
           my %discinfo = ();  
           if ($ENV{'form.allposts'}) {  
               $discinfo{$ressymb.'_showonlyunread'} = 0;  
               $discinfo{$ressymb.'_showonlyunmark'} = 0;  
           } elsif ($ENV{'form.onlyunread'}) {  
               $discinfo{$ressymb.'_showonlyunread'} = 1;  
           } else {  
               $discinfo{$ressymb.'_showonlyunmark'} = 1;  
           }  
           &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});  
       }  
       if (($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || ($ENV{'form.onlyunmark'}) ||($ENV{'form.toggoff'}) || ($ENV{'form.toggon'}) ) {  
           &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0','',$previous);  
       } else {  
           &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0');  
       }  
       return OK;  
   } elsif ($ENV{'form.markread'}) {  
 # ----------------------------------------------------------------- Mark new posts not NEW   
       &Apache::loncommon::content_type($r,'text/html');  
       $r->send_http_header;  
       my $symb=$ENV{'form.markread'};  
       my $ressymb = $symb;  
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
       unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
           $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
       }        }
       my %discinfo = ();  # --------------------------------- Modify display setting for this discussion 
       my $lastkey = $ressymb.'_lastread';        if ($ENV{'form.allposts'}) {
       $discinfo{$lastkey} = time;    $discinfo{$symb.'_showonlyunread'} = 0;
       &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});    $discinfo{$symb.'_showonlyunmark'} = 0;
       &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed reading status').'<br />','0','0');        }
         if ($ENV{'form.onlyunread'}) { $discinfo{$symb.'_showonlyunread'} = 1;  }
         if ($ENV{'form.onlyunmark'}) { $discinfo{$symb.'_showonlyunmark'} = 1;  }
   # ----------------------------------------------------- Mark new posts not NEW 
         if ($ENV{'form.markread'})   { $discinfo{$symb.'_lastread'} = time; }
         &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',
      \%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
         my $previous=$ENV{'form.previous'};
         if ($ENV{'form.markondisp'}) { $previous=undef; }
         &redirect_back($r,$feedurl,&mt('Changed display status').'<br />',
        '0','0','',$previous);
       return OK;        return OK;
   } elsif (($ENV{'form.hide'}) || ($ENV{'form.unhide'})) {    } elsif (($ENV{'form.hide'}) || ($ENV{'form.unhide'})) {
 # ----------------------------------------------------------------- Hide/unhide  # ----------------------------------------------------------------- Hide/unhide
     &Apache::loncommon::content_type($r,'text/html');        my $entry=$ENV{'form.hide'}?$ENV{'form.hide'}:$ENV{'form.unhide'};
     $r->send_http_header;        my ($symb,$idx)=split(/\:\:\:/,$entry);
         ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
     my $entry=$ENV{'form.hide'}?$ENV{'form.hide'}:$ENV{'form.unhide'};  
   
     my ($symb,$idx)=split(/\:\:\:/,$entry);        my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
     my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);                            $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
             $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
   
     my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},        my $currenthidden=$contrib{'hidden'};
                      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},        my $currentstudenthidden=$contrib{'studenthidden'};
      $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
   
                 my $crs='/'.$ENV{'request.course.id'};
     my $currenthidden=$contrib{'hidden'};        if ($ENV{'request.course.sec'}) {
     my $currentstudenthidden=$contrib{'studenthidden'};    $crs.='_'.$ENV{'request.course.sec'};
         }
         $crs=~s/\_/\//g;
         my $seeid=&Apache::lonnet::allowed('rin',$crs);
   
     my $crs='/'.$ENV{'request.course.id'};        if ($ENV{'form.hide'}) {
     if ($ENV{'request.course.sec'}) {    $currenthidden.='.'.$idx.'.';
         $crs.='_'.$ENV{'request.course.sec'};    unless ($seeid) {
     }        $currentstudenthidden.='.'.$idx.'.';
     $crs=~s/\_/\//g;    }
     my $seeid=&Apache::lonnet::allowed('rin',$crs);        } else {
         $currenthidden=~s/\.$idx\.//g;
     if ($ENV{'form.hide'}) {        }
  $currenthidden.='.'.$idx.'.';        my %newhash=('hidden' => $currenthidden);
         unless ($seeid) {        if ( ($ENV{'form.hide'}) && (!$seeid) ) {
             $currentstudenthidden.='.'.$idx.'.';    $newhash{'studenthidden'} = $currentstudenthidden;
         }        }
     } else {  
         $currenthidden=~s/\.$idx\.//g;  
     }  
     my %newhash=('hidden' => $currenthidden);  
     if ( ($ENV{'form.hide'}) && (!$seeid) ) {  
         $newhash{'studenthidden'} = $currentstudenthidden;  
     }  
   
     &Apache::lonnet::store(\%newhash,$symb,$ENV{'request.course.id'},        &Apache::lonnet::store(\%newhash,$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'});
   
     &redirect_back($r,&Apache::lonnet::clutter($url),        &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',
        &mt('Changed discussion status').'<br />','0','0','',$ENV{'form.previous'});       '0','0','',$ENV{'form.previous'});
   } elsif (($ENV{'form.threadedon'}) || ($ENV{'form.threadedoff'})) {        return OK;
       &Apache::loncommon::content_type($r,'text/html');    } elsif ($ENV{'form.cmd'}=~/^(threadedoff|threadedon)$/) {
       $r->send_http_header;        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($ENV{'form.symb'});
       if ($ENV{'form.threadedon'}) {        if ($ENV{'form.cmd'} eq 'threadedon') {
   &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 {        } else {
    &Apache::lonnet::del('environment',['threadeddiscussion']);     &Apache::lonnet::del('environment',['threadeddiscussion']);
   &Apache::lonnet::delenv('environment\.threadeddiscussion');    &Apache::lonnet::delenv('environment\.threadeddiscussion');
       }        }
       my $symb=$ENV{'form.threadedon'}?$ENV{'form.threadedon'}:$ENV{'form.threadedoff'};        &redirect_back($r,$feedurl,&mt('Changed discussion view mode').'<br />',
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);       '0','0','',$ENV{'form.previous'});
       &redirect_back($r,&Apache::lonnet::clutter($url),        return OK;
      &mt('Changed discussion view mode').'<br />','0','0','',$ENV{'form.previous'});  
   } elsif ($ENV{'form.deldisc'}) {    } elsif ($ENV{'form.deldisc'}) {
 # --------------------------------------------------------------- Hide for good  # --------------------------------------------------------------- Hide for good
     &Apache::loncommon::content_type($r,'text/html');        my ($symb,$idx)=split(/\:\:\:/,$ENV{'form.deldisc'});
     $r->send_http_header;        ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
         my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
     my $entry=$ENV{'form.deldisc'};                            $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
             $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
     my ($symb,$idx)=split(/\:\:\:/,$entry);        my %newhash=('deleted' => $contrib{'deleted'}.".$idx.");
     my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);        &Apache::lonnet::store(\%newhash,$symb,$ENV{'request.course.id'},
      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
     my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},     $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
                      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},        &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',
      $ENV{'course.'.$ENV{'request.course.id'}.'.num'});       '0','0','',$ENV{'form.previous'});
         return OK;
           
     my $currentdeleted=$contrib{'deleted'};  
       
     $currentdeleted.='.'.$idx.'.';  
   
     my %newhash=('deleted' => $currentdeleted);  
   
     &Apache::lonnet::store(\%newhash,$symb,$ENV{'request.course.id'},  
                      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
      $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
   
     &redirect_back($r,&Apache::lonnet::clutter($url),  
        &mt('Changed discussion status').'<br />','0','0','',$ENV{'form.previous'});  
   } elsif ($ENV{'form.preview'}) {    } elsif ($ENV{'form.preview'}) {
 # -------------------------------------------------------- User wants a preview  # -------------------------------------------------------- User wants a preview
       $r->content_type('text/html');  
       $r->send_http_header;  
       &show_preview($r);        &show_preview($r);
         return OK;
   } elsif ($ENV{'form.attach'}) {    } elsif ($ENV{'form.attach'}) {
 # -------------------------------------------------------- Work on attachments  # -------------------------------------------------------- Work on attachments
       &Apache::loncommon::content_type($r,'text/html');        &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;        $r->send_http_header;
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','addnewattach','delnewattach','timestamp','numoldver','idx','anondiscuss','discuss']);        &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','addnewattach','delnewattach','timestamp','numoldver','idx','anondiscuss','discuss']);
       my @currnewattach = ();        my (@currnewattach,@currdelold,@keepold);
       my @currdelold = ();  
       my @keepold = ();  
       &process_attachments(\@currnewattach,\@currdelold,\@keepold);        &process_attachments(\@currnewattach,\@currdelold,\@keepold);
       if (exists($ENV{'form.addnewattach.filename'})) {        if (exists($ENV{'form.addnewattach.filename'})) {
           unless (length($ENV{'form.addnewattach'})>131072) {            unless (length($ENV{'form.addnewattach'})>131072) {
               my $subdir = 'feedback/'.$ENV{'form.timestamp'};                my $subdir = 'feedback/'.$ENV{'form.timestamp'};
               my $newattachment=&Apache::lonnet::userfileupload('addnewattach',undef,$subdir);                my $newattachment=&Apache::lonnet::userfileupload('addnewattach',undef,$subdir);
               push @currnewattach, $newattachment;        push @currnewattach, $newattachment;
           }            }
       }        }
       my $attachmenturls = '';        my $attachmenturls;
         my ($symb) = &get_feedurl_and_clean_symb($ENV{'form.attach'});
       my $idx = $ENV{'form.idx'};        my $idx = $ENV{'form.idx'};
       my $symb = $ENV{'form.attach'};  
       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'},                           $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
                          $ENV{'course.'.$ENV{'request.course.id'}.'.num'});                           $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
           $attachmenturls = $contrib{$idx.':attachmenturl'};            $attachmenturls = $contrib{$idx.':attachmenturl'};
       }        }
       &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,$attachmenturls);        &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,
   } elsif ($ENV{'form.chgreads'}) {    $attachmenturls);
       &Apache::loncommon::content_type($r,'text/html');        return OK;
       $r->send_http_header;  
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ENV{'form.chgreads'});  
       &redirect_back($r,&Apache::lonnet::clutter($url),  
        &mt('Changed read status').'<br />','0','0');  
   } elsif ($ENV{'form.export'}) {    } elsif ($ENV{'form.export'}) {
       &Apache::loncommon::content_type($r,'text/html');        &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;        $r->send_http_header;
       my $symb=$ENV{'form.export'};        my ($symb,$feedurl) = &get_feedurl_and_clean_symb($ENV{'form.export'});
       my $mode;        my $mode='board';
       my $status='OPEN';        my $status='OPEN';
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
       my $previous=$ENV{'form.previous'};        my $previous=$ENV{'form.previous'};
       my $feedurl = &Apache::lonnet::clutter($url);  
  # backward compatibility (bulletin boards used to be 'wrapped')  
       if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
           $mode = 'board';  
           $feedurl=~s|^/adm/wrapper||;  
       }  
       if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library)$/) {        if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library)$/) {
           $mode='problem';            $mode='problem';
           $status=$Apache::inputtags::status[-1];            $status=$Apache::inputtags::status[-1];
Line 3175  ENDREDIR Line 3194  ENDREDIR
       return OK;        return OK;
   } else {    } else {
 # ------------------------------------------------------------- Normal feedback  # ------------------------------------------------------------- Normal feedback
   my $feedurl=$ENV{'form.postdata'};        my $feedurl=$ENV{'form.postdata'};
   $feedurl=~s/^http\:\/\///;        $feedurl=~s/^http\:\/\///;
   $feedurl=~s/^$ENV{'SERVER_NAME'}//;        $feedurl=~s/^$ENV{'SERVER_NAME'}//;
   $feedurl=~s/^$ENV{'HTTP_HOST'}//;        $feedurl=~s/^$ENV{'HTTP_HOST'}//;
   $feedurl=~s/\?.+$//;        $feedurl=~s/\?.+$//;
   
   my $symb;        my $symb;
   if ($ENV{'form.replydisc'}) {        if ($ENV{'form.replydisc'}) {
       $symb=(split(/\:\:\:/,$ENV{'form.replydisc'}))[0];    $symb=(split(/\:\:\:/,$ENV{'form.replydisc'}))[0];
       my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);    my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
       $feedurl=&Apache::lonnet::clutter($url);    $feedurl=&Apache::lonnet::clutter($url);
   } elsif ($ENV{'form.editdisc'}) {        } elsif ($ENV{'form.editdisc'}) {
       $symb=(split(/\:\:\:/,$ENV{'form.editdisc'}))[0];    $symb=(split(/\:\:\:/,$ENV{'form.editdisc'}))[0];
       my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);  
       $feedurl=&Apache::lonnet::clutter($url);  
   } elsif ($ENV{'form.origpage'}) {  
       $symb="";   
   } else {  
       $symb=&Apache::lonnet::symbread($feedurl);  
   }  
   unless ($symb) {  
       $symb=$ENV{'form.symb'};  
       if ($symb) {  
   my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);    my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
           $feedurl=&Apache::lonnet::clutter($url);    $feedurl=&Apache::lonnet::clutter($url);
         } elsif ($ENV{'form.origpage'}) {
     $symb=""; 
         } else {
     $symb=&Apache::lonnet::symbread($feedurl);
         }
         unless ($symb) {
     $symb=$ENV{'form.symb'};
     if ($symb) {
         my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
         $feedurl=&Apache::lonnet::clutter($url);
     }
         }
         &Apache::lonenc::check_decrypt(\$symb);
         my $goahead=1;
         if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form)$/) {
     unless ($symb) { $goahead=0; }
         }
         # backward compatibility (bulletin boards used to be 'wrapped')
         if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
     $feedurl=~s|^/adm/wrapper||;
         }
         if (!$goahead) {
             # Ambiguous Problem Resource
     $r->internal_redirect('/adm/ambiguous');
     return OK;
       }        }
   }  
   my $goahead=1;  
   if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form)$/) {  
       unless ($symb) { $goahead=0; }  
   }  
   # backward compatibility (bulletin boards used to be 'wrapped')  
   if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
       $feedurl=~s|^/adm/wrapper||;  
   }  
   if ($goahead) {  
 # Go ahead with feedback, no ambiguous reference  # Go ahead with feedback, no ambiguous reference
     &Apache::loncommon::content_type($r,'text/html');        unless (
     $r->send_http_header;    (
        ($feedurl=~m:^/res:) && ($feedurl!~m:^/res/adm:)
     if (     ) 
       (    || 
        ($feedurl=~m:^/res:) && ($feedurl!~m:^/res/adm:)    ($ENV{'request.course.id'} && ($feedurl!~m:^/adm:))
       )     ||
       ||     ($ENV{'request.course.id'} && ($symb=~/^bulletin\_\_\_/))
       ($ENV{'request.course.id'} && ($feedurl!~m:^/adm:))    ) {
       ||    &Apache::loncommon::content_type($r,'text/html');
       ($ENV{'request.course.id'} && ($symb=~/^bulletin\_\_\_/))    $r->send_http_header;
      ) {  # Unable to give feedback
     &no_redirect_back($r,$feedurl);
         }
 # --------------------------------------------------- Print login screen header  # --------------------------------------------------- Print login screen header
     unless ($ENV{'form.sendit'}) {        unless ($ENV{'form.sendit'}) {
       my $options=&screen_header($feedurl);    &Apache::loncommon::content_type($r,'text/html');
       if ($options) {    $r->send_http_header;
         &mail_screen($r,$feedurl,$options);    my $options=&screen_header($feedurl,$symb);
       } else {    if ($options) {
  &fail_redirect($r,$feedurl);        &mail_screen($r,$feedurl,$options);
     } else {
         &fail_redirect($r,$feedurl);
     }
     return OK;
       }        }
     } else {  
               
 # Get previous user input  # Get previous user input
       my $prevattempts=&Apache::loncommon::get_previous_attempt(        my $prevattempts=&Apache::loncommon::get_previous_attempt(
             $symb,$ENV{'user.name'},$ENV{'user.domain'},                                     $symb,$ENV{'user.name'},$ENV{'user.domain'},
             $ENV{'request.course.id'});     $ENV{'request.course.id'});
   
 # Get output from resource  # Get output from resource
       my $usersaw=&resource_output($feedurl);        my $usersaw=&resource_output($feedurl);
Line 3245  ENDREDIR Line 3274  ENDREDIR
 # Get resource answer (need to allow student to view grades for this to work)  # Get resource answer (need to allow student to view grades for this to work)
       &Apache::lonnet::appenv(('allowed.vgr'=>'F'));        &Apache::lonnet::appenv(('allowed.vgr'=>'F'));
       my $useranswer=&Apache::loncommon::get_student_answers(        my $useranswer=&Apache::loncommon::get_student_answers(
                        $symb,$ENV{'user.name'},$ENV{'user.domain'},                                     $symb,$ENV{'user.name'},$ENV{'user.domain'},
        $ENV{'request.course.id'});                     $ENV{'request.course.id'});
       &Apache::lonnet::delenv('allowed.vgr');        &Apache::lonnet::delenv('allowed.vgr');
 # Get attachments, if any, and not too large  # Get attachments, if any, and not too large
       my $attachmenturl='';        my $attachmenturl='';
       if (($ENV{'form.origpage'}) || ($ENV{'form.editdisc'}) || ($ENV{'form.replydisc'})) {        if (($ENV{'form.origpage'}) || ($ENV{'form.editdisc'}) ||
           my ($symb,$idx);    ($ENV{'form.replydisc'})) {
           if ($ENV{'form.replydisc'}) {    my ($symb,$idx);
               ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'});    if ($ENV{'form.replydisc'}) {
           } elsif ($ENV{'form.editdisc'}) {        ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'});
               ($symb,$idx)=split(/\:\:\:/,$ENV{'form.editdisc'});    } elsif ($ENV{'form.editdisc'}) {
           } elsif ($ENV{'form.origpage'}) {        ($symb,$idx)=split(/\:\:\:/,$ENV{'form.editdisc'});
               $symb = $ENV{'form.symb'};    } elsif ($ENV{'form.origpage'}) {
           }        $symb = $ENV{'form.symb'};
           my @currnewattach = ();    }
           my @deloldattach = ();    &Apache::lonenc::check_decrypt(\$symb);
           my @keepold = ();    my @currnewattach = ();
           &process_attachments(\@currnewattach,\@deloldattach,\@keepold);    my @deloldattach = ();
           $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|;    my @keepold = ();
           $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);    &process_attachments(\@currnewattach,\@deloldattach,\@keepold);
     $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|;
     $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);
       } elsif ($ENV{'form.attachment.filename'}) {        } elsif ($ENV{'form.attachment.filename'}) {
   unless (length($ENV{'form.attachment'})>131072) {    unless (length($ENV{'form.attachment'})>131072) {
       $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');        $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');
Line 3275  ENDREDIR Line 3306  ENDREDIR
   
 # Assemble email  # Assemble email
       my ($email,$citations)=&assemble_email($feedurl,$message,$prevattempts,        my ($email,$citations)=&assemble_email($feedurl,$message,$prevattempts,
           $usersaw,$useranswer);       $usersaw,$useranswer);
     
 # Who gets this?  # Who gets this?
       my ($typestyle,%to) = &decide_receiver($feedurl);        my ($typestyle,%to) = &decide_receiver($feedurl);
   
 # Actually send mail  # Actually send mail
       my ($status,$numsent)=&send_msg($feedurl,$email,$citations,        my ($status,$numsent)=&send_msg($feedurl,$email,$citations,
           $attachmenturl,%to);        $attachmenturl,%to);
   
 # Discussion? Store that.  # Discussion? Store that.
   
       my $numpost=0;        my $numpost=0;
       if ($ENV{'form.discuss'}) {        if ($ENV{'form.discuss'} || $ENV{'form.anondiscuss'}) {
           my $subject = &clear_out_html($ENV{'form.subject'});    my $subject = &clear_out_html($ENV{'form.subject'});
   $typestyle.=&adddiscuss($symb,$message,0,$attachmenturl,$subject);    my $anonmode=(defined($ENV{'form.anondiscuss'}));
   $numpost++;    $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,
       }    $subject);
   
       if ($ENV{'form.anondiscuss'}) {  
           my $subject = &clear_out_html($ENV{'form.subject'});  
   $typestyle.=&adddiscuss($symb,$message,1,$attachmenturl,$subject);  
   $numpost++;    $numpost++;
       }        }
     
   
 # Receipt screen and redirect back to where came from  # Receipt screen and redirect back to where came from
       &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$status,$ENV{'form.previous'});        &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$status,$ENV{'form.previous'});
   
     }  
    } else {  
 # Unable to give feedback  
     &no_redirect_back($r,$feedurl);  
    }  
   } else {  
 # Ambiguous Problem Resource  
       if ( &Apache::lonnet::mod_perl_version() == 2 ) {  
   &Apache::lonnet::cleanenv();  
       }  
       $r->internal_redirect('/adm/ambiguous');  
   }    }
 }  
   return OK;    return OK;
 }   } 
   
   sub wrap_symb {
       my ($ressymb)=@_;
       if ($ressymb =~ /bulletin___\d+___/) {
           unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
               $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;
           }
       }
       return $ressymb;
   }
   sub dewrapper {
       my ($feedurl)=@_;
       if ($$feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
           $$feedurl=~s|^/adm/wrapper||;
       }
   }
   
   sub get_feedurl {
       my ($symb)=@_;
       my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
       my $feedurl = &Apache::lonnet::clutter($url);
       &dewrapper(\$feedurl);
       return $feedurl;
   }
   
   sub get_feedurl_and_clean_symb {
       my ($symb)=@_;
       &Apache::lonenc::check_decrypt(\$symb);
   # backward compatibility (bulletin boards used to be 'wrapped')
       unless ($symb =~ m|bulletin___\d+___adm/wrapper|) {
    $symb=~s|(bulletin___\d+___)|$1adm/wrapper|;
       }
       my $feedurl = &get_feedurl($symb);
       return ($symb,$feedurl);
   }
 1;  1;
 __END__  __END__

Removed from v.1.127  
changed lines
  Added in v.1.143


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>