Diff for /loncom/interface/lonfeedback.pm between versions 1.120 and 1.190

version 1.120, 2004/08/31 18:28:18 version 1.190, 2006/04/10 21:55:48
Line 35  use Apache::lonmsg(); Line 35  use Apache::lonmsg();
 use Apache::loncommon();  use Apache::loncommon();
 use Apache::lontexconvert();  use Apache::lontexconvert();
 use Apache::lonlocal; # must not have ()  use Apache::lonlocal; # must not have ()
   use Apache::lonnet;
 use Apache::lonhtmlcommon();  use Apache::lonhtmlcommon();
   use Apache::lonnavmaps;
   use Apache::lonenc();
   use Apache::lonrss();
 use HTML::LCParser();  use HTML::LCParser();
 use Apache::lonspeller();  use Apache::lonspeller();
 use Cwd;  use Cwd;
   
 sub discussion_open {  sub discussion_open {
     my ($status)=@_;      my ($status,$symb)=@_;
       if ($env{'request.role.adv'}) { return 1; }
     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');      my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);
     if (defined($close) && $close ne '' && $close < time) {      if (defined($close) && $close ne '' && $close < time) {
  return 0;   return 0;
     }      }
Line 59  sub discussion_visible { Line 64  sub discussion_visible {
     if (not &discussion_open($status)) {      if (not &discussion_open($status)) {
  my $hidden=&Apache::lonnet::EXT('resource.0.discusshide');   my $hidden=&Apache::lonnet::EXT('resource.0.discusshide');
  if (lc($hidden) eq 'yes' or $hidden eq '' or !defined($hidden))  {   if (lc($hidden) eq 'yes' or $hidden eq '' or !defined($hidden))  {
     return 0;      if (!$env{'request.role.adv'}) { return 0; }
  }   }
     }      }
     return 1;      return 1;
 }  }
   
 sub list_discussion {  sub list_discussion {
     my ($mode,$status,$symb)=@_;      my ($mode,$status,$ressymb,$imsextras)=@_;
     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';
           }
       }
       if (defined($imsextras)) {
           if ($$imsextras{'caller'} eq 'imsexport') {
             $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;
     if ($mode eq 'board') { $discussiononly=1; }      if ($mode eq 'board') { $discussiononly=1; }
     unless ($ENV{'request.course.id'}) { return ''; }      unless ($env{'request.course.id'}) { return ''; }
     my $crs='/'.$ENV{'request.course.id'};      my $crs='/'.$env{'request.course.id'};
     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|task)$/));
       
     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 114  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_'.$cid.'_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;
     my $showunmark = 0;       my $showunmark = 0; 
Line 122  sub list_discussion { Line 128  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 = ();
     my $sectionpick = $ENV{'form.sectionpick'};      if ($env{'form.sectionpick'} =~ /,/) {
     my $totposters = $ENV{'form.totposters'};          @sectionpick = split/,/,$env{'form.sectionpick'};
     $previous = $ENV{'form.previous'};      } 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'};
       $previous = $env{'form.previous'};
     if ($previous > 0) {      if ($previous > 0) {
         $prevread = $previous;          $prevread = $previous;
     } elsif (defined($dischash{$lastkey})) {      } elsif (defined($dischash{$lastkey})) {
Line 139  sub list_discussion { Line 155  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.'.$cid.'.domain'},
      $env{'course.'.$cid.'.num'});
         foreach (keys %roleshash) {          foreach (keys %roleshash) {
             my ($role,$uname,$udom,$sec) = split/:/,$_;              my ($role,$uname,$udom,$sec) = split/:/,$_;
               if ($role =~ /^cr/) {
                   $role = 'cr';
               }
             my ($end,$start) = split/:/,$roleshash{$_};              my ($end,$start) = split/:/,$roleshash{$_};
             my $now = time;              my $now = time;
             my $status = 'Active';              my $status = 'Active';
             if (($now < $start) || ($end > 0 && $now > $end)) {              if (($now < $start) || ($end > 0 && $now > $end)) {
                 $status = 'Expired';                  $status = 'Expired';
             }              }
             push @{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status;              if ($uname && $udom) { 
                   push @{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status;
               }
         }          }
         my ($classlist) = &Apache::loncoursedata::get_classlist(          my ($classlist) = &Apache::loncoursedata::get_classlist(
                               $ENV{'request.course.id'},                                $env{'course.'.$cid.'.domain'},
                               $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},                                $env{'course.'.$cid.'.num'});
                               $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
         my $sec_index = &Apache::loncoursedata::CL_SECTION();          my $sec_index = &Apache::loncoursedata::CL_SECTION();
         my $status_index = &Apache::loncoursedata::CL_STATUS();          my $status_index = &Apache::loncoursedata::CL_STATUS();
         while (my ($student,$data) = each %$classlist) {          while (my ($student,$data) = each %$classlist) {
Line 165  sub list_discussion { Line 187  sub list_discussion {
     }      }
   
 # Get discussion display default settings for user  # Get discussion display default settings for user
     my %userenv = &Apache::lonnet::get('environment',['discdisplay','discmarkread'],$ENV{'user.domain'},$ENV{'user.name'});      if ($env{'environment.discdisplay'} eq 'unread') {
     my $discdisplay=$userenv{'discdisplay'};  
     if ($discdisplay eq 'unread') {  
         $showonlyunread = 1;          $showonlyunread = 1;
     }      }
     my $discmarkread=$userenv{'discmarkread'};      if ($env{'environment.discmarkread'} eq 'ondisp') {
     if ($discmarkread eq 'ondisp') {  
         $markondisp = 1;          $markondisp = 1;
     }      }
   
 # Override user's default if user specified display setting for this discussion  # Override user's default if user specified display setting for this discussion
     if (defined($dischash{$ondispkey})) {      if (defined($dischash{$ondispkey})) {
         $markondisp = $dischash{$ondispkey};          unless ($dischash{$ondispkey} eq '') {
               $markondisp = $dischash{$ondispkey};
           }
     }      }
     if ($markondisp) {      if ($markondisp) {
         $discinfo{$lastkey} = time;          $discinfo{$lastkey} = time;
     }      }
   
     if (defined($dischash{$showkey})) {      if (defined($dischash{$showkey})) {
         $showonlyunread = $dischash{$showkey};          unless ($dischash{$showkey} eq '') {
               $showonlyunread = $dischash{$showkey};
           }
     }      }
   
     if (defined($dischash{$markkey})) {      if (defined($dischash{$markkey})) {
         $showunmark = $dischash{$markkey};          unless ($dischash{$markkey} eq '') {
               $showunmark = $dischash{$markkey};
           }
     }      }
   
     if (defined($dischash{$visitkey})) {      if (defined($dischash{$visitkey})) {
         $visit = $dischash{$visitkey};          unless ($dischash{$visitkey} eq '') {
               $visit = $dischash{$visitkey};
           }
     }      }
     $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 213  sub list_discussion { Line 238  sub list_discussion {
     my %notshown = ();      my %notshown = ();
     my %newitem = ();      my %newitem = ();
     my $maxdepth=0;      my $maxdepth=0;
       my %anonhash=();
       my $anoncnt=0;
     my $target='';      my $target='';
     unless ($ENV{'browser.interface'} eq 'textual' ||      unless ($env{'browser.interface'} eq 'textual' ||
     $ENV{'environment.remote'} eq 'off' ) {      $env{'environment.remote'} eq 'off' ) {
  $target='target="LONcom"';   $target='target="LONcom"';
     }      }
   
     my $now = time;      my $now = time;
     $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_'.$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,$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,\%anonhash,$anoncnt);
   
     my $discussion='';      my $discussion='';
     my $manifestfile;      my $manifestfile;
Line 235  sub list_discussion { Line 261  sub list_discussion {
   
     my $function = &Apache::loncommon::get_users_function();      my $function = &Apache::loncommon::get_users_function();
     my $color = &Apache::loncommon::designparm($function.'.tabbg',      my $color = &Apache::loncommon::designparm($function.'.tabbg',
                                                     $ENV{'user.domain'});                                                      $env{'user.domain'});
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'cuse' => 'Current discussion settings',          'cuse' => 'Current discussion settings',
         'allposts' => 'All posts',          'allposts' => 'All posts',
Line 301  sub list_discussion { Line 327  sub list_discussion {
     if ($visible) {      if ($visible) {
 # Print the discusssion  # Print the discusssion
         if ($outputtarget eq 'tex') {          if ($outputtarget eq 'tex') {
             $discussion.='<tex>\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{DISCUSSIONS}\makebox[2 cm][b]{\hrulefill}'.
                          '\vskip 0 mm\noindent\textbf{'.$lt{'cuse'}.'}:\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') {
 # Create temporary directory if this is an export  # Create temporary directory if this is an export
             my $now = time;              my $now = time;
             $tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';              if ((defined($imsextras)) && ($$imsextras{'caller'} eq 'imsexport')) {
             if (!-e $tempexport) {                  $tempexport = $$imsextras{'tempexport'};
                 mkdir($tempexport,0700);                  if (!-e $tempexport) {
             }                      mkdir($tempexport,0700);
             $tempexport .= '/'.$now;                  }
             if (!-e $tempexport) {                  $tempexport .= '/'.$$imsextras{'count'};
                 mkdir($tempexport,0700);                  if (!-e $tempexport) {
                       mkdir($tempexport,0700);
                   }
               } else {
                   $tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';
                   if (!-e $tempexport) {
                       mkdir($tempexport,0700);
                   }
                   $tempexport .= '/'.$now;
                   if (!-e $tempexport) {
                       mkdir($tempexport,0700);
                   }
                   $tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'};
             }              }
             $tempexport .= '/'.$ENV{'user.domain'}.'_'.$ENV{'user.name'};  
             if (!-e $tempexport) {              if (!-e $tempexport) {
                 mkdir($tempexport,0700);                  mkdir($tempexport,0700);
             }              }
 # open manifest file  # open manifest file
             my $manifest = '/imsmanifest.xml';              my $manifest = '/imsmanifest.xml';
             my $manifestfilename = $tempexport.$manifest;              my $manifestfilename = $tempexport.$manifest;
             print STDERR "manifestfilename is $manifestfilename\n";  
             if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {              if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {
                 $manifestok=1;                  $manifestok=1;
                 print $manifestfile qq|                  print $manifestfile qq|
Line 355  imscp_v1p1.xsd http://www.imsglobal.org/ Line 391  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>';
       my $escsymb=&Apache::lonnet::escape($ressymb);
     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='.$escsymb;
  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='.$escsymb;
  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='.$escsymb;
                 if ($newpostsflag) {                  if ($newpostsflag) {
                     $discussion .= '&previous='.$prevread;                      $discussion .= '&previous='.$prevread;
                 }                  }
Line 378  imscp_v1p1.xsd http://www.imsglobal.org/ Line 415  imscp_v1p1.xsd http://www.imsglobal.org/
             } else {              } else {
                 $discussion .= '<td align="left">';                  $discussion .= '<td align="left">';
             }              }
             $discussion .='<a href= "/adm/feedback?export='.$ressymb;              $discussion .='<a href= "/adm/feedback?export='.$escsymb;
             if ($newpostsflag) {              if ($newpostsflag) {
                 $discussion .= '&previous='.$prevread;                  $discussion .= '&previous='.$prevread;
             }              }
             $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/preferences?action=changediscussions">'.
    &mt('Preferences on what is marked as NEW').
    '</a><br /><a href="/adm/feedback?markread=1&amp;symb='.$escsymb.'">'.&mt('Mark NEW posts no longer new').'</a>';
  } else {   } else {
     $discussion .= '<td>&nbsp;</td>';      $discussion .= '<td>&nbsp;</td>';
  }   }
Line 398  imscp_v1p1.xsd http://www.imsglobal.org/ Line 437  imscp_v1p1.xsd http://www.imsglobal.org/
             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='.$ressymb;                           '<a href="/adm/feedback?allposts=1&amp;symb='.$escsymb;
                 if ($newpostsflag) {                  if ($newpostsflag) {
                     $discussion .= '&previous='.$prevread;                      $discussion .= '&previous='.$prevread;
                 }                  }
Line 436  imscp_v1p1.xsd http://www.imsglobal.org/ Line 475  imscp_v1p1.xsd http://www.imsglobal.org/
                  }                   }
             }              }
         } else {          } else {
             $sortposts = 'ascdate';  
             @showposts =  (sort { $a <=> $b } keys %alldiscussion);              @showposts =  (sort { $a <=> $b } keys %alldiscussion);
         }          }
         my $currdepth = 0;          my $currdepth = 0;
         my $firstidx = $alldiscussion{$showposts[0]};          my $firstidx = $alldiscussion{$showposts[0]};
         foreach (@showposts) {          foreach (@showposts) {
             unless (($sortposts eq 'thread') || ($sortposts eq 'ascdate' && $ENV{'environment.threadeddiscussion'}) || ($outputtarget eq 'export')) {              unless (($sortposts eq 'thread') || (($sortposts eq '') && ($env{'environment.threadeddiscussion'})) || ($outputtarget eq 'export')) {
                 $alldiscussion{$_} = $_;                  $alldiscussion{$_} = $_;
             }              }
             unless ( ($notshown{$alldiscussion{$_}} eq '1') || ($shown{$alldiscussion{$_}} == 0) ) {              unless ( ($notshown{$alldiscussion{$_}} eq '1') || ($shown{$alldiscussion{$_}} == 0) ) {
Line 474  imscp_v1p1.xsd http://www.imsglobal.org/ Line 512  imscp_v1p1.xsd http://www.imsglobal.org/
                     my $postfilename = $alldiscussion{$_}.'-'.$imsitems{$alldiscussion{$_}}{'timestamp'}.'.html';                      my $postfilename = $alldiscussion{$_}.'-'.$imsitems{$alldiscussion{$_}}{'timestamp'}.'.html';
                     if ($manifestok) {                      if ($manifestok) {
                         if (($depth[$alldiscussion{$_}] <= $currdepth) && ($alldiscussion{$_} != $firstidx)) {                          if (($depth[$alldiscussion{$_}] <= $currdepth) && ($alldiscussion{$_} != $firstidx)) {
                             print STDERR "depth is $depth[$alldiscussion{$_}], currdepth is $currdepth, idx is $alldiscussion{$_}, firstidx is $firstidx\n";  
                             print $manifestfile '  </item>'."\n";                              print $manifestfile '  </item>'."\n";
                         }                          }
                         $currdepth = $depth[$alldiscussion{$_}];                          $currdepth = $depth[$alldiscussion{$_}];
Line 483  imscp_v1p1.xsd http://www.imsglobal.org/ Line 520  imscp_v1p1.xsd http://www.imsglobal.org/
         $imsitems{$alldiscussion{$_}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$_}.'">'.          $imsitems{$alldiscussion{$_}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$_}.'">'.
         '<title>'.$imsitems{$alldiscussion{$_}}{'title'}.'</title>';          '<title>'.$imsitems{$alldiscussion{$_}}{'title'}.'</title>';
                         $imsresources .= "\n".                          $imsresources .= "\n".
     '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$_}.'" type="webcontent" href="'.$postfilename.'">'.      '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$_}.'" type="webcontent" href="'.$postfilename.'">'."\n".
       '<file href="'.$alldiscussion{$_}.'.html">'."\n".        '<file href="'.$postfilename.'">'."\n".
       $imsfiles{$alldiscussion{$_}}{$imsitems{$alldiscussion{$_}}{'currversion'}}."\n".        $imsfiles{$alldiscussion{$_}}{$imsitems{$alldiscussion{$_}}{'currversion'}}."\n".
     '</resource>';      '</resource>';
                     }                      }
Line 541  END Line 578  END
             $discussion .= <<END;              $discussion .= <<END;
                    </font></td>                     </font></td>
                    <td>&nbsp;</td>                     <td>&nbsp;</td>
                    <td>                     <td align="left">
                     <font size="-1"><b><a href="$chglink">$lt{'chgt'}</a>?</font></b>                      <font size="-1"><b><a href="$chglink">$lt{'chgt'}</a>?</font></b>
                    </td>                     </td>
                   </tr>                    </tr>
                  </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>-';
                           foreach (@rolefilter) {
                               $filterchoice .= '&nbsp;'.$role_types{$_}.',';
                           }
                           $filterchoice =~ s/,$//;
                           $filterchoice .= '<br />&nbsp;&nbsp&nbsp;&nbsp;&nbsp;&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 580  END Line 658  END
 </manifest>  </manifest>
                 |;                  |;
                 close($manifestfile);                  close($manifestfile);
                   if ((defined($imsextras)) && ($$imsextras{'caller'} eq 'imsexport')) {
                       $discussion = $copyresult;
                   } else {
   
 #Create zip file in prtspool  #Create zip file in prtspool
   
                 my $imszipfile = '/prtspool/'.                      my $imszipfile = '/prtspool/'.
                 $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.                      $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
                      time.'_'.rand(1000000000).'.zip';                           time.'_'.rand(1000000000).'.zip';
     # zip can cause an sh launch which can pass along all of %ENV                      my $cwd = &getcwd(); 
     # which can be too large for /bin/sh to handle                      my $imszip = '/home/httpd/'.$imszipfile;
                 my %oldENV=%ENV;                      chdir $tempexport;
                 undef(%ENV);                      open(OUTPUT, "zip -r $imszip *  2> /dev/null |");
                 my $cwd = &getcwd();                       close(OUTPUT);
                 my $imszip = '/home/httpd/'.$imszipfile;                      chdir $cwd;
                 chdir $tempexport;                      $discussion .= 'Download the zip file from <a href="'.$imszipfile.'">Discussion Posting Archive</a><br />';
                 open(OUTPUT, "zip -r $imszip *  2> /dev/null |");                      if ($copyresult) {
                 close(OUTPUT);                          $discussion .= 'The following errors occurred during export - <br />'.$copyresult;
                 chdir $cwd;                      }
                 %ENV=%oldENV;  
                 undef(%oldENV);  
                 $discussion .= 'Download the zip file from <a href="'.$imszipfile.'">Discussion Posting Archive</a><br />';  
                 if ($copyresult) {  
                     $discussion .= 'The following errors occurred during export - '.$copyresult;  
                 }                  }
             } else {              } else {
                 $discussion .= '<br />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 .= '<br />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 />';
Line 616  END Line 692  END
         my @currdelold = ();          my @currdelold = ();
         my $comment = '';          my $comment = '';
         my $subject = '';          my $subject = '';
         if ($ENV{'form.origpage'}) {          if ($env{'form.origpage'}) {
             &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['addnewattach','deloldattach','delnewattach','timestamp','idx','subject','comment']);              &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['addnewattach','deloldattach','delnewattach','timestamp','idx','subject','comment']);
             $subject = &HTML::Entities::encode($ENV{'form.subject'},'<>&"');              $subject = &Apache::lonnet::unescape($env{'form.subject'});
             $comment = &HTML::Entities::encode($ENV{'form.comment'},'<>&"');              $comment = &Apache::lonnet::unescape($env{'form.comment'});
             my @keepold = ();              my @keepold = ();
             &process_attachments(\@currnewattach,\@currdelold,\@keepold);              &process_attachments(\@currnewattach,\@currdelold,\@keepold);
             if (@currnewattach > 0) {              if (@currnewattach > 0) {
                 $attachnum += @currnewattach;                  $attachnum += @currnewattach;
             }              }
         }          }
  $discussion.=(<<ENDDISCUSS);   if (&discussion_open($status)) {
       $discussion.=(<<ENDDISCUSS);
 <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data">  <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data">
 <input type="submit" name="discuss" value="Post Discussion" />  <input type="submit" name="discuss" value="Post Discussion" />
 <input type="submit" name="anondiscuss" value="Post Anonymous Discussion" />  <input type="submit" name="anondiscuss" value="Post Anonymous Discussion" />
Line 639  to course faculty</font><br /> Line 716  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) &&   $discussion.='<table bgcolor="#BBBBBB"><tr><td>';
     &Apache::lonnet::allowed('pch',          if (&discussion_open($status) &&
    $ENV{'request.course.id'}.              &Apache::lonnet::allowed('pch',
  ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) {             $env{'request.course.id'}.
           ($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.='<a href="/adm/feedback?replydisc='.
     $symb.':::" '.$target.'>'.      &Apache::lonnet::escape($ressymb).':::" '.$target.'>'.
     '<img src="/adm/lonMisc/chat.gif" border="0" />'.      '<img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" border="0" />'.
     &mt('Post Discussion').'</a></td></tr></table>';      &mt('Post Discussion').'</a><br />';
     }              }
  }   }
    $discussion.='<a href="/adm/feedback?sendmessageonly=1&symb='.
       &Apache::lonnet::escape($ressymb).
       '"><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').'" border="0" />'.
       &mt('Send Message').'</td></tr></table>';
     }      }
     return $discussion;      return $discussion;
 }  }
   
 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,$anonhash,$anoncnt) = @_;
   
     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 $escsymb=&Apache::lonnet::escape($ressymb);
   $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'},
     $env{'course.'.$env{'request.course.id'}.'.num'});
   
     if ($contrib{'version'}) {      if ($contrib{'version'}) {
         my $oldest = $contrib{'1:timestamp'};          my $oldest = $contrib{'1:timestamp'};
         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 708  sub build_posting_display { Line 796  sub build_posting_display {
     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 'ascdate'))) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) {                  if ( (($env{'environment.threadeddiscussion'}) && ($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 745  sub build_posting_display { Line 833  sub build_posting_display {
                 my %allattachments = ();                  my %allattachments = ();
                 my ($screenname,$plainname);                  my ($screenname,$plainname);
                 my $sender = &mt('Anonymous');                  my $sender = &mt('Anonymous');
   # Anonymous users getting number within a discussion
   # Since idx is in static order, this should give the same sequence every time. 
    my $key=$contrib{$idx.':sendername'}.'@'.$contrib{$idx.':senderdomain'};
    unless ($$anonhash{$key}) {
                       $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,$outputtarget,\%messages,\%subjects,\%allattachments,\%attachtxt,$imsfiles,\$screenname,\$plainname,$numoldver);
   
Line 783  sub build_posting_display { Line 878  sub build_posting_display {
  $contrib{$idx.':sendername'}.' at '.   $contrib{$idx.':sendername'}.' at '.
  $contrib{$idx.':senderdomain'}.')';   $contrib{$idx.':senderdomain'}.')';
     if ($contrib{$idx.':anonymous'}) {      if ($contrib{$idx.':anonymous'}) {
         $sender.=' ['.&mt('anonymous').'] '.          $sender.=' <font color="red"><b>['.$$anonhash{$key}.']</b></font> '.
     $screenname;      $screenname;
     }      }
   
Line 816  sub build_posting_display { Line 911  sub build_posting_display {
                             } else {                              } else {
                                 @{$$namesort{$lastname}{$firstname}} = ("$idx");                                  @{$$namesort{$lastname}{$firstname}} = ("$idx");
                             }                              }
                             if ($ENV{'course.'.$ENV{'request.course.id'}.'.allow_discussion_post_editing'} =~ m/yes/i) {                              if (&editing_allowed()) {
                                 if (($ENV{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($ENV{'user.name'} eq $contrib{$idx.':sendername'})) {                                  if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) {
                                     $sender.=' <a href="/adm/feedback?editdisc='.                                      $sender.=' <a href="/adm/feedback?editdisc='.
                                          $ressymb.':::'.$idx;                                           $escsymb.':::'.$idx;
                                     if ($newpostsflag) {                                      if ($$newpostsflag) {
                                         $sender .= '&previous='.$prevread;                                          $sender .= '&previous='.$prevread;
                                     }                                      }
                                     $sender .= '" '.$target.'>'.&mt('Edit').'</a>';                                                                                   $sender .= '" '.$target.'>'.&mt('Edit').'</a>';                                             
                                     unless ($seeid) {                                      unless ($seeid) {
                                         $sender.=" <a href=\"javascript:studentdelete('$ressymb','$idx','$newpostsflag','$prevread')";                                          $sender.=" <a href=\"javascript:studentdelete('$escsymb','$idx','$$newpostsflag','$prevread')";
                                         $sender .= '">'.&mt('Delete').'</a>';                                          $sender .= '">'.&mt('Delete').'</a>';
                                     }                                      }
                                 }                                  }
Line 834  sub build_posting_display { Line 929  sub build_posting_display {
         if ($hidden) {          if ($hidden) {
                                     unless ($studenthidden) {                                      unless ($studenthidden) {
                 $sender.=' <a href="/adm/feedback?unhide='.                  $sender.=' <a href="/adm/feedback?unhide='.
                 $ressymb.':::'.$idx;                  $escsymb.':::'.$idx;
                                         if ($newpostsflag) {                                          if ($$newpostsflag) {
                                              $sender .= '&previous='.$prevread;                                              $sender .= '&previous='.$prevread;
                                         }                                          }
                                         $sender .= '">'.&mt('Make Visible').'</a>';                                          $sender .= '">'.&mt('Make Visible').'</a>';
                                     }                                      }
         } else {          } else {
     $sender.=' <a href="/adm/feedback?hide='.      $sender.=' <a href="/adm/feedback?hide='.
         $ressymb.':::'.$idx;          $escsymb.':::'.$idx;
                                     if ($newpostsflag) {                                      if ($$newpostsflag) {
                                         $sender .= '&previous='.$prevread;                                          $sender .= '&previous='.$prevread;
                                     }                                      }
                                     $sender .= '">'.&mt('Hide').'</a>';                                      $sender .= '">'.&mt('Hide').'</a>';
         }                               }                     
         $sender.=' <a href="/adm/feedback?deldisc='.          $sender.=' <a href="/adm/feedback?deldisc='.
         $ressymb.':::'.$idx;          $escsymb.':::'.$idx;
                                 if ($newpostsflag) {                                  if ($$newpostsflag) {
                                     $sender .= '&previous='.$prevread;                                      $sender .= '&previous='.$prevread;
                                 }                                  }
                                 $sender .= '">'.&mt('Delete').'</a>';                                  $sender .= '">'.&mt('Delete').'</a>';
Line 858  sub build_posting_display { Line 953  sub build_posting_display {
         } else {          } else {
     if ($screenname) {      if ($screenname) {
         $sender='<i>'.$screenname.'</i>';          $sender='<i>'.$screenname.'</i>';
       } else {
    $sender='<i>'.$$anonhash{$key}.'</i>';
     }      }
 # 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'})) {
Line 880  sub build_posting_display { Line 977  sub build_posting_display {
         }          }
         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'}:''))) {
     $sender.=' <a href="/adm/feedback?replydisc='.      $sender.=' <a href="/adm/feedback?replydisc='.
             $ressymb.':::'.$idx;              $escsymb.':::'.$idx;
                             if ($newpostsflag) {                              if ($$newpostsflag) {
                                     $sender .= '&previous='.$prevread;                                  $sender .= '&previous='.$prevread;
                             }                              }
                             $sender .= '" '.$target.'>'.&mt('Reply').'</a>';                              $sender .= '" '.$target.'>'.&mt('Reply').'</a>';
                         }                          }
Line 894  sub build_posting_display { Line 991  sub build_posting_display {
                             $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);                              $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);
         }          }
                         if ($$dischash{$readkey}=~/\.$idx\./) {                           if ($$dischash{$readkey}=~/\.$idx\./) { 
                             $ctlink = '<b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" />';                              $ctlink = '<label><b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" /></label>';
                         } else {                          } else {
                             $ctlink = '<b>'.&mt('Mark read').'?</b>&nbsp;<input type="checkbox" name="postread_'.$idx.'" />';                              $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 'ascdate'))) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) {      if ( (($env{'environment.threadeddiscussion'}) && ($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 944  sub build_posting_display { Line 1041  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;
                                                   last;
                                               }
                                           } elsif ($role =~ /^$rolematch$/) {
                                             $$shown{$idx} = 1;                                              $$shown{$idx} = 1;
                                             last;                                              last;
                                         }                                          }
                                     }                                      }
                                 }                                  }
                               } else {
                                   $$shown{$idx} = 1;
                             }                              }
                         }                          }
                         unless ($$notshown{$idx} == 1) {                          unless ($$notshown{$idx} == 1) {
Line 1013  sub build_posting_display { Line 1096  sub build_posting_display {
                                 my @postversions = ();                                  my @postversions = ();
                                 $$discussionitems[$idx] .= &mt('This post has been edited by the author.');                                  $$discussionitems[$idx] .= &mt('This post has been edited by the author.');
                                 if ($seeid) {                                  if ($seeid) {
                                     $$discussionitems[$idx] .= '&nbsp;&nbsp;<a href="/adm/feedback?allversions='.$ressymb.':::'.$idx.'">'.&mt('Display all versions').'</a>';                                      $$discussionitems[$idx] .= '&nbsp;&nbsp;<a href="/adm/feedback?allversions='.$escsymb.':::'.$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 1034  sub build_posting_display { Line 1117  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 1046  sub get_post_contents { Line 1183  sub get_post_contents {
            return $discussion;             return $discussion;
        }          } 
     }      }
     $$screenname=&Apache::loncommon::screenname(  #    $$screenname=&Apache::loncommon::screenname(
                                         $$contrib{$idx.':sendername'},  #                                        $$contrib{$idx.':sendername'},
                                         $$contrib{$idx.':senderdomain'});  #                                        $$contrib{$idx.':senderdomain'});
     $$plainname=&Apache::loncommon::nickname(      $$plainname=&Apache::loncommon::nickname(
                                         $$contrib{$idx.':sendername'},                                          $$contrib{$idx.':sendername'},
                                         $$contrib{$idx.':senderdomain'});                                          $$contrib{$idx.':senderdomain'});
       $$screenname=$$contrib{$idx.':screenname'};
   
     my $sender=&Apache::loncommon::aboutmewrapper(      my $sender=&Apache::loncommon::aboutmewrapper(
                                  $$plainname,                                   $$plainname,
                                  $$contrib{$idx.':sendername'},                                   $$contrib{$idx.':sendername'},
Line 1063  sub get_post_contents { Line 1202  sub get_post_contents {
     if ($type eq 'allversions' || $type eq 'export') {      if ($type eq 'allversions' || $type eq 'export') {
         $start = 0;          $start = 0;
         if ($$contrib{$idx.':history'}) {          if ($$contrib{$idx.':history'}) {
             if ($$contrib{$idx.':history'} =~ m/:/) {      @postversions = split(/:/,$$contrib{$idx.':history'});
                 @postversions = split/:/,$$contrib{$idx.':history'};  
             } else {  
                 @postversions = ("$$contrib{$idx.':history'}");  
             }  
         }          }
         &get_post_versions($messages,$$contrib{$idx.':message'},1);          &get_post_versions($messages,$$contrib{$idx.':message'},1);
         &get_post_versions($subjects,$$contrib{$idx.':subject'},1);          &get_post_versions($subjects,$$contrib{$idx.':subject'},1);
Line 1088  sub get_post_contents { Line 1223  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]);
         $$messages{$i}=~s/\n/\<br \/\>/g;   &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 1123  END Line 1258  END
         }          }
     }      }
     if ($type eq 'allversions') {      if ($type eq 'allversions') {
         $discussion.=('</ul></body></html>');          $discussion.='</ul>';
         return $discussion;          return $discussion;
     } else {      } else {
         return;          return;
Line 1149  sub replicate_attachments { Line 1284  sub replicate_attachments {
                     $i ++;                      $i ++;
                 }                  }
                 my ($content,$rtncode);                  my ($content,$rtncode);
                 print STDERR "File to replicate is $$attachrefs{$id}{'filename'} in $1,$2\n";  
                 my $uploadreply = &Apache::lonnet::getuploaded('GET',$$attachrefs{$id}{'filename'},$1,$2,$content,$rtncode);                  my $uploadreply = &Apache::lonnet::getuploaded('GET',$$attachrefs{$id}{'filename'},$1,$2,$content,$rtncode);
                 if ($uploadreply eq 'ok') {                  if ($uploadreply eq 'ok') {
                      my $attachcopy;                      my $attachcopy;
                      if ($attachcopy = Apache::File->new('>'.$destination)) {                      if ($attachcopy = Apache::File->new('>'.$destination)) {
                          print $attachcopy $content;                          print $attachcopy $content;
                          close($attachcopy);                          close($attachcopy);
                      } else {                      } else {
                          $response .= 'Error copying a file attachment to IMS package: '.$!.'<br />'."\n";                          $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$!.'<br />'."\n";
                      }                      }
                 } else {                  } else {
                     print STDERR "return code from lonnet was $rtncode\n";                      &Apache::lonnet::logthis("Replication of attachment failed when building IMS export of discussion posts - domain: $1, course: $2, file: $$attachrefs{$id}{'filename'} -error: $rtncode");
                       $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$rtncode.'<br />'."\n";
                 }                  }
             }              }
         }          }
     }      }
       return $response;
 }  }
   
 sub mail_screen {  sub mail_screen {
   my ($r,$feedurl,$options) = @_;    my ($r,$feedurl,$options) = @_;
   if (exists($ENV{'form.origpage'})) {    if (exists($env{'form.origpage'})) {
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss']);        &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss','blog']);
   }    }
   my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion',  
                                           '','onLoad="window.focus();setposttype();"');  
   my $title=&Apache::lonnet::gettitle($feedurl);    my $title=&Apache::lonnet::gettitle($feedurl);
   if (!$title) { $title = $feedurl; }    if (!$title) { $title = $feedurl; }
   my $quote='';    my $quote='';
Line 1203  sub mail_screen { Line 1338  sub mail_screen {
    }     }
 END  END
   my $anonscript;    my $anonscript;
   if (exists($ENV{'form.origpage'})) {    if (exists($env{'form.origpage'})) {
       $anonscript = (<<END);        $anonscript = (<<END);
   function setposttype() {    function setposttype() {
       var anondisc = $ENV{'form.anondiscuss'};        var anondisc = $env{'form.anondiscuss'};
       var disc = $ENV{'form.discuss'};        var disc = $env{'form.discuss'};
       if (anondisc == 1) {        if (anondisc == 1) {
           document.mailform.anondiscuss.checked = true            document.mailform.anondiscuss.checked = true
       }        }
Line 1224  END Line 1359  END
   }    }
 END  END
   }    }
   if (($ENV{'form.replydisc'}) || ($ENV{'form.editdisc'})) {    if (($env{'form.replydisc'}) || ($env{'form.editdisc'})) {
       if ($ENV{'form.replydisc'}) {        if ($env{'form.replydisc'}) {
           ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'});            ($symb,$idx)=split(/\:\:\:/,$env{'form.replydisc'});
       } else {        } else {
           ($symb,$idx)=split(/\:\:\:/,$ENV{'form.editdisc'});            ($symb,$idx)=split(/\:\:\:/,$env{'form.editdisc'});
       }        }
       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'});
       unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {        unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {
           if ($contrib{$idx.':history'}) {            if ($contrib{$idx.':history'}) {
               if ($contrib{$idx.':history'} =~ /:/) {                if ($contrib{$idx.':history'} =~ /:/) {
Line 1242  END Line 1377  END
                   $numoldver = 1;                    $numoldver = 1;
               }                }
           }            }
           if ($ENV{'form.replydisc'}) {            if ($env{'form.replydisc'}) {
               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 1257  END Line 1392  END
                   &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);                    &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);
                   $message = $msgversions{$numoldver};                    $message = $msgversions{$numoldver};
               }                }
       $message=~s/\n/\<br \/\>/g;        &newline_to_br(\$message);
       $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message).'</blockquote>';        $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message).'</blockquote>';
               if ($idx > 0) {                if ($idx > 0) {
                   my %subversions = ();                    my %subversions = ();
Line 1278  END Line 1413  END
               if (defined($contrib{$idx.':replyto'})) {                if (defined($contrib{$idx.':replyto'})) {
                   $parentmsg = $contrib{$idx.':replyto'};                    $parentmsg = $contrib{$idx.':replyto'};
               }                }
               unless (exists($ENV{'form.origpage'})) {                unless (exists($env{'form.origpage'})) {
                   my $anonflag = 0;                    my $anonflag = 0;
                   if ($contrib{$idx.':anonymous'}) {                    if ($contrib{$idx.':anonymous'}) {
                       $anonflag = 1;                        $anonflag = 1;
Line 1300  END Line 1435  END
               }                }
           }            }
       }        }
       if ($ENV{'form.previous'}) {        if ($env{'form.previous'}) {
           $prevtag = '<input type="hidden" name="previous" value="'.$ENV{'form.previous'}.'" />';            $prevtag = '<input type="hidden" name="previous" value="'.$env{'form.previous'}.'" />';
       }        }
   }    }
   
   if ($ENV{'form.origpage'}) {    if ($env{'form.origpage'}) {
       $subject = $ENV{'form.subject'};        $subject = &Apache::lonnet::unescape($env{'form.subject'});
       $comment = $ENV{'form.comment'};        $comment = &Apache::lonnet::unescape($env{'form.comment'});
       &process_attachments(\@currnewattach,\@currdelold,\@keepold);        &process_attachments(\@currnewattach,\@currdelold,\@keepold);
   }    }
   my $latexHelp=&Apache::loncommon::helpLatexCheatsheet();    my $latexHelp=&Apache::loncommon::helpLatexCheatsheet();
   my $htmlheader=&Apache::lonhtmlcommon::htmlareaheaders();  
   my $send=&mt('Send');    my $send=&mt('Send');
   $r->print(<<END);    my $js= <<END;
 <html>  
 <head>  
 <title>The LearningOnline Network with CAPA</title>  
 <meta http-equiv="pragma" content="no-cache"></meta>  
 $htmlheader  
 <script type="text/javascript">  <script type="text/javascript">
 //<!--  //<!--
     function gosubmit() {      function gosubmit() {
Line 1353  $htmlheader Line 1482  $htmlheader
              rec=1;               rec=1;
           }             } 
         }          }
           if (typeof(document.mailform.elements.blog)!="undefined") {
             if (document.mailform.elements.blog.checked) {
                rec=1;
             } 
           }
   
         if (rec) {          if (rec) {
             if (typeof(document.mailform.onsubmit)=='function') {              if (typeof(document.mailform.onsubmit)=='function') {
Line 1367  $htmlheader Line 1501  $htmlheader
     $anonscript      $anonscript
 //-->  //-->
 </script>  </script>
 </head>  END
 $bodytag  
     my %onload = ('onload' => 'window.focus();setposttype();');
     my $start_page=
         &Apache::loncommon::start_page('Resource Feedback and Discussion',$js,
        {'add_entries' => \%onload});
   
     $r->print(<<END);
   $start_page
 <h2><tt>$title</tt></h2>  <h2><tt>$title</tt></h2>
 <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" />
 END  END
   if ($ENV{'form.replydisc'}) {    if ($env{'form.replydisc'}) {
       $r->print(<<END);        $r->print(<<END);
 <input type="hidden" name="replydisc" value="$ENV{'form.replydisc'}" />  <input type="hidden" name="replydisc" value="$env{'form.replydisc'}" />
 END  END
   } elsif ($ENV{'form.editdisc'}) {    } elsif ($env{'form.editdisc'}) {
      $r->print(<<END);       $r->print(<<END);
 <input type="hidden" name="editdisc" value ="$ENV{'form.editdisc'}" />  <input type="hidden" name="editdisc" value ="$env{'form.editdisc'}" />
 <input type="hidden" name="parentmsg" value ="$parentmsg" />  <input type="hidden" name="parentmsg" value ="$parentmsg" />
 END  END
   }    }
Line 1398  Title: <input type="text" name="subject" Line 1539  Title: <input type="text" name="subject"
 </textarea></p>  </textarea></p>
 <p>  <p>
 END  END
     if ( ($ENV{'form.editdisc'}) || ($ENV{'form.replydisc'}) ) {      if ( ($env{'form.editdisc'}) || ($env{'form.replydisc'}) ) {
         if ($ENV{'form.origpage'}) {          if ($env{'form.origpage'}) {
             foreach (@currnewattach) {              foreach (@currnewattach) {
                 $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");                  $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");
             }              }
Line 1407  END Line 1548  END
                 $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");                  $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");
             }              }
         }          }
         if ($ENV{'form.editdisc'}) {          if ($env{'form.editdisc'}) {
             if ($attachmenturls) {              if ($attachmenturls) {
                 &extract_attachments($attachmenturls,$idx,$numoldver,\$attachmsg,\%attachments,\%currattach,\@currdelold);                  &extract_attachments($attachmenturls,$idx,$numoldver,\$attachmsg,\%attachments,\%currattach,\@currdelold);
                 $attachnum = scalar(keys %currattach);                  $attachnum = scalar(keys %currattach);
Line 1429  END Line 1570  END
 </p>  </p>
 </form>  </form>
 END  END
     if ($ENV{'form.editdisc'} || $ENV{'form.replydisc'}) {      if ($env{'form.editdisc'} || $env{'form.replydisc'}) {
         my $now = time;          my $now = time;
         my $ressymb = $symb;          my $ressymb = $symb;
         my $postidx = '';          my $postidx = '';
         if ($ENV{'form.editdisc'}) {          if ($env{'form.editdisc'}) {
             $postidx = $idx;              $postidx = $idx;
         }          }
         if (@currnewattach > 0) {          if (@currnewattach > 0) {
Line 1465  END Line 1606  END
     }      }
     $r->print(&generate_preview_button().      $r->print(&generate_preview_button().
               &Apache::lonhtmlcommon::htmlareaselectactive('comment').                &Apache::lonhtmlcommon::htmlareaselectactive('comment').
               '</body></html>');        &Apache::loncommon::end_page());
   
 }  }
   
 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',
                                                     $ENV{'user.domain'});                                                      $env{'user.domain'});
     my $bodytag=&Apache::loncommon::bodytag('Discussion options',  
                                           '','');  
   
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'dido' => 'Discussion display options',  
         'pref' => 'Display Preference',          'pref' => 'Display Preference',
         'curr' => 'Current setting ',          'curr' => 'Current setting ',
         'actn' => 'Action',          'actn' => 'Action',
Line 1540  sub print_display_options { Line 1677  sub print_display_options {
         $currtogg = $lt{'toggon'};          $currtogg = $lt{'toggon'};
         $disctogg = 'toggon';          $disctogg = 'toggon';
     }      }
     $r->print(<<END);  
 <html>      my $js = <<END;
 <head>  <script type="text/javascript">
 <title>$lt{'dido'}</title>  
 <meta http-equiv="pragma" content="no-cache" />  
 <script>  
 function discdispChk(caller) {  function discdispChk(caller) {
     var disctogg = '$toggchg'      var disctogg = '$toggchg'
     if (caller == 0) {      if (caller == 0) {
Line 1612  function setDisp() { Line 1746  function setDisp() {
     }      }
 }  }
 </script>  </script>
 </head>  END
 $bodytag  
 <form name="modifydisp" method="post" action="/adm/feedback">  
       my $start_page =
    &Apache::loncommon::start_page('Discussion display options',$js);
       my $end_page =
    &Apache::loncommon::end_page();
       $r->print(<<END);
   <form name="modifydisp" method="POSTx" action="/adm/feedback">
 $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$lt{'whpo'}</li><li>$lt{'unwh'}</li><li>$lt{'wipa'}</li></ol>  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$lt{'whpo'}</li><li>$lt{'unwh'}</li><li>$lt{'wipa'}</li></ol>
 <br />  <br />
 <table border="0" cellpadding="0" cellspacing="0">  <table border="0" cellpadding="0" cellspacing="0">
Line 1632  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l Line 1772  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l
        <tr bgcolor="#dddddd">         <tr bgcolor="#dddddd">
        <td>$lt{'disa'}</td>         <td>$lt{'disa'}</td>
        <td>$lt{$discdisp}</td>         <td>$lt{$discdisp}</td>
        <td><input type="checkbox" name="discdisp" onClick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"         <td><label><input type="checkbox" name="discdisp" onClick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"</label>
            <br />             <br />
            <input type="checkbox" name="discdisp" onClick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"             <label><input type="checkbox" name="discdisp" onClick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"</label>
        </td>         </td>
       </tr><tr bgcolor="#eeeeee">        </tr><tr bgcolor="#eeeeee">
        <td>$lt{'npmr'}</td>         <td>$lt{'npmr'}</td>
        <td>$lt{$discmark}</td>         <td>$lt{$discmark}</td>
        <td><input type="checkbox" name="discmark" />$lt{'chgt'} "$markchange"</td>         <td><label><input type="checkbox" name="discmark" />$lt{'chgt'} "$markchange"</label></td>
       </tr><tr bgcolor="#dddddd">        </tr><tr bgcolor="#dddddd">
        <td>$lt{'dotm'}</td>         <td>$lt{'dotm'}</td>
        <td>$lt{$disctogg}</td>         <td>$lt{$disctogg}</td>
        <td><input type="checkbox" name="disctogg" onClick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</td>         <td><label><input type="checkbox" name="disctogg" onClick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</label></td>
       </tr>        </tr>
      </table>       </table>
     </td>      </td>
Line 1654  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l Line 1794  $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 1663  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l Line 1804  $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$l
 <br />  <br />
 <br />  <br />
 </form>  </form>
 </body>  $end_page
 </html>  
 END  END
     return;      return;
 }  }
   
 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;
     my $numvisible = 5;      my $numvisible = 5;
     my ($classlist) = &Apache::loncoursedata::get_classlist(  
                               $ENV{'request.course.id'},  
                               $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
                               $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
                                                                                      
     my $sec_index = &Apache::loncoursedata::CL_SECTION();  
     my $status_index = &Apache::loncoursedata::CL_STATUS();  
     my %sectioncount = ();      my %sectioncount = ();
     while (my ($student,$data) = each %$classlist) {  
         my ($section,$status) = ($data->[$sec_index],      $numsections = &Apache::loncommon::get_sections($env{'course.'.$env{'request.course.id'}.'.domain'},$env{'course.'.$env{'request.course.id'}.'.num'},\%sectioncount);
                                  $data->[$status_index]);  
         unless ($section eq '' || $section =~ /^\s*$/) {      if ($env{'request.course.sec'} !~ /^\s*$/) {  #Restrict section choice to current section 
             if (!defined($sectioncount{$section})) {          @sections = ('all',$env{'request.course.sec'});
                 $sectioncount{$section} = 1;          $numvisible = 2;
                 $numsections ++;  
             } else {  
                 $sectioncount{$section} ++;  
             }  
         }  
     }  
                                                                                      
     if ($ENV{'request.course.sec'} !~ /^\s*$/) {  
         @sections = ($ENV{'request.course.sec'});  
         $numvisible = 1;  
     } else {      } else {
         @sections = sort {$a cmp $b} keys(%sectioncount);          @sections = sort {$a cmp $b} keys(%sectioncount);
         unshift(@sections,'all'); # Put 'all' at the front of the list          unshift(@sections,'all'); # Put 'all' at the front of the list
Line 1716  sub print_sortfilter_options { Line 1840  sub print_sortfilter_options {
                                                                                                                                                                         
     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',
                                                     $ENV{'user.domain'});                                                      $env{'user.domain'});
     my $bodytag=&Apache::loncommon::bodytag('Discussion options',  
                                           '','');  
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'diso' => 'Discussion sorting and filtering 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);
   
       my $js = <<END;
   <script type="text/javascript">
   function verifyFilter() {
       var rolenum = 0
       for (var i=0; i<document.modifyshown.rolefilter.length; i++) {
           if (document.modifyshown.rolefilter.options[i].selected == true) {
               rolenum ++
           }
       }
       if (rolenum == 0) {
           document.modifyshown.rolefilter.options[0].selected = true
       }
   
       var secnum = 0
       for (var i=0; i<document.modifyshown.sectionpick.length; i++) {
           if (document.modifyshown.sectionpick.options[i].selected == true) {
               secnum ++
           }
       }
       if (secnum == 0) {
           document.modifyshown.sectionpick.options[0].selected = true
       }
       document.modifyshown.submit();
   }
   </script>
   END
   
       my $start_page=
    &Apache::loncommon::start_page('Discussion options',$js);
       my $end_page=
    &Apache::loncommon::end_page();
   
     $r->print(<<END);      $r->print(<<END);
 <html>  $start_page
 <head>  <form name="modifyshown" method="POST" action="/adm/feedback">
 <title>$lt{'diso'}</title>  
 <meta http-equiv="pragma" content="no-cache" />  
 </head>  
 $bodytag  
 <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 /><br />
 <table border="0">  <table border="0">
  <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" selected="selected" />$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" selected="selected" />$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>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td><input type="checkbox" name="posterlist" value="$symb" />$lt{'shal'}</td>    <td><label><input type="checkbox" name="posterlist" value="$symb" />$lt{'shal'}</label></td>
  </tr>   </tr>
 </table>  </table>
 <br />  <br />
 <br />  <br />
 <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="Store Changes" onClick="javascript:document.modifyshown.submit()" />  <input type="button" name="sub" value="Store Changes" onClick="verifyFilter()" />
 <br />  <br />
 <br />  <br />
 </form>  </form>
 </body>  $end_page
 </html>  
 END  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::loncommon::content_type($r,'text/html');
         $feedurl=~s|^/adm/wrapper||;      $r->send_http_header;
     }  
 # backward compatibility (bulletin boards used to be 'wrapped')      &Apache::lonenc::check_encrypt(\$symb);
     my $ressymb=$symb;      my $crs='/'.$env{'request.course.id'};
     if ($ressymb =~ /bulletin___\d+___/) {      if ($env{'request.course.sec'}) {
         unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {          $crs.='_'.$env{'request.course.sec'};
             $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;  
         }  
     }  
     my $crs='/'.$ENV{'request.course.id'};  
     if ($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 = ();
     my %postcounts = ();      my %postcounts = ();
     my %lt=&Apache::lonlocal::texthash(  
                      'diso' => 'Discussion filtering options',  
     );  
     my $bodytag=&Apache::loncommon::bodytag('Discussion options',  
                                           '','');  
     if ($contrib{'version'}) {      if ($contrib{'version'}) {
         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\./);
Line 1868  sub print_showposters { Line 2012  sub print_showposters {
             }              }
         }          }
     }      }
   
       my $start_page = &Apache::loncommon::start_page('Discussion options');
   
     $r->print(<<END);      $r->print(<<END);
 <html>  $start_page
 <head>  
 <title>$lt{'diso'}</title>  
 <meta http-equiv="pragma" content="no-cache" />  
 </head>  
 $bodytag  
  <form name="pickpostersform" method="post">   <form name="pickpostersform" method="post">
   <table border="0">    <table border="0">
    <tr>     <tr>
Line 1896  END Line 2038  END
                     next;                      next;
                 } else {                  } else {
                     $count ++;                      $count ++;
                     $r->print('<tr bgcolor="#ffffe6"><td align="right">'.$count.'</td><td align="center"><input name="stuinfo" type="checkbox" value="'.$_.'" /></td><td>'.$last.', '.$first.' ('.$uname.','.$udom.')</td><td>'.$postcounts{$_}.'</td></tr>');                      $r->print('<tr bgcolor="#ffffe6"><td align="right">'.$count.'</td><td align="center"><label><input name="stuinfo" type="checkbox" value="'.$_.'" /></td><td>'.$last.', '.$first.' ('.$uname.','.$udom.')</label></td><td>'.$postcounts{$_}.'</td></tr>');
                 }                  }
             }              }
         }          }
     }      }
   
       my $end_page   = &Apache::loncommon::end_page();
     $r->print(<<END);      $r->print(<<END);
      </table>       </table>
     </td>      </td>
Line 1911  END Line 2055  END
 <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>
 </body>  $end_page
 </html>  
 END  END
 }  }
   
Line 1920  sub get_post_versions { Line 2063  sub get_post_versions {
     my ($versions,$incoming,$htmldecode,$numver) = @_;      my ($versions,$incoming,$htmldecode,$numver) = @_;
     if ($incoming =~ /^<version num="0">/) {      if ($incoming =~ /^<version num="0">/) {
         my $p = HTML::LCParser->new(\$incoming);          my $p = HTML::LCParser->new(\$incoming);
         my $done = 0;                                                                                 my $done = 0; 
   
         while ( (my $token = $p->get_tag("version")) && (!$done)) {          while ( (my $token = $p->get_tag("version")) && (!$done)) {
             my $num = $token->[1]{num};              my $num = $token->[1]{num};
             my $text = $p->get_text("/version");              my $text = $p->get_text("/version");
Line 1977  sub get_post_attachments { Line 2121  sub get_post_attachments {
     return;      return;
 }  }
   
 sub build_ims_export {  sub fail_redirect {
     my ($r,$symb,$previous,$feedurl) = @_;  
  # backward compatibility (bulletin boards used to be 'wrapped')  
     if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {  
         $feedurl=~s|^/adm/wrapper||;  
     }  
     my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},  
                           $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
                           $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
     my @depth=();  
     my %alldiscussion=();  
     my @discussionitems=();  
     my %usernamesort = ();  
     my %subjectsort = ();  
     my %namesort = ();  
     my %notshown = ();  
     my %newitem = ();  
     my %dischash = ();  
     my %shown = ();  
     my %roleinfo = ();  
     my @posters=();  
     my $maxdepth=0;  
     my $visible=0;  
     my $newpostsflag=0;  
     my $status;  
     my $viewgrades;  
     my $seeid;  
     my $prevread;  
     my $sortposts;  
     my $ressymb;  
     my $target;  
     my $readkey;  
     my $showunmark;  
     my $showonlyunread;  
   
 }  
   
   
   
 sub fail_redirect {;  
   my ($r,$feedurl) = @_;    my ($r,$feedurl) = @_;
   if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };    if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
   $r->print (<<ENDFAILREDIR);    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
 <html>    $r->print(&Apache::loncommon::start_page('Feedback not sent',undef,
 <head><title>Feedback not sent</title>     {'redirect'  => [2,$feedurl],
 <meta http-equiv="pragma" content="no-cache" />      'only_body' => 1,}));
 <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />    $r->print(<<ENDFAILREDIR);
 </head>  <img align="right" src="$logo" />
 <body bgcolor="#FFFFFF">  
 <img align="right" src="/adm/lonIcons/lonlogos.gif" />  
 <b>Sorry, no recipients  ...</b>  <b>Sorry, no recipients  ...</b>
 <a href="$feedurl">Continue</a>  
 </body>  
 </html>  
 ENDFAILREDIR  ENDFAILREDIR
     $r->print(&Apache::loncommon::end_page());
 }  }
   
 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,$blog,$status,$previous,$sort,$rolefilter,$statusfilter,$sectionpick,$numpicks) = @_;
   my $sorttag = '';    my $sorttag = '';
   my $roletag = '';    my $roletag = '';
   my $statustag = '';    my $statustag = '';
Line 2043  sub redirect_back { Line 2144  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 2065  sub redirect_back { Line 2167  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.'" />';  
       }        }
   }    }
   $r->print (<<ENDREDIR);    $feedurl=&Apache::lonenc::check_encrypt($feedurl);
 <html>    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
 <head>    my %onload = ('onload' => "if (window.name!='loncapaclient') { this.document.reldt.submit(); self.window.close(); }");
 <title>Feedback sent</title>    my $start_page=
 <meta http-equiv="pragma" content="no-cache" />        &Apache::loncommon::start_page('New posts marked as read',undef,
 <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />       {'redirect'    => [2,$feedurl],
 </head>        'only_body'   => 1,
 <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>        'add_entries' => \%onload});
 <img align="right" src="/adm/lonIcons/lonlogos.gif" />    my $end_page = &Apache::loncommon::end_page();
   
     $r->print(<<ENDREDIR);
   $start_page
   <img align="right" src="$logo" />
 $typestyle  $typestyle
 <b>Sent $sendsomething message(s), and $sendposts post(s).</b>  <b>Sent $sendsomething message(s), and $sendposts post(s).</b>
   $blog
 <font color="red">$status</font>  <font color="red">$status</font>
 <form name="reldt" action="$feedurl" target="loncapaclient">  <form name="reldt" action="$feedurl" target="loncapaclient">
 $prevtag  $prevtag
Line 2099  $roletag Line 2229  $roletag
 $sectag  $sectag
 $userpicktag  $userpicktag
 </form>  </form>
 <a href="$feedurl">Continue</a>  $end_page
 </body>  
 </html>  
 ENDREDIR  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 $continue=&mt('Continue');   
   $r->print (<<ENDNOREDIR);    my %body_options = ('only_body'   => 1,
 <html>        'add_entries' => {'onload' => "if (window.name!='loncapaclient') { self.window.close(); }"});
 <head><title>Feedback not sent</title>  
 <meta http-equiv="pragma" content="no-cache" />  
 ENDNOREDIR  
   
   if ($feedurl!~/^\/adm\/feedback/) {     if ($feedurl !~ m{^/adm/feedback}) { 
     $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2; url='.$feedurl.'">');        $body_options{'rediect'} = [2,$feedurl];
   }    }
       my $start_page=
         &Apache::loncommon::start_page('Feedback not sent',undef,
        \%body_options);
         
     my $end_page = &Apache::loncommon::end_page();
   
     $feedurl=&Apache::lonenc::check_encrypt($feedurl);
     my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   $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.window.close(); }'>
 <img align="right" src="/adm/lonIcons/lonlogos.gif" />  <img align="right" src="$logo" />
 <b>$nofeed</b>  <b>$nofeed</b>
 <a href="$feedurl">$continue</a>  <br />
 </body>  $end_page
 </html>  
 ENDNOREDIRTWO  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'})) {
  if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/)) {   if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/) && ($env{'user.adv'})) {
     $msgoptions=       $msgoptions= 
  '<p><input type="checkbox" name="author" /> '.   '<p><label><input type="checkbox" name="author" /> '.
  &mt('Feedback to resource author').'</p>';   &mt('Feedback to resource author').'</label></p>';
  }   }
  if (&feedback_available(1)) {   if (&feedback_available(1)) {
     $msgoptions.=      $msgoptions.=
  '<br /><input type="checkbox" name="question" /> '.   '<p><label><input type="checkbox" name="question" /> '.
  &mt('Question about resource content');   &mt('Question about resource content').'</label></p>';
  }   }
  if (&feedback_available(0,1)) {   if (&feedback_available(0,1)) {
     $msgoptions.=      $msgoptions.=
  '<br /><input type="checkbox" name="course" /> '.   '<p><label><input type="checkbox" name="course" /> '.
  &mt('Question/Comment/Feedback about course content');   &mt('Question/Comment/Feedback about course content').
    '</label></p>';
  }   }
  if (&feedback_available(0,0,1)) {   if (&feedback_available(0,0,1)) {
     $msgoptions.=      $msgoptions.=
  '<br /><input type="checkbox" name="policy" /> '.   '<p><label><input type="checkbox" name="policy" /> '.
  &mt('Question/Comment/Feedback about course policy');   &mt('Question/Comment/Feedback about course policy').
    '</label></p>';
  }   }
     }      }
     if ($ENV{'request.course.id'}) {      if (($env{'request.course.id'}) && (!$env{'form.sendmessageonly'})) {
  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'}:''))) {
     $discussoptions='<input type="checkbox" name="discuss" onClick="this.form.anondiscuss.checked=false;" '.      $discussoptions='<label><input type="checkbox" name="discuss" onClick="this.form.anondiscuss.checked=false;" '.
  ($ENV{'form.replydisc'}?' checked="1"':'').' /> '.   ($env{'form.replydisc'}?' checked="1"':'').' /> '.
  &mt('Contribution to course discussion of resource');   &mt('Contribution to course discussion of resource');
     $discussoptions.='<br /><input type="checkbox" name="anondiscuss" onClick="this.form.discuss.checked=false;" /> '.      $discussoptions.='</label><br /><label><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></label> '.
       }   '<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';
           }
           $discussoptions.='<br /><label><input type="checkbox" name="blog" /> '.
       &mt('Add to my public course blog').'</label>';
     }      }
     if ($msgoptions) { $msgoptions='<h2><img src="/adm/lonMisc/feedback.gif" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }      if ($msgoptions) { $msgoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').'" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }
     if ($discussoptions) {       if ($discussoptions) { 
  $discussoptions='<h2><img src="/adm/lonMisc/chat.gif" />'.&mt('Discussion Contributions').'</h2>'.$discussoptions; }   $discussoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" />'.&mt('Discussion Contributions').'</h2>'.$discussoptions; }
     return $msgoptions.$discussoptions;      return $msgoptions.$discussoptions;
 }  }
   
Line 2194  sub clear_out_html { Line 2330  sub clear_out_html {
 # 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
   my $cid=$ENV{'request.course.id'};    my $cid=$env{'request.course.id'};
   if (($ENV{"course.$cid.allow_limited_html_in_feedback"} =~ m/yes/i) ||    if (($env{"course.$cid.allow_limited_html_in_feedback"} =~ m/yes/i) ||
       ($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>
       %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, DIV=>1, IMG=>1,
      M=>1, SUB=>1, SUP=>1, SPAN=>1,        M=>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);
   }    }
 # Do the substitution of everything that is not explicitly allowed  # Do the substitution of everything that is not explicitly allowed
Line 2216  sub clear_out_html { Line 2352  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 2240  sub secapply { Line 2374  sub secapply {
     my ($adr,$sections)=($rec=~/^([^\(]+)\(([^\)]+)\)/);      my ($adr,$sections)=($rec=~/^([^\(]+)\(([^\)]+)\)/);
     if ($sections) {      if ($sections) {
  foreach (split(/\;/,$sections)) {   foreach (split(/\;/,$sections)) {
             if (($_ eq $ENV{'request.course.sec'}) ||              if (($_ eq $env{'request.course.sec'}) ||
                 ($defaultflag && ($_ eq '*'))) {                  ($defaultflag && ($_ eq '*'))) {
                 return $adr;                   return $adr; 
             }              }
Line 2251  sub secapply { Line 2385  sub secapply {
     return '';      return '';
 }  }
   
   =pod 
   
   =over 4
   
   =item *
   
   decide_receiver($feedurl,$author,$question,$course,$policy,$defaultflag);
   
   Arguments
     $feedurl - /res/ url of resource (only need if $author is true)
     $author,$question,$course,$policy - all true/false parameters
       if true will attempt to find the addresses of user that should receive
       this type of feedback (author - feedback to author of resource $feedurl,
       $question 'Resource Content Questions', $course 'Course Content Question',
       $policy 'Course Policy')
       (Additionally it also checks $env for whether the corresponding form.<name>
       element exists, for ease of use in a html response context)
      
     $defaultflag - (internal should be left blank) if true gather addresses 
                    that aren't for a section even if I have a section
                    (used for reccursion internally, first we look for
                    addresses for our specific section then we recurse
                    and look for non section addresses)
   
   Returns
     $typestyle - string of html text, describing what addresses were found
     %to - a hash, which keys are addresses of users to send messages to
           the keys will look like   name:domain
   
   =cut
   
 sub decide_receiver {  sub decide_receiver {
   my ($feedurl,$author,$question,$course,$policy,$defaultflag) = @_;    my ($feedurl,$author,$question,$course,$policy,$defaultflag) = @_;
   my $typestyle='';    my $typestyle='';
   my %to=();    my %to=();
   if ($ENV{'form.author'}||$author) {    if ($env{'form.author'}||$author) {
     $typestyle.='Submitting as Author Feedback<br>';      $typestyle.='Submitting as Author Feedback<br />';
     $feedurl=~/^\/res\/(\w+)\/(\w+)\//;      $feedurl=~/^\/res\/(\w+)\/(\w+)\//;
     $to{$2.':'.$1}=1;      $to{$2.':'.$1}=1;
   }    }
   if ($ENV{'form.question'}||$question) {    if ($env{'form.question'}||$question) {
     $typestyle.='Submitting as Question<br>';      $typestyle.='Submitting as Question<br />';
     foreach (split(/\,/,      foreach (split(/\,/,
    $ENV{'course.'.$ENV{'request.course.id'}.'.question.email'})     $env{'course.'.$env{'request.course.id'}.'.question.email'})
      ) {       ) {
  my $rec=&secapply($_,$defaultflag);   my $rec=&secapply($_,$defaultflag);
         if ($rec) { $to{$rec}=1; }          if ($rec) { $to{$rec}=1; }
     }       } 
   }    }
   if ($ENV{'form.course'}||$course) {    if ($env{'form.course'}||$course) {
     $typestyle.='Submitting as Comment<br />';      $typestyle.='Submitting as Comment<br />';
     foreach (split(/\,/,      foreach (split(/\,/,
    $ENV{'course.'.$ENV{'request.course.id'}.'.comment.email'})     $env{'course.'.$env{'request.course.id'}.'.comment.email'})
      ) {       ) {
  my $rec=&secapply($_,$defaultflag);   my $rec=&secapply($_,$defaultflag);
         if ($rec) { $to{$rec}=1; }          if ($rec) { $to{$rec}=1; }
     }       } 
   }    }
   if ($ENV{'form.policy'}||$policy) {    if ($env{'form.policy'}||$policy) {
     $typestyle.='Submitting as Policy Feedback<br />';      $typestyle.='Submitting as Policy Feedback<br />';
     foreach (split(/\,/,      foreach (split(/\,/,
    $ENV{'course.'.$ENV{'request.course.id'}.'.policy.email'})     $env{'course.'.$env{'request.course.id'}.'.policy.email'})
      ) {       ) {
  my $rec=&secapply($_,$defaultflag);   my $rec=&secapply($_,$defaultflag);
         if ($rec) { $to{$rec}=1; }          if ($rec) { $to{$rec}=1; }
Line 2301  sub feedback_available { Line 2466  sub feedback_available {
 }  }
   
 sub send_msg {  sub send_msg {
   my ($feedurl,$email,$citations,$attachmenturl,%to)=@_;    my ($title,$feedurl,$email,$citations,$attachmenturl,%to)=@_;
   my $status='';    my $status='';
   my $sendsomething=0;    my $sendsomething=0;
     if ($title=~/^Error/) { $title=&mt('Feedback').': '.$title; }
     unless ($title=~/\w/) { $title=&mt('Feedback'); }
   foreach (keys %to) {    foreach (keys %to) {
     if ($_) {      if ($_) {
       my $declutter=&Apache::lonnet::declutter($feedurl);        my $declutter=&Apache::lonnet::declutter($feedurl);
       unless (&Apache::lonmsg::user_normal_msg(split(/\:/,$_),        unless (&Apache::lonmsg::user_normal_msg(split(/\:/,$_),
                'Feedback ['.$declutter.']',$email,$citations,$feedurl,                 $title.' ['.$declutter.']',$email,$citations,$feedurl,
                 $attachmenturl)=~/ok/) {                  $attachmenturl)=~/ok/) {
  $status.='<br />'.&mt('Error sending message to').' '.$_.'<br />';   $status.='<br />'.&mt('Error sending message to').' '.$_.'<br />';
       } else {        } else {
Line 2334  sub send_msg { Line 2501  sub send_msg {
 sub adddiscuss {  sub adddiscuss {
     my ($symb,$email,$anon,$attachmenturl,$subject)=@_;      my ($symb,$email,$anon,$attachmenturl,$subject)=@_;
     my $status='';      my $status='';
     if (&discussion_open() &&      my $realsymb;
  &Apache::lonnet::allowed('pch',$ENV{'request.course.id'}.      if ($symb=~/^bulletin___/) {
         ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) {   my $filename=(&Apache::lonnet::decode_symb($symb))[2];
    $filename=~s|^adm/wrapper/||;
    $realsymb=&Apache::lonnet::symbread($filename);
       }
       if (&discussion_open(undef,$realsymb) &&
    &Apache::lonnet::allowed('pch',$env{'request.course.id'}.
           ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
   
     my %contrib=('message'      => $email,      my %contrib=('message'      => $email,
                  'sendername'   => $ENV{'user.name'},                   'sendername'   => $env{'user.name'},
                  'senderdomain' => $ENV{'user.domain'},                   'senderdomain' => $env{'user.domain'},
                  'screenname'   => $ENV{'environment.screenname'},                   'screenname'   => $env{'environment.screenname'},
                  'plainname'    => $ENV{'environment.firstname'}.' '.                   'plainname'    => $env{'environment.firstname'}.' '.
                    $ENV{'environment.middlename'}.' '.                     $env{'environment.middlename'}.' '.
                                    $ENV{'environment.lastname'}.' '.                                     $env{'environment.lastname'}.' '.
                                    $ENV{'enrironment.generation'},                                     $env{'enrironment.generation'},
                  'attachmenturl'=> $attachmenturl,                   'attachmenturl'=> $attachmenturl,
                  'subject'      => $subject);                   'subject'      => $subject);
     if ($ENV{'form.replydisc'}) {      if ($env{'form.replydisc'}) {
  $contrib{'replyto'}=(split(/\:\:\:/,$ENV{'form.replydisc'}))[1];   $contrib{'replyto'}=(split(/\:\:\:/,$env{'form.replydisc'}))[1];
     }      }
     if ($anon) {      if ($anon) {
  $contrib{'anonymous'}='true';   $contrib{'anonymous'}='true';
     }      }
     if (($symb) && ($email)) {      if (($symb) && ($email)) {
         if ($ENV{'form.editdisc'}) {          if ($env{'form.editdisc'}) {
             my %newcontrib = ();  
             $contrib{'ip'}=$ENV{'REMOTE_ADDR'};              $contrib{'ip'}=$ENV{'REMOTE_ADDR'};
             $contrib{'host'}=$Apache::lonnet::perlvar{'lonHostID'};              $contrib{'host'}=$Apache::lonnet::perlvar{'lonHostID'};
             $contrib{'timestamp'} = time;              $contrib{'timestamp'} = time;
             $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'},
                      $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'});
             if (defined($oldcontrib{$oldidx.':replyto'})) {              if (defined($oldcontrib{$oldidx.':replyto'})) {
                 $contrib{'replyto'} = $oldcontrib{$oldidx.':replyto'};                  $contrib{'replyto'} = $oldcontrib{$oldidx.':replyto'};
             }              }
Line 2398  sub adddiscuss { Line 2571  sub adddiscuss {
                 }                  }
             }              }
             $contrib{'history'} .= $oldcontrib{$oldidx.':timestamp'};              $contrib{'history'} .= $oldcontrib{$oldidx.':timestamp'};
             foreach (keys %contrib) {              my $put_reply = &Apache::lonnet::putstore($env{'request.course.id'},
                 my $key = $oldidx.':'.&Apache::lonnet::escape($oldsymb).':'.$_;                                                                                                   $oldsymb,$oldidx,\%contrib,
                 $newcontrib{$key} = $contrib{$_};                    $env{'course.'.$env{'request.course.id'}.'.domain'},
             }                    $env{'course.'.$env{'request.course.id'}.'.num'});
             my $put_reply = &Apache::lonnet::putstore($ENV{'request.course.id'},  
                   \%newcontrib,  
                   $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
                   $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
             $status='Editing class discussion'.($anon?' (anonymous)':'');              $status='Editing class discussion'.($anon?' (anonymous)':'');
         } else {          } else {
            $status='Adding to class discussion'.($anon?' (anonymous)':'').': '.             $status='Adding to class discussion'.($anon?' (anonymous)':'').': '.
            &Apache::lonnet::store(\%contrib,$symb,$ENV{'request.course.id'},             &Apache::lonnet::store(\%contrib,$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 %storenewentry=($symb => time);          my %storenewentry=($symb => time);
         $status.='<br />'.&mt('Updating discussion time').': '.          $status.='<br />'.&mt('Updating discussion time').': '.
         &Apache::lonnet::put('discussiontimes',\%storenewentry,          &Apache::lonnet::put('discussiontimes',\%storenewentry,
                      $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=&Apache::lonnet::restore('_discussion');
     my ($temp)=keys %record;      my ($temp)=keys %record;
Line 2437  sub adddiscuss { Line 2606  sub adddiscuss {
 # ----------------------------------------------------------- Preview function  # ----------------------------------------------------------- Preview function
   
 sub show_preview {  sub show_preview {
     my $r=shift;      my ($r) = @_;
     my $message=&clear_out_html($ENV{'form.comment'});      &Apache::loncommon::content_type($r,'text/html');
     $message=~s/\n/\<br \/\>/g;      $r->send_http_header;
       my $message=&clear_out_html($env{'form.comment'});
       &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'});      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);
     $r->print('<table border="2"><tr><td>'.      my $start_page=
        '<b>Subject:</b> '.$subject.'<br /><br />'.   &Apache::loncommon::start_page('Preview',undef,
        $message.'</td></tr></table>');         {'only_body'   => 1,});
   
       my $end_page = &Apache::loncommon::end_page();
   
       $r->print($start_page.'<table border="2"><tr><td>'.
         '<b>Subject:</b> '.$subject.'<br /><br />'.
         $message.'</td></tr></table>'.$end_page);
   }
   
   
   sub newline_to_br {
       my ($message)=@_;
       my $newmessage;
       my $parser=HTML::LCParser->new($message);
       while (my $token=$parser->get_token()) {
    if ($token->[0] eq 'T') {
       my $text=$token->[1];
       $text=~s/\n/\<br \/\>/g;
       $newmessage.=$text;
    } elsif ($token->[0] eq 'D' || $token->[0] eq 'C') {
       $newmessage.=$token->[1];
    } elsif ($token->[0] eq 'PI' || $token->[0] eq 'E') {
       $newmessage.=$token->[2];
    } elsif ($token->[0] eq 'S') {
       $newmessage.=$token->[4];
    }
       
       }
       $$message=$newmessage;
 }  }
   
 sub generate_preview_button {  sub generate_preview_button {
       my ($formname,$fieldname)=@_;
       unless ($formname) { $formname='mailform'; }
       unless ($fieldname) { $fieldname='comment'; }
     my $pre=&mt("Show Preview and Check Spelling");      my $pre=&mt("Show Preview and Check Spelling");
     return(<<ENDPREVIEW);      return(<<ENDPREVIEW);
 <form name="preview" action="/adm/feedback?preview=1" method="post" target="preview">  <form name="preview" action="/adm/feedback?preview=1" method="post" target="preview">
 <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.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=document.mailform.comment.value;this.form.subject.value=document.mailform.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
 }  }
   
 sub modify_attachments {  sub modify_attachments {
     my ($r,$currnewattach,$currdelold,$symb,$idx,$attachmenturls)=@_;      my ($r,$currnewattach,$currdelold,$symb,$idx,$attachmenturls)=@_;
     my $subject=&clear_out_html($ENV{'form.subject'});      my $orig_subject = &Apache::lonnet::unescape($env{'form.subject'});
       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'};
     my $numoldver=$ENV{'form.numoldver'};      my $numoldver=$env{'form.numoldver'};
     my $bodytag=&Apache::loncommon::bodytag('Discussion Post Attachments',  
                                           '','');  
     my $msg = '';      my $msg = '';
     my %attachments = ();      my %attachments = ();
     my %currattach = ();      my %currattach = ();
     if ($idx) {      if ($idx) {
         &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);          &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);
     }      }
     $r->print(<<END);      &Apache::lonenc::check_encrypt(\$symb);
 <html>      my $js = <<END;
 <head>  <script type="text/javascript">
 <title>Managing Attachments</title>  
 <script>  
  function setAction () {   function setAction () {
    document.modattachments.action = document.modattachments.origpage.value;     document.modattachments.action = document.modattachments.origpage.value;
    document.modattachments.submit();     document.modattachments.submit();
  }   }
 </script>   </script> 
 </head>  END
 $bodytag  
       my $start_page = 
    &Apache::loncommon::start_page('Discussion Post Attachments',$js);
       my $end_page = 
    &Apache::loncommon::end_page();
          
       $r->print(<<END);
 <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">
  <table border="2">   <table border="2">
   <tr>    <tr>
    <td>     <td>
     <b>Subject:</b>$subject</b><br /><br />      <b>Subject:</b> $subject</b><br /><br />
 END  END
     if ($idx) {      if ($idx) {
         if ($attachmenturls) {          if ($attachmenturls) {
Line 2503  END Line 2709  END
                 foreach my $id (@currold) {                  foreach my $id (@currold) {
                     my $attachurl = &HTML::Entities::decode($attachments{$id}{'filename'});                       my $attachurl = &HTML::Entities::decode($attachments{$id}{'filename'}); 
                     $attachurl =~ m#/([^/]+)$#;                      $attachurl =~ m#/([^/]+)$#;
                     $r->print('<input type="checkbox" name="deloldattach" value="'.$id.'" />&nbsp;'.$1.'<br />'."\n");                      $r->print('<label><input type="checkbox" name="deloldattach" value="'.$id.'" />&nbsp;'.$1.'</label><br />'."\n");
                 }                  }
                 $r->print("<br />");                  $r->print("<br />");
             }              }
Line 2513  END Line 2719  END
         $r->print("The following attachments have been uploaded for inclusion with this posting.<br />Check the checkboxes for any you wish to remove<br />\n");          $r->print("The following attachments have been uploaded for inclusion with this posting.<br />Check the checkboxes for any you wish to remove<br />\n");
         foreach (@{$currnewattach}) {          foreach (@{$currnewattach}) {
             $_ =~ m#/([^/]+)$#;              $_ =~ m#/([^/]+)$#;
             $r->print('<input type="checkbox" name="delnewattach" value="'.$_.'" />&nbsp;'.$1.'<br />'."\n");              $r->print('<label><input type="checkbox" name="delnewattach" value="'.$_.'" />&nbsp;'.$1.'</label><br />'."\n");
         }          }
         $r->print("<br />");           $r->print("<br />"); 
     }      }
Line 2522  END Line 2728  END
    </td>     </td>
   </tr>    </tr>
  </table>   </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'}" />
 <input type="hidden" name="idx" value="$ENV{'form.idx'}" />  <input type="hidden" name="idx" value="$env{'form.idx'}" />
 <input type="hidden" name="numoldver" value="$ENV{'form.numoldver'}" />  <input type="hidden" name="numoldver" value="$env{'form.numoldver'}" />
 <input type="hidden" name="origpage" value="$ENV{'form.origpage'}" />  <input type="hidden" name="origpage" value="$env{'form.origpage'}" />
 <input type="hidden" name="anondiscuss" value="$ENV{'form.anondiscuss'}" />  <input type="hidden" name="anondiscuss" value="$env{'form.anondiscuss'}" />
 <input type="hidden" name="discuss" value="$ENV{'form.discuss'}" />  <input type="hidden" name="blog" value="$env{'form.blog'}" />
   <input type="hidden" name="discuss" value="$env{'form.discuss'}" />
 END  END
     foreach (@{$currnewattach}) {      foreach (@{$currnewattach}) {
         $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");          $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");
Line 2540  END Line 2747  END
     $r->print(<<END);      $r->print(<<END);
  <input type="button" name="rtntoedit" value="Store Changes" onClick="setAction()"/>   <input type="button" name="rtntoedit" value="Store Changes" onClick="setAction()"/>
 </form>  </form>
 </body>  $end_page
 </html>  
 END  END
     return;      return;
 }  }
   
 sub process_attachments {  sub process_attachments {
     my ($currnewattach,$currdelold,$keepold) = @_;      my ($currnewattach,$currdelold,$keepold) = @_;
     if (exists($ENV{'form.currnewattach'})) {  
         if (ref($ENV{'form.currnewattach'}) eq 'ARRAY') {      @{$currnewattach}=
             @{$currnewattach} = @{$ENV{'form.currnewattach'}};   &Apache::loncommon::get_env_multiple('form.currnewattach');
         } else {      @{$currdelold}=
             $$currnewattach[0] = $ENV{'form.currnewattach'};   &Apache::loncommon::get_env_multiple('form.deloldattach');
         }      if (exists($env{'form.delnewattach'})) {
     }          my @currdelnew =
     if (exists($ENV{'form.deloldattach'})) {      &Apache::loncommon::get_env_multiple('form.delnewattach');
         if (ref($ENV{'form.deloldattach'}) eq 'ARRAY') {  
             @{$currdelold} = @{$ENV{'form.deloldattach'}};  
         } else {  
             $$currdelold[0] = $ENV{'form.deloldattach'};  
         }  
     }  
     if (exists($ENV{'form.delnewattach'})) {  
         my @currdelnew = ();  
         my @currnew = ();          my @currnew = ();
         if (ref($ENV{'form.delnewattach'}) eq 'ARRAY') {  
             @currdelnew = @{$ENV{'form.delnewattach'}};  
         } else {  
             $currdelnew[0] = $ENV{'form.delnewattach'};  
         }  
         foreach my $newone (@{$currnewattach}) {          foreach my $newone (@{$currnewattach}) {
             my $delflag = 0;              my $delflag = 0;
             foreach (@currdelnew) {              foreach (@currdelnew) {
Line 2584  sub process_attachments { Line 2777  sub process_attachments {
         }          }
         @{$currnewattach} = @currnew;          @{$currnewattach} = @currnew;
     }      }
     if (exists($ENV{'form.keepold'})) {      @{$keepold} = &Apache::loncommon::get_env_multiple('form.keepold');
         if (ref($ENV{'form.keepold'}) eq 'ARRAY') {  
             @{$keepold} = @{$ENV{'form.keepold'}};  
         } else {  
             $$keepold[0] = $ENV{'form.keepold'};  
         }  
     }  
 }  }
   
 sub generate_attachments_button {  sub generate_attachments_button {
Line 2600  sub generate_attachments_button { Line 2787  sub generate_attachments_button {
     my $response = (<<END);      my $response = (<<END);
 <form name="attachment" action="/adm/feedback?attach=$ressymb" method="post">  <form name="attachment" action="/adm/feedback?attach=$ressymb" method="post">
 Click to add/remove attachments:&nbsp;<input type="button" value="$att"  Click to add/remove attachments:&nbsp;<input type="button" value="$att"
 onClick="this.form.subject.value=document.mailform.subject.value;this.form.comment.value=document.mailform.comment.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
     unless ($mode eq 'board') {      unless ($mode eq 'board') {
         $response .= 'javascript:anonchk();';          $response .= 'javascript:anonchk();';
Line 2612  this.form.submit();" /> Line 2799  this.form.submit();" />
 <input type="hidden" name="timestamp" value="$now" />  <input type="hidden" name="timestamp" value="$now" />
 <input type="hidden" name="subject" />  <input type="hidden" name="subject" />
 <input type="hidden" name="comment" />  <input type="hidden" name="comment" />
 <input type="hidden" name="anondiscuss" value = "0";  <input type="hidden" name="blog" value = "0" />
 <input type="hidden" name="discuss" value = "0";  <input type="hidden" name="anondiscuss" value = "0" />
   <input type="hidden" name="discuss" value = "0" />
 <input type="hidden" name="numoldver" value="$numoldver" />  <input type="hidden" name="numoldver" value="$numoldver" />
 ENDATTACH  ENDATTACH
     if (defined($deloldattach)) {      if (defined($deloldattach)) {
Line 2690  sub construct_attachmenturl { Line 2878  sub construct_attachmenturl {
     my $newattachmenturl;      my $newattachmenturl;
     my $startnum = 0;      my $startnum = 0;
     my $currver = 0;      my $currver = 0;
     if (($ENV{'form.editdisc'}) && ($idx)) {      if (($env{'form.editdisc'}) && ($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'});
         $oldattachmenturl = $contrib{$idx.':attachmenturl'};          $oldattachmenturl = $contrib{$idx.':attachmenturl'};
         if ($contrib{$idx.':history'}) {          if ($contrib{$idx.':history'}) {
             if ($contrib{$idx.':history'} =~ /:/) {              if ($contrib{$idx.':history'} =~ /:/) {
Line 2740  sub construct_attachmenturl { Line 2928  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 = $resource->wrap_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 2752  sub handler { Line 2980  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','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','sendmessageonly']);
   if ($ENV{'form.discsymb'}) {    if ($env{'form.editdisc'}) {
       my $symb = $ENV{'form.discsymb'};        if (!(&editing_allowed())) {
             my $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
             my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
             my $feedurl=&Apache::lonnet::clutter($url);
             &redirect_back($r,$feedurl,&mt('Editing not permitted').'<br />',                     '0','0','','',$env{'form.previous'},'','','',);
             return OK;
         }
     } 
     if ($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\./) {
                   $readinghash{$readkey} =~ s/\.$1\.//;                    $readinghash{$readkey} =~ s/\.$1\.//;
Line 2773  sub handler { Line 3009  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');
         &Apache::loncommon::no_cache($r);
       $r->send_http_header;        $r->send_http_header;
       my $bodytag=&Apache::loncommon::bodytag('Discussion Post Versions',  
                                           '','');        $r->print(&Apache::loncommon::start_page('Discussion Post Versions'));
       $r->print (<<END);  
 <html>        my $crs='/'.$env{'request.course.id'};
 <head>        if ($env{'request.course.sec'}) {
 <title>Post Versions</title>            $crs.='_'.$env{'request.course.sec'};
 <meta http-equiv="pragma" content="no-cache" />  
 </head>  
 $bodytag  
 END  
       my $crs='/'.$ENV{'request.course.id'};  
       if ($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 2814  END Line 3038  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);  
       }        }
         $r->print(&Apache::loncommon::end_page());
       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')  
           my $ressymb=$_;            my $ressymb=$_;
           if ($ressymb =~ m/bulletin___\d+___/) {    &Apache::lonenc::check_decrypt(\$ressymb);
               unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {  
                   $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper/|;  
               }  
           }  
           my $lastkey = $ressymb.'_lastread';            my $lastkey = $ressymb.'_lastread';
           $discinfo{$lastkey} = time;            $discinfo{$lastkey} = $env{'form.navtime'};
         }
         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::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});  
       &Apache::loncommon::content_type($r,'text/html');        &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;        $r->send_http_header;
         my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
         my %onload = ('onload' => "if (window.name!='loncapaclient') { this.document.reldt.submit(); self.window.close(); }");
         my $start_page=
     &Apache::loncommon::start_page('New posts marked as read',undef,
    {'redirect'    => [2,$feedurl],
     'only_body'   => 1,
     'add_entries' => \%onload});
         my $end_page = &Apache::loncommon::end_page();
       $r->print (<<ENDREDIR);        $r->print (<<ENDREDIR);
 <html>  $start_page
 <head>  <img align="right" src="$logo" />
 <title>New posts marked as read</title>  $textline
 <meta http-equiv="pragma" content="no-cache" />  
 <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />  
 </head>  
 <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>  
 <img align="right" src="/adm/lonIcons/lonlogos.gif" />  
 <b>$lt{'mnpa'} $numitems $lt{'robb'}</b>  
 <form name="reldt" action="$feedurl" target="loncapaclient">  <form name="reldt" action="$feedurl" target="loncapaclient">
 </form>  </form>
 <a href="$feedurl">Continue</a>  <br />
 </body>  $end_page
 </html>  
 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 
 # ----------------------------------------------------------------- Modify display setting for this discussion         if ($env{'form.allposts'}) {
           my $symb;    $discinfo{$symb.'_showonlyunread'} = 0;
           if ($ENV{'form.allposts'}) {    $discinfo{$symb.'_showonlyunmark'} = 0;
               $symb = $ENV{'form.allposts'};        }
           } elsif ($ENV{'form.onlyunread'}) {        if ($env{'form.onlyunread'}) { $discinfo{$symb.'_showonlyunread'} = 1;  }
               $symb = $ENV{'form.onlyunread'};        if ($env{'form.onlyunmark'}) { $discinfo{$symb.'_showonlyunmark'} = 1;  }
           } else {  # ----------------------------------------------------- Mark new posts not NEW 
               $symb = $ENV{'form.onlyunmark'};        if ($env{'form.markread'})   { $discinfo{$symb.'_lastread'} = time; }
           }        &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',
           my $ressymb = $symb;     \%discinfo,$env{'user.domain'},$env{'user.name'});
           ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);        my $previous=$env{'form.previous'};
           unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {        if ($env{'form.markondisp'}) { $previous=undef; }
               $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;        &redirect_back($r,$feedurl,&mt('Changed display status').'<br />',
           }       '0','0','','',$previous);
           my %discinfo = ();        return OK;
           if ($ENV{'form.allposts'}) {    } elsif (($env{'form.hide'}) || ($env{'form.unhide'})) {
               $discinfo{$ressymb.'_showonlyunread'} = 0;  # ----------------------------------------------------------------- Hide/unhide
               $discinfo{$ressymb.'_showonlyunmark'} = 0;        my $entry=$env{'form.hide'}?$env{'form.hide'}:$env{'form.unhide'};
           } elsif ($ENV{'form.onlyunread'}) {        my ($symb,$idx)=split(/\:\:\:/,$entry);
               $discinfo{$ressymb.'_showonlyunread'} = 1;        ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
           } else {  
               $discinfo{$ressymb.'_showonlyunmark'} = 1;        my $crs='/'.$env{'request.course.id'};
           }        if ($env{'request.course.sec'}) {
           &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});            $crs.='_'.$env{'request.course.sec'};
       }        }
       if (($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || ($ENV{'form.onlyunmark'}) ||($ENV{'form.toggoff'}) || ($ENV{'form.toggon'}) ) {        $crs=~s/\_/\//g;
           &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0','',$previous);        my $seeid=&Apache::lonnet::allowed('rin',$crs);
   
         if ($env{'form.hide'} && !$seeid && !(&editing_allowed())) {
             &redirect_back($r,$feedurl,&mt('Deletion not permitted').'<br />',                 '0','0','','',$env{'form.previous'},'','','',);
             return OK;
         }
   
         my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                             $env{'course.'.$env{'request.course.id'}.'.domain'},
             $env{'course.'.$env{'request.course.id'}.'.num'});
   
         my $currenthidden=$contrib{'hidden'};
         my $currentstudenthidden=$contrib{'studenthidden'};
   
         if ($env{'form.hide'}) {
     $currenthidden.='.'.$idx.'.';
     unless ($seeid) {
         $currentstudenthidden.='.'.$idx.'.';
     }
       } else {        } else {
           &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0');    $currenthidden=~s/\.$idx\.//g;
       }        }
       return OK;        my %newhash=('hidden' => $currenthidden);
   } elsif ($ENV{'form.markread'}) {        if ( ($env{'form.hide'}) && (!$seeid) ) {
 # ----------------------------------------------------------------- Mark new posts not NEW     $newhash{'studenthidden'} = $currentstudenthidden;
       &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 = ();  
       my $lastkey = $ressymb.'_lastread';  
       $discinfo{$lastkey} = time;  
       &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});  
       &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed reading status').'<br />','0','0');  
       return OK;  
   } elsif (($ENV{'form.hide'}) || ($ENV{'form.unhide'})) {  
 # ----------------------------------------------------------------- Hide/unhide  
     &Apache::loncommon::content_type($r,'text/html');  
     $r->send_http_header;  
   
     my $entry=$ENV{'form.hide'}?$ENV{'form.hide'}:$ENV{'form.unhide'};  
   
     my ($symb,$idx)=split(/\:\:\:/,$entry);  
     my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);  
   
     my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},  
                      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
      $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
   
           
     my $currenthidden=$contrib{'hidden'};  
     my $currentstudenthidden=$contrib{'studenthidden'};  
   
     my $crs='/'.$ENV{'request.course.id'};  
     if ($ENV{'request.course.sec'}) {  
         $crs.='_'.$ENV{'request.course.sec'};  
     }  
     $crs=~s/\_/\//g;  
     my $seeid=&Apache::lonnet::allowed('rin',$crs);  
       
     if ($ENV{'form.hide'}) {  
  $currenthidden.='.'.$idx.'.';  
         unless ($seeid) {  
             $currentstudenthidden.='.'.$idx.'.';  
         }  
     } 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;
             } elsif ($env{'form.preview'}) {
     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'}) {  
 # -------------------------------------------------------- User wants a preview  # -------------------------------------------------------- User wants a preview
       $r->content_type('text/html');  
       $r->send_http_header;  
       &show_preview($r);        &show_preview($r);
   } elsif ($ENV{'form.attach'}) {        return OK;
     } 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','blog']);
       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 $idx = $ENV{'form.idx'};        my ($symb) = &get_feedurl_and_clean_symb($env{'form.attach'});
       my $symb = $ENV{'form.attach'};        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'},                           $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;    } elsif ($env{'form.export'}) {
       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'}) {  
       &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'};        if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {
       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)$/) {  
           $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); 
 #      &build_ims_export($r,$symb,$previous,$feedurl);        my $start_page = 
       my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion');    &Apache::loncommon::start_page('Resource Feedback and Discussion');
       $r->print($bodytag.$discussion);                                             my $end_page = 
     &Apache::loncommon::end_page();
         $r->print($start_page.$discussion.$end_page);
       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);  
       $feedurl=&Apache::lonnet::clutter($url);  
   } elsif ($ENV{'form.editdisc'}) {  
       $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.editdisc'}) {
     $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);
         $feedurl=&Apache::lonnet::clutter($url);
     }
         }
         &Apache::lonenc::check_decrypt(\$symb);
         my $goahead=1;
         if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form|task)$/) {
     unless ($symb) { $goahead=0; }
         }
         # backward compatibility (bulletin boards used to be 'wrapped')
         &dewrapper(\$feedurl);
         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);
     return OK;
         }
 # --------------------------------------------------- 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 3270  ENDREDIR Line 3372  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);
       } elsif ($ENV{'form.attachment.filename'}) {    $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|;
   unless (length($ENV{'form.attachment'})>131072) {    $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);
         } elsif ($env{'form.attachment.filename'}) {
     unless (length($env{'form.attachment'})>131072) {
       $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');        $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');
   }    }
       }        }
 # 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 $message=&clear_out_html($env{'form.comment'});
   
 # 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(&clear_out_html($env{'form.subject'}),$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'}));
     $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,
     $subject);
   $numpost++;    $numpost++;
       }        }
   
       if ($ENV{'form.anondiscuss'}) {  # Add to blog?
           my $subject = &clear_out_html($ENV{'form.subject'});  
   $typestyle.=&adddiscuss($symb,$message,1,$attachmenturl,$subject);        my $blog='';
   $numpost++;        if ($env{'form.blog'}) {
     my $subject = &clear_out_html($env{'form.subject'});
     $status.=&Apache::lonrss::addentry($env{'user.name'},
       $env{'user.domain'},
       'CourseBlog_'.$env{'request.course.id'},
       $subject,$message,$feedurl,'public');
     $blog='<br />'.&mt('Added to my course blog').'<br />';
       }        }
     
   # Receipt screen and redirect back to where came from
         &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$blog,$status,$env{'form.previous'});
     }
     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||;
       }
   }
   
 # Receipt screen and redirect back to where came from  sub get_feedurl {
       &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$status,$ENV{'form.previous'});      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|;
     }      }
    } else {      my $feedurl = &get_feedurl($symb);
 # Unable to give feedback      return ($symb,$feedurl);
     &no_redirect_back($r,$feedurl);  }
    }  
   } else {  sub editing_allowed {
 # Ambiguous Problem Resource      my $can_edit = 0;
       if ( &Apache::lonnet::mod_perl_version() == 2 ) {      my $cid = $env{'request.course.id'};
   &Apache::lonnet::cleanenv();      my $role = (split(/\./,$env{'request.role'}))[0];
       }      my $section = $env{'request.course.sec'};
       $r->internal_redirect('/adm/ambiguous');      my $allow_editing_config = 
   }   $env{'course.'.$cid.'.allow_discussion_post_editing'};
       if ($allow_editing_config =~ m/^\s*yes\s*$/i) {
           $can_edit = 1;
       } else {
    foreach my $editor (split(/,/,$allow_editing_config)) {
       my ($editor_role,$editor_sec) = split(/:/,$editor);
       if ($editor_role eq $role
    && defined($editor_sec)
    && defined($section)
    && $editor_sec eq $section) {
    $can_edit = 1;
    last;
       }
       if ($editor_role eq $role
    && !defined($editor_sec)) {
    $can_edit = 1;
       }
    }
       }
       return $can_edit;
 }  }
   return OK;  
 }   
   
 1;  1;
 __END__  __END__

Removed from v.1.120  
changed lines
  Added in v.1.190


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.