Diff for /loncom/interface/lonfeedback.pm between versions 1.185 and 1.331

version 1.185, 2006/03/15 22:06:08 version 1.331, 2012/01/10 00:54:05
Line 41  use Apache::lonnavmaps; Line 41  use Apache::lonnavmaps;
 use Apache::lonenc();  use Apache::lonenc();
 use Apache::lonrss();  use Apache::lonrss();
 use HTML::LCParser();  use HTML::LCParser();
   #use HTML::Tidy::libXML;
 use Apache::lonspeller();  use Apache::lonspeller();
   use Apache::longroup;
 use Cwd;  use Cwd;
   use LONCAPA;
   
 sub discussion_open {  sub discussion_open {
     my ($status,$symb)=@_;      my ($status,$symb)=@_;
   # Advanced roles can always discuss
     if ($env{'request.role.adv'}) { return 1; }      if ($env{'request.role.adv'}) { return 1; }
   # Get discussion closing date
       my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);
   # If it is defined and in the future, the instructor wants this discussion to be open
       if (defined($close) && $close ne '' && $close > time) {
           return 1;
       }
   # It was not explicitly open, check if the problem is available.
   # If the problem is not available, close the discussion 
     if (defined($status) &&      if (defined($status) &&
  !($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'   !($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'
   || $status eq 'OPEN')) {    || $status eq 'OPEN')) {
  return 0;   return 0;
     }      }
     my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);  # The problem is available, but check if the instructor explictly closed discussion
     if (defined($close) && $close ne '' && $close < time) {      if (defined($close) && $close ne '' && $close < time) {
  return 0;   return 0;
     }      }
Line 71  sub discussion_visible { Line 83  sub discussion_visible {
 }  }
   
 sub list_discussion {  sub list_discussion {
     my ($mode,$status,$ressymb,$imsextras)=@_;      my ($mode,$status,$ressymb,$imsextras,$group)=@_;
       unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }
       unless ($ressymb) { return ''; }
       $ressymb=&wrap_symb($ressymb);
     my $outputtarget=$env{'form.grade_target'};      my $outputtarget=$env{'form.grade_target'};
     if (defined($env{'form.export'})) {      if (defined($env{'form.export'})) {
  if($env{'form.export'}) {   if($env{'form.export'}) {
Line 83  sub list_discussion { Line 98  sub list_discussion {
             $outputtarget = 'export';              $outputtarget = 'export';
         }          }
     }      }
     if (not &discussion_visible($status)) { return ''; }      if (not &discussion_visible($status)) {
     my @bgcols = ("#cccccc","#eeeeee");          if ($mode ne 'board') {
               &Apache::lonenc::check_encrypt(\$ressymb); 
               return '<br /><div class="LC_feedback_link">'.&send_message_link($ressymb)."</div>";
           }
       }
       if ($group ne '' && $mode eq 'board') {
           if (&check_group_priv($group,'vgb') ne 'ok') {
               return '';
           }
       }
   
       my ($blocked,$blocktext) = 
           &Apache::loncommon::blocking_status('boards');
       if ($blocked) {
           $blocktext = '<br /><div class="LC_feedback_link"><span class="LC_feedback_link">'.$blocktext."</span>";
           &Apache::lonenc::check_encrypt(\$ressymb);
           if ($mode ne 'board') {
               $blocktext.=&send_message_link($ressymb).'</div>';
           }else{
               $blocktext.="</div>";
           }
           return $blocktext; 
       }
   
       my @bgcols = ("LC_disc_old_item","LC_disc_new_item");
     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 ''; }
Line 94  sub list_discussion { Line 133  sub list_discussion {
  $crs.='_'.$env{'request.course.sec'};   $crs.='_'.$env{'request.course.sec'};
     }      }
     $crs=~s/\_/\//g;      $crs=~s/\_/\//g;
     unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }  
     unless ($ressymb) { return ''; }  
     $ressymb=&wrap_symb($ressymb);  
     my $encsymb=&Apache::lonenc::check_encrypt($ressymb);      my $encsymb=&Apache::lonenc::check_encrypt($ressymb);
     my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)      my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
   && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form|task)$/));    && ($ressymb=~/$LONCAPA::assess_re/));
           
     my %usernamesort = ();      my %usernamesort = ();
     my %namesort =();      my %namesort =();
Line 124  sub list_discussion { Line 160  sub list_discussion {
     my $previous = 0;      my $previous = 0;
     my $visit = 0;      my $visit = 0;
     my $newpostsflag = 0;      my $newpostsflag = 0;
     my @posters = split/\&/,$dischash{$userpickkey};      my @posters = split(/\&/,$dischash{$userpickkey});
   
 # 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','grouppick','totposters']);
     my $sortposts = $env{'form.sortposts'};      my $sortposts = $env{'form.sortposts'};
     my $statusfilter = $env{'form.statusfilter'};      my $statusfilter = $env{'form.statusfilter'};
     my @sectionpick = ();      my @sectionpick = split(/,/,$env{'form.sectionpick'});
     if ($env{'form.sectionpick'} =~ /,/) {      my @grouppick   = split(/,/,$env{'form.grouppick'});
         @sectionpick = split/,/,$env{'form.sectionpick'};      my @rolefilter  = split(/,/,$env{'form.rolefilter'});
     } else {  
         $sectionpick[0] = $env{'form.sectionpick'};  
     }  
     my @rolefilter = ();  
     if ($env{'form.rolefilter'} =~ /,/) {  
         @rolefilter = split/,/,$env{'form.rolefilter'};  
     } else {  
         $rolefilter[0] = $env{'form.rolefilter'};  
     }  
     my $totposters = $env{'form.totposters'};      my $totposters = $env{'form.totposters'};
     $previous = $env{'form.previous'};      $previous = $env{'form.previous'};
     if ($previous > 0) {      if ($previous > 0) {
Line 152  sub list_discussion { Line 180  sub list_discussion {
         }          }
     }      }
   
       my $cdom = $env{'course.'.$cid.'.domain'};
       my $cnum = $env{'course.'.$cid.'.num'};
       my $crstype = &Apache::loncommon::course_type();
   
 # Get information about students and non-students in course for filtering display of posts  # Get information about students and non-students in course for filtering display of posts
     my %roleshash = ();      my %roleshash = ();
     my %roleinfo = ();      my %roleinfo = ();
       my ($classgroups,$studentgroups);
     if ($env{'form.rolefilter'}) {      if ($env{'form.rolefilter'}) {
         %roleshash = &Apache::lonnet::dump('nohist_userroles',          %roleshash = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
    $env{'course.'.$cid.'.domain'},          foreach my $rolekey (keys(%roleshash)) {
    $env{'course.'.$cid.'.num'});              my ($role,$uname,$udom,$sec) = split(/:/,$rolekey);
         foreach (keys %roleshash) {  
             my ($role,$uname,$udom,$sec) = split/:/,$_;  
             if ($role =~ /^cr/) {              if ($role =~ /^cr/) {
                 $role = 'cr';                  $role = 'cr';
             }              }
             my ($end,$start) = split/:/,$roleshash{$_};              my ($end,$start) = split(/:/,$roleshash{$rolekey});
             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';
             }              }
             if ($uname && $udom) {               if ($uname && $udom) { 
                 push @{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status;                  push(@{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status);
             }              }
         }          }
         my ($classlist) = &Apache::loncoursedata::get_classlist(          my ($classlist,$keylist) =
                               $env{'course.'.$cid.'.domain'},                           &Apache::loncoursedata::get_classlist($cdom,$cnum);
                               $env{'course.'.$cid.'.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) {
             my ($section,$status) = ($data->[$sec_index],              my ($section,$status) = ($data->[$sec_index],
                                  $data->[$status_index]);                                   $data->[$status_index]);
             push @{$roleinfo{$student}}, 'st:'.$section.':'.$status;              push(@{$roleinfo{$student}}, 'st:'.$section.':'.$status);
         }          }
    ($classgroups,$studentgroups) = 
       &Apache::loncoursedata::get_group_memberships($classlist,$keylist,
     $cdom,$cnum);
     }      }
   
 # Get discussion display default settings for user  # Get discussion display default settings for user
Line 223  sub list_discussion { Line 256  sub list_discussion {
     }      }
     $visit ++;      $visit ++;
   
     my $seeid=&Apache::lonnet::allowed('rin',$crs);      my $seeid;
       if (($group ne '') && ($mode eq 'board') && 
           ($ressymb =~ m|^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|)) {
           if (&check_group_priv($group,'dgp') eq 'ok') {
               $seeid = 1;
           }
       } else {
           $seeid=&Apache::lonnet::allowed('rin',$crs);
       }
     my @discussionitems=();      my @discussionitems=();
     my %shown = ();      my %shown = ();
     my @posteridentity=();      my @posteridentity=();
Line 240  sub list_discussion { Line 281  sub list_discussion {
     my $maxdepth=0;      my $maxdepth=0;
     my %anonhash=();      my %anonhash=();
     my $anoncnt=0;      my $anoncnt=0;
     my $target='';  
     unless ($env{'browser.interface'} eq 'textual' ||  
     $env{'environment.remote'} eq 'off' ) {  
  $target='target="LONcom"';  
     }  
   
     my $now = time;      my $now = time;
     $discinfo{$visitkey} = $visit;      $discinfo{$visitkey} = $visit;
   
     &Apache::lonnet::put('nohist_'.$cid.'_discuss',\%discinfo,$env{'user.domain'},$env{'user.name'});      &Apache::lonnet::put('nohist_'.$cid.'_discuss',\%discinfo,$env{'user.domain'},$env{'user.name'});
     &build_posting_display(\%usernamesort,\%subjectsort,\%namesort,\%notshown,\%newitem,\%dischash,\%shown,\%alldiscussion,\%imsitems,\%imsfiles,\%roleinfo,\@discussionitems,\@replies,\@depth,\@posters,\$maxdepth,\$visible,\$newpostsflag,\$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$encsymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,$statusfilter,$toggkey,$outputtarget,\%anonhash,$anoncnt);      &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,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,\@grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,\%anonhash,$anoncnt,$group);
   
     my $discussion='';      my $discussion='';
     my $manifestfile;      my $manifestfile;
Line 260  sub list_discussion { Line 296  sub list_discussion {
     my $copyresult;      my $copyresult;
   
     my $function = &Apache::loncommon::get_users_function();      my $function = &Apache::loncommon::get_users_function();
     my $color = &Apache::loncommon::designparm($function.'.tabbg',  
                                                     $env{'user.domain'});  
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'cuse' => 'Current discussion settings',          'cuse' => 'My settings for this discussion',
         'allposts' => 'All posts',          'allposts' => 'All posts',
         'unread' => 'New posts only',          'unread' => 'New posts only',
         'unmark' => 'Unread only',          'unmark' => 'Unread only',
Line 278  sub list_discussion { Line 312  sub list_discussion {
         'disp' => 'Display',          'disp' => 'Display',
         'nolo' => 'Not new',          'nolo' => 'Not new',
         'togg' => 'Toggle read/unread',          'togg' => 'Toggle read/unread',
           'aner' => 'An error occurred opening the manifest file.',
           'difo' => 'Discussion for',
           'aerr' => 'An error occurred opening the export file for posting',
           'aysu' => 'Are you sure you want to delete this post?',
           'dpwn' => 'Deleted posts will no longer be visible to you and other students',
           'bwco' => 'but will continue to be visible to your instructor',
           'depo' => 'Deleted posts will no longer be visible to you or anyone else.',
           'discussions' => 'DISCUSSIONS'
     );      );
   
     my $currdisp = $lt{'allposts'};      my $currdisp = $lt{'allposts'};
Line 318  sub list_discussion { Line 360  sub list_discussion {
         $togglink = 'toggoff';          $togglink = 'toggoff';
     }       } 
         
     $chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;      $chglink .= '&amp;changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;
   
     if ($newpostsflag) {      if ($newpostsflag) {
         $chglink .= '&previous='.$prevread;          $chglink .= '&amp;previous='.$prevread;
     }      }
       $chglink.=&group_args($group);
   
     if ($visible) {      if ($visible) {
 # Print the discusssion  # Print the discusssion
         if ($outputtarget eq 'tex') {          if ($outputtarget eq 'tex') {
             $discussion.='<tex>{\tiny \vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.              $discussion.='<tex>{\tiny \vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.
                          '\textbf{DISCUSSIONS}\makebox[2 cm][b]{\hrulefill}'.                           '\textbf{'.$lt{'discussions'}.'}\makebox[2 cm][b]{\hrulefill}\vskip 0 mm'.
                          '\vskip 0 mm\noindent\textbf{'.$lt{'cuse'}.'}:\vskip 0 mm'.  
                          '\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.                           '\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.
                          '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}}</tex>';                           '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}}</tex>';
         } elsif ($outputtarget eq 'export') {          } elsif ($outputtarget eq 'export') {
Line 363  sub list_discussion { Line 405  sub list_discussion {
             my $manifestfilename = $tempexport.$manifest;              my $manifestfilename = $tempexport.$manifest;
             if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {              if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {
                 $manifestok=1;                  $manifestok=1;
                 print $manifestfile qq|                  print $manifestfile qq|<?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>  
 <manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2  <manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
 identifier="MANIFEST-$ressymb" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1   identifier="MANIFEST-$ressymb" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 
 imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">  imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">
   <organizations default="$ressymb">    <organizations default="$ressymb">
     <organization identifier="$ressymb">      <organization identifier="$ressymb">
       <title>Discussion for $ressymb</title>\n|;        <title>$lt{'difo'} $ressymb</title>\n|;
             } else {              } else {
                 $discussion .= 'An error occurred opening the manifest file.<br />';                  $discussion .= $lt{'aner'}.'<br />';
             }              }
  } else {   } else {
             my $colspan=$maxdepth+1;              my $colspan=$maxdepth+1;
             $discussion.= qq|              $discussion.= &Apache::lonhtmlcommon::scripttag(qq|
 <script>     function verifydelete (caller,symb,idx,newflag,previous,groupparm) {
    function studentdelete (symb,idx,newflag,previous) {  
        var symbparm = symb+':::'+idx         var symbparm = symb+':::'+idx
        var prevparm = ""         var prevparm = ""
        if (newflag == 1) {         if (newflag == 1) {
            prevparm = "&previous="+previous             prevparm = "&amp;previous="+previous
          }
          if (caller == 'studentdelete') {
              if (confirm("$lt{'aysu'}\\n$lt{'dpwn'},\\n$lt{'bwco'}")) {
                  document.location.href = "/adm/feedback?hide="+symbparm+prevparm+groupparm
              }
          } else {
              if (caller == 'seeiddelete') {
                  if (confirm("$lt{'aysu'}\\n$lt{'depo'}")) {
                      document.location.href = "/adm/feedback?deldisc="+symbparm+prevparm+groupparm
                  }
              }
        }         }
        if (confirm("Are you sure you want to delete this post?\\nDeleted posts will no longer be visible to you and other students,\\nbut will continue to be visible to your instructor")) {  
            document.location.href = "/adm/feedback?hide="+symbparm+prevparm  
        }    
    }     }
 </script>              |);
             |;      $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$ressymb.'" >'.
     $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$ressymb.'" ><table bgcolor="#AAAAAA" cellpadding="2" cellspacing="2" border="0">';                           "\n".'<table width="100%" class="LC_discussion">';
     $discussion .='<tr><td bgcolor="#DDDDBB" colspan="'.$colspan.'">'.              $discussion .= &action_links_bar($colspan,$ressymb,$visible,
  '<table border="0" width="100%" bgcolor="#DDDDBB"><tr>';                                               $newpostsflag,$group,
     my $escsymb=&Apache::lonnet::escape($ressymb);                                               $prevread,$markondisp);
     if ($visible>2) {              my $escsymb=&escape($ressymb);
  $discussion.='<td align="left">'.              my $numhidden = keys(%notshown);
     '<a href="/adm/feedback?cmd=threadedon&amp;symb='.$escsymb;  
  if ($newpostsflag) {  
     $discussion .= '&previous='.$prevread;  
  }  
  $discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.  
     '<a href="/adm/feedback?cmd=threadedoff&amp;symb='.$escsymb;  
  if ($newpostsflag) {  
     $discussion .= '&previous='.$prevread;  
  }  
  $discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;  
                               <a href= "/adm/feedback?cmd=sortfilter&amp;symb='.$escsymb;  
                 if ($newpostsflag) {  
                     $discussion .= '&previous='.$prevread;  
                 }  
                 $discussion .='">'.&mt('Sorting/Filtering options').'</a>&nbsp;&nbsp';  
             } else {  
                 $discussion .= '<td align="left">';  
             }  
             $discussion .='<a href= "/adm/feedback?export='.$escsymb;  
             if ($newpostsflag) {  
                 $discussion .= '&previous='.$prevread;  
             }  
             $discussion .= '">'.&mt('Export').'?</a>&nbsp;&nbsp;</td>';  
     if ($newpostsflag) {  
  if (!$markondisp) {  
     $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 {  
     $discussion .= '<td>&nbsp;</td>';  
  }  
     } else {  
  $discussion .= '<td>&nbsp;</td>';  
     }  
     $discussion .= '</tr></table></td></tr>';  
   
             my $numhidden = keys %notshown;  
             if ($numhidden > 0) {              if ($numhidden > 0) {
                 my $colspan = $maxdepth+1;                  my $colspan = $maxdepth+1;
                 $discussion.="\n".'<tr><td bgcolor="#CCCCCC" colspan="'.$colspan.'">'.                  $discussion.="\n".'<tr><td bgcolor="#CCCCCC" colspan="'.$colspan.'">'.
                          '<a href="/adm/feedback?allposts=1&amp;symb='.$escsymb;                           '<a href="/adm/feedback?allposts=1&amp;symb='.$escsymb;
                 if ($newpostsflag) {                  if ($newpostsflag) {
                     $discussion .= '&previous='.$prevread;                      $discussion .= '&amp;previous='.$prevread;
                 }                  }
    $discussion .= &group_args($group);
                 $discussion .= '">'.&mt('Show all posts').'</a> '.&mt('to display').' '.                  $discussion .= '">'.&mt('Show all posts').'</a> '.&mt('to display').' '.
                          $numhidden.' ';                           $numhidden.' ';
                 if ($showunmark) {                  if ($showunmark) {
Line 455  imscp_v1p1.xsd http://www.imsglobal.org/ Line 467  imscp_v1p1.xsd http://www.imsglobal.org/
 # Choose sort mechanism  # Choose sort mechanism
         my @showposts = ();          my @showposts = ();
         if ($sortposts eq 'descdate') {          if ($sortposts eq 'descdate') {
             @showposts = (sort { $b <=> $a } keys %alldiscussion);              @showposts = (sort { $b <=> $a } keys(%alldiscussion));
         } elsif ($sortposts eq 'thread') {          } elsif ($sortposts eq 'thread') {
             @showposts = (sort { $a <=> $b } keys %alldiscussion);              @showposts = (sort { $a <=> $b } keys(%alldiscussion));
         } elsif ($sortposts eq 'subject') {          } elsif ($sortposts eq 'subject') {
             foreach (sort keys %subjectsort) {              foreach my $key (sort(keys(%subjectsort))) {
                 push @showposts, @{$subjectsort{$_}};                  push(@showposts, @{$subjectsort{$key}});
             }              }
         } elsif ($sortposts eq 'username') {          } elsif ($sortposts eq 'username') {
             foreach my $domain (sort keys %usernamesort) {              foreach my $domain (sort(keys(%usernamesort))) {
                 foreach (sort keys %{$usernamesort{$domain}}) {                  foreach my $key (sort(keys(%{$usernamesort{$domain}}))) {
                     push @showposts, @{$usernamesort{$domain}{$_}};                      push(@showposts, @{$usernamesort{$domain}{$key}});
                 }                  }
             }              }
         } elsif ($sortposts eq 'lastfirst') {          } elsif ($sortposts eq 'lastfirst') {
             foreach my $last (sort keys %namesort) {              foreach my $last (sort(keys(%namesort))) {
                  foreach (sort keys %{$namesort{$last}}) {                   foreach my $key (sort(keys(%{$namesort{$last}}))) {
                      push @showposts, @{$namesort{$last}{$_}};                       push(@showposts, @{$namesort{$last}{$key}});
                  }                   }
             }              }
         } else {          } else {
             @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 my $post (@showposts) {
             unless (($sortposts eq 'thread') || (($sortposts eq '') && ($env{'environment.threadeddiscussion'})) || ($outputtarget eq 'export')) {              unless (($sortposts eq 'thread') || (($sortposts eq '') && ($env{'environment.threadeddiscussion'})) || ($outputtarget eq 'export')) {
                 $alldiscussion{$_} = $_;                  $alldiscussion{$post} = $post;
             }              }
             unless ( ($notshown{$alldiscussion{$_}} eq '1') || ($shown{$alldiscussion{$_}} == 0) ) {              unless ( ($notshown{$alldiscussion{$post}} eq '1') || ($shown{$alldiscussion{$post}} == 0) ) {
                 if ($outputtarget ne 'tex' && $outputtarget ne 'export') {                  if ($outputtarget ne 'tex' && $outputtarget ne 'export') {
     $discussion.="\n<tr>";      $discussion.="\n<tr>";
  }   }
         my $thisdepth=$depth[$alldiscussion{$_}];          my $thisdepth=$depth[$alldiscussion{$post}];
                 if ($outputtarget ne 'tex' && $outputtarget ne 'export') {                  if ($outputtarget ne 'tex' && $outputtarget ne 'export') {
     for (1..$thisdepth) {      for (1..$thisdepth) {
  $discussion.='<td>&nbsp;&nbsp;&nbsp;</td>';   $discussion.='<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>';
     }      }
  }   }
         my $colspan=$maxdepth-$thisdepth+1;          my $colspan=$maxdepth-$thisdepth+1;
                 if ($outputtarget eq 'tex') {                  if ($outputtarget eq 'tex') {
     #cleanup block      #cleanup block
     $discussionitems[$alldiscussion{$_}]=~s/<table([^>]*)>/<table TeXwidth="90 mm">/;      $discussionitems[$alldiscussion{$post}]=~s/<table([^>]*)>/<table TeXwidth="90 mm">/;
     $discussionitems[$alldiscussion{$_}]=~s/<tr([^>]*)><td([^>]*)>/<tr><td TeXwidth="20 mm" align="left">/;      $discussionitems[$alldiscussion{$post}]=~s/<tr([^>]*)><td([^>]*)>/<tr><td TeXwidth="20 mm" align="left">/;
                     my $threadinsert='';                      my $threadinsert='';
                     if ($thisdepth > 0) {                      if ($thisdepth > 0) {
  $threadinsert='<br /><strong>Reply: '.$thisdepth.'</strong>';   $threadinsert='<br /><strong>Reply: '.$thisdepth.'</strong>';
     }      }
     $discussionitems[$alldiscussion{$_}]=~s/<\/td><td([^>]*)>/$threadinsert<\/td><td TeXwidth="65 mm" align="left">/;      $discussionitems[$alldiscussion{$post}]=~s/<\/td><td([^>]*)>/$threadinsert<\/td><td TeXwidth="65 mm" align="left">/;
     $discussionitems[$alldiscussion{$_}]=~s/<a([^>]+)>(Edit|Hide|Delete|Reply|Submissions)<\/a>//g;                      $discussionitems[$alldiscussion{$post}]=~s/(<b>|<\/b>|<\/a>|<a([^>]+)>)//g;
                     $discussionitems[$alldiscussion{$_}]=~s/(<b>|<\/b>|<\/a>|<a([^>]+)>)//g;  
   
     $discussionitems[$alldiscussion{$_}]='<tex>\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}</tex>'.$discussionitems[$alldiscussion{$_}];      $discussionitems[$alldiscussion{$post}]='<tex>\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}</tex>'.$discussionitems[$alldiscussion{$post}];
     $discussion.=$discussionitems[$alldiscussion{$_}];      $discussion.=$discussionitems[$alldiscussion{$post}];
  } elsif ($outputtarget eq 'export') {   } elsif ($outputtarget eq 'export') {
                     my $postfilename = $alldiscussion{$_}.'-'.$imsitems{$alldiscussion{$_}}{'timestamp'}.'.html';                      my $postfilename = $alldiscussion{$post}.'-'.$imsitems{$alldiscussion{$post}}{'timestamp'}.'.html';
                     if ($manifestok) {                      if ($manifestok) {
                         if (($depth[$alldiscussion{$_}] <= $currdepth) && ($alldiscussion{$_} != $firstidx)) {                          if (($depth[$alldiscussion{$post}] <= $currdepth) && ($alldiscussion{$post} != $firstidx)) {
                             print $manifestfile '  </item>'."\n";                              print $manifestfile '  </item>'."\n";
                         }                          }
                         $currdepth = $depth[$alldiscussion{$_}];                          $currdepth = $depth[$alldiscussion{$post}];
                         print $manifestfile "\n".                           print $manifestfile "\n". 
       '<item identifier="ITEM-'.$ressymb.'-'.$alldiscussion{$_}.'" isvisible="'.        '<item identifier="ITEM-'.$ressymb.'-'.$alldiscussion{$post}.'" isvisible="'.
         $imsitems{$alldiscussion{$_}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$_}.'">'.          $imsitems{$alldiscussion{$post}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$post}.'">'.
         '<title>'.$imsitems{$alldiscussion{$_}}{'title'}.'</title>';          '<title>'.$imsitems{$alldiscussion{$post}}{'title'}.'</title></item>';
                         $imsresources .= "\n".                          $imsresources .= "\n".
     '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$_}.'" type="webcontent" href="'.$postfilename.'">'."\n".      '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$post}.'" type="webcontent" href="'.$postfilename.'">'."\n".
       '<file href="'.$postfilename.'">'."\n".        '<file href="'.$postfilename.'">'."\n".
       $imsfiles{$alldiscussion{$_}}{$imsitems{$alldiscussion{$_}}{'currversion'}}."\n".        $imsfiles{$alldiscussion{$post}}{$imsitems{$alldiscussion{$post}}{'currversion'}}.'</file>'."\n".
     '</resource>';      '</resource>';
                     }                      }
                     my $postingfile;                      my $postingfile;
                     my $postingfilename = $tempexport.'/'.$postfilename;                      my $postingfilename = $tempexport.'/'.$postfilename;
                     if ($postingfile = Apache::File->new('>'.$postingfilename)) {                      if ($postingfile = Apache::File->new('>'.$postingfilename)) {
                         print $postingfile '<html><head><title>Discussion Post</title></head><body>'.                          print $postingfile '<html><head><title>Discussion Post</title></head><body>'.
                                            $imsitems{$alldiscussion{$_}}{'title'}.' '.                                             $imsitems{$alldiscussion{$post}}{'title'}.' '.
                                            $imsitems{$alldiscussion{$_}}{'sender'}.                                             $imsitems{$alldiscussion{$post}}{'sender'}.
                                            $imsitems{$alldiscussion{$_}}{'timestamp'}.'<br /><br />'.                                             $imsitems{$alldiscussion{$post}}{'timestamp'}.'<br /><br />'.
                                            $imsitems{$alldiscussion{$_}}{'message'}.'<br />'.                                             $imsitems{$alldiscussion{$post}}{'message'}.'<br />'.
                                            $imsitems{$alldiscussion{$_}}{'attach'}.'</body></html>'."\n";                                              $imsitems{$alldiscussion{$post}}{'attach'}.'</body></html>'."\n"; 
                         close($postingfile);                          close($postingfile);
                     } else {                      } else {
                         $discussion .= 'An error occurred opening the export file for posting '.$alldiscussion{$_}.'<br />';                          $discussion .= $lt{'aerr'}.' '.$alldiscussion{$post}.'<br />';
                     }                      }
                     $copyresult.=&replicate_attachments($imsitems{$alldiscussion{$_}}{'allattachments'},$tempexport);                      $copyresult.=&replicate_attachments($imsitems{$alldiscussion{$post}}{'allattachments'},$tempexport);
                 } else {                  } else {
                     $discussion.='<td  bgcolor="'.$bgcols[$newitem{$alldiscussion{$_}}].                      $discussion.='<td class="'.$bgcols[$newitem{$alldiscussion{$post}}].
                        '" colspan="'.$colspan.'">'. $discussionitems[$alldiscussion{$_}].                         '" colspan="'.$colspan.'">'. $discussionitems[$alldiscussion{$post}].
                        '</td></tr>';                         '</td></tr>';
                 }                  }
     }      }
Line 549  imscp_v1p1.xsd http://www.imsglobal.org/ Line 560  imscp_v1p1.xsd http://www.imsglobal.org/
  unless ($outputtarget eq 'tex' || $outputtarget eq 'export') {   unless ($outputtarget eq 'tex' || $outputtarget eq 'export') {
             my $colspan=$maxdepth+1;              my $colspan=$maxdepth+1;
             $discussion .= <<END;              $discussion .= <<END;
             <tr bgcolor="#FFFFFF">              <tr>
              <td colspan="$colspan" valign="top">               <td colspan="$colspan">
               <table border="0" bgcolor="#FFFFFF" width="100%" cellspacing="2" cellpadding="2">                <table width="100%">
                <tr>                 <tr>
                 <td align="left">                  <td class="LC_disc_action_left">
                  <table border="0" cellpadding="0" cellspacing="4">                      <font size="-1"><b>$lt{'cuse'}</b>:&nbsp;
                   <tr>  
                    <td>  
                     <font size="-1"><b>$lt{'cuse'}</b>:</td>  
                    <td>&nbsp;</td>  
                    <td><font size="-1">  
 END  END
             if ($newpostsflag) {              if ($newpostsflag) {
                 $discussion .=                   $discussion .= 
Line 576  END Line 582  END
                 }                  }
             }              }
             $discussion .= <<END;              $discussion .= <<END;
                    </font></td>                     &nbsp;&nbsp;<b><a href="$chglink">$lt{'chgt'}</a></b></font>
                    <td>&nbsp;</td>  
                    <td align="left">  
                     <font size="-1"><b><a href="$chglink">$lt{'chgt'}</a>?</font></b>  
                    </td>  
                   </tr>  
                  </table>  
                 </td>                  </td>
 END  END
             if ($sortposts) {              if ($sortposts) {
                 my %sort_types = ();                  my %sort_types = ();
                 my %role_types = ();                  my %role_types = ();
                 my %status_types = ();                  my %status_types = ();
                 &sort_filter_names(\%sort_types,\%role_types,\%status_types);                  &sort_filter_names(\%sort_types,\%role_types,\%status_types,$crstype);
   
                 $discussion .= '<td><font size="-1"><b>'.&mt('Sorted by').'</b>: '.$sort_types{$sortposts}.'<br />';                  $discussion .= '<td class="LC_disc_action_right"><font size="-1"><b>'.&mt('Sorted by').'</b>: '.$sort_types{$sortposts}.'<br />';
                 if (defined($env{'form.totposters'})) {                  if (defined($env{'form.totposters'})) {
                     $discussion .= &mt('Posts by').':';                      $discussion .= &mt('Posts by').':';
                     if ($totposters > 0) {                      if ($totposters > 0) {
                         foreach my $poster (@posters) {                          foreach my $poster (@posters) {
                             $poster =~ s/:/\@/;  
                             $discussion .= ' '.$poster.',';                              $discussion .= ' '.$poster.',';
                         }                          }
                         $discussion =~ s/,$//;                          $discussion =~ s/,$//;
Line 609  END Line 608  END
                         $filterchoice = '<i>'.&mt('sections').'</i>-&nbsp;'.$env{'form.sectionpick'};                          $filterchoice = '<i>'.&mt('sections').'</i>-&nbsp;'.$env{'form.sectionpick'};
                         $filterchoice .= '&nbsp;&nbsp;&nbsp; ';                          $filterchoice .= '&nbsp;&nbsp;&nbsp; ';
                     }                      }
                       if (@grouppick > 0) {
                           $filterchoice = '<i>'.&mt('groups').'</i>-&nbsp;'.$env{'form.grouppick'};
                           $filterchoice .= '&nbsp;&nbsp;&nbsp; ';
                       }
                     if (@rolefilter > 0) {                      if (@rolefilter > 0) {
                         $filterchoice .= '<i>'.&mt('roles').'</i>-';                          $filterchoice .= '<i>'.&mt('roles').'</i>-';
                         foreach (@rolefilter) {                          foreach my $role (@rolefilter) {
                             $filterchoice .= '&nbsp;'.$role_types{$_}.',';                              $filterchoice .= '&nbsp;'.$role_types{$role}.',';
                         }                          }
                         $filterchoice =~ s/,$//;                          $filterchoice =~ s/,$//;
                         $filterchoice .= '<br />&nbsp;&nbsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp&nbsp;';                          $filterchoice .= '<br />'.('&nbsp;' x8);
                     }                      }
                     if ($statusfilter) {                      if ($statusfilter) {
                         $filterchoice .= '<i>'.&mt('status').'</i>-&nbsp;'.$status_types{$statusfilter};                          $filterchoice .= '<i>'.&mt('status').'</i>-&nbsp;'.$status_types{$statusfilter};
Line 623  END Line 626  END
                     if ($filterchoice) {                      if ($filterchoice) {
                         $discussion .= '<b>'.&mt('Filters').'</b>:&nbsp;'.$filterchoice;                          $discussion .= '<b>'.&mt('Filters').'</b>:&nbsp;'.$filterchoice;
                     }                      }
                     $discussion .= '</font></td>';  
                 }                  }
                   $discussion .= '</font></td>';
   
             }              }
             if ($dischash{$toggkey}) {              if ($dischash{$toggkey}) {
                 my $storebutton = &mt('Store read/unread changes');                  my $storebutton = &mt('Save read/unread changes');
                 $discussion.='<td align="right">'.                  $discussion.='<td align="right">'.
               '<input type="hidden" name="discsymb" value="'.$ressymb.'">'."\n".                '<input type="hidden" name="discsymb" value="'.$ressymb.'" />'."\n".
               '<input type="button" name="readoptions" value="'.$storebutton.'"'.                '<input type="button" name="readoptions" value="'.$storebutton.'"'.
               ' onClick="this.form.submit();">'."\n".                ' onclick="this.form.submit();" />'."\n".
               '</td>';                '</td>';
             }              }
             $discussion .= (<<END);              $discussion .= (<<END);
Line 639  END Line 643  END
               </table>                </table>
              </td>               </td>
             </tr>              </tr>
            </table>  
            <br /><br /></form>  
 END  END
               $discussion .= &action_links_bar($colspan,$ressymb,$visible,
                                                $newpostsflag,$group,
                                                $prevread,$markondisp);
               $discussion .= "</table></form>\n";
         }           } 
         if ($outputtarget eq 'export') {          if ($outputtarget eq 'export') {
             if ($manifestok) {              if ($manifestok) {
Line 673  END Line 679  END
                     open(OUTPUT, "zip -r $imszip *  2> /dev/null |");                      open(OUTPUT, "zip -r $imszip *  2> /dev/null |");
                     close(OUTPUT);                      close(OUTPUT);
                     chdir $cwd;                      chdir $cwd;
                     $discussion .= 'Download the zip file from <a href="'.$imszipfile.'">Discussion Posting Archive</a><br />';                      $discussion .= &mt('Download the zip file from [_1]Discussion Posting Archive','<a href="'.$imszipfile.'">').'</a><br />';
                     if ($copyresult) {                      if ($copyresult) {
                         $discussion .= 'The following errors occurred during export - <br />'.$copyresult;                          $discussion .= &mt('The following errors occurred during export').' - <br />'.$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 />'.&mt('Unfortunately you will not be able to retrieve an archive of the discussion posts at this time, because there was a problem creating a manifest file.').'<br />';
             }              }
             return $discussion;              return $discussion;
         }          }
Line 687  END Line 693  END
     if ($discussiononly) {      if ($discussiononly) {
         my $now = time;          my $now = time;
         my $attachnum = 0;          my $attachnum = 0;
         my $newattachmsg = '';          my $currnewattach = [];
         my @currnewattach = ();          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 = &Apache::lonnet::unescape($env{'form.subject'});              $subject = &unescape($env{'form.subject'});
             $comment = &Apache::lonnet::unescape($env{'form.comment'});              $comment = &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};
             }              }
         }          }
  if (&discussion_open($status)) {   if ((&discussion_open($status)) && ($outputtarget ne 'tex')) {
     $discussion.=(<<ENDDISCUSS);              if (($group ne '') && ($mode eq 'board')) {  
 <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data">                  if ((&check_group_priv($group,'pgd') eq 'ok') && 
 <input type="submit" name="discuss" value="Post Discussion" />                     ($ressymb =~ m{^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$})) {
 <input type="submit" name="anondiscuss" value="Post Anonymous Discussion" />                      $discussion .=
 <input type="hidden" name="symb" value="$ressymb" />   &postingform_display($mode,$ressymb,$now,$subject,
 <input type="hidden" name="sendit" value="true" />       $comment,$outputtarget,$attachnum,
 <input type="hidden" name="timestamp" value="$now" />       $currnewattach,$currdelold,
 <br /><a name="newpost"></a>       $group,$crstype);
 <font size="1">Note: in anonymous discussion, your name is visible only   
 to course faculty</font><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>  
 ENDDISCUSS  
             if ($env{'form.origpage'}) {  
                 $discussion.='<input type="hidden" name="origpage" value="'.$env{'form.origpage'}.'" />'."\n";  
                 foreach (@currnewattach) {  
                     $discussion.='<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";  
                 }  
             }  
             $discussion.="</form>\n";  
             if ($outputtarget ne 'tex') {  
                 $discussion.=&generate_attachments_button('',$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,'',$mode);  
                 if (@currnewattach > 0) {  
                     $newattachmsg .= '<b>New attachments</b><br />';  
                     if (@currnewattach > 1) {  
                         $newattachmsg .= '<ol>';  
                         foreach my $item (@currnewattach) {  
                             $item =~ m#.*/([^/]+)$#;  
                             $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";  
                     }  
                 }                  }
                 $discussion.=$newattachmsg;              } else {
         $discussion.=&generate_preview_button();                  if (&Apache::lonnet::allowed('pch',$env{'request.course.id'}.
     }                      ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
   
               $discussion.= 
           &postingform_display($mode,$ressymb,$now,$subject,
        $comment,$outputtarget,$attachnum,
        $currnewattach,$currdelold,'',$crstype);
                   } else {
                       $discussion.= '<span class="LC_feedback_link">'.
                                     &mt('This discussion is closed.').'</span>';
                   }
               }
  }   }
     } else {          if (!(&discussion_open($status)) && ($outputtarget ne 'tex')) {
               $discussion.= '<span class="LC_feedback_link">'.
                             &mt('This discussion is closed.').'</span>';
           }
       } elsif ($outputtarget ne 'tex') {
           $discussion.='<div class="LC_feedback_link">';
         if (&discussion_open($status) &&          if (&discussion_open($status) &&
             &Apache::lonnet::allowed('pch',              &Apache::lonnet::allowed('pch',
            $env{'request.course.id'}.             $env{'request.course.id'}.
         ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {          ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
     if ($outputtarget ne 'tex') {              $discussion.= &send_feedback_link($ressymb);
  $discussion.='<table bgcolor="#BBBBBB"><tr><td><a href="/adm/feedback?replydisc='.              if ($env{'request.role.adv'}) {
     &Apache::lonnet::escape($ressymb).':::" '.$target.'>'.                  my $close = &Apache::lonnet::EXT('resource.0.discussend',$ressymb);
     '<img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" border="0" />'.                  if (defined($close) && $close ne '' && $close < time) {
     &mt('Post Discussion').'</a></td></tr></table>';                      $discussion .= '&nbsp;'.&mt('(Closed for [_1] roles)',
     }                                                  &Apache::lonnet::plaintext('st',$crstype));
  }                  }
               }
    } else {
               $discussion.= '<span class="LC_feedback_link">'.&mt('This discussion is closed.').'</span>';
           }
    $discussion.= &send_message_link($ressymb).'</div>';
     }      }
     return $discussion;      return $discussion;
 }  }
   
   
   sub discussion_link {
      my ($ressymb,$linktext,$cmd,$item,$flag,$prev,$adds,$title)=@_;
      my $link='/adm/feedback?inhibitmenu=yes&modal=yes&'.$cmd.'='.&escape($ressymb).':::'.$item;
      if ($flag) { $link .= '&amp;previous='.$prev; }
      if ($adds) { $link .= $adds; }
      my $width=600;
      my $height=600;
      if (($cmd eq 'hide') || ($cmd eq 'unhide') || ($cmd eq 'like') || ($cmd eq 'unlike')) {
          $width=300;
          $height=200;
      }
      return &Apache::loncommon::modal_link($link,$linktext,$width,$height,undef,undef,$title);
   }
   
   
   sub send_feedback_link {
       my ($ressymb) = @_;
       return '<span class="LC_feedback_link">'.
                    &discussion_link($ressymb,
                       '<img alt="" class="LC_noBorder" src="'.
                       &Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').
                       '" border="0" /><span class="LC_menubuttons_inline_text">'.&mt('Post Discussion').'</span>',
                       'replydisc').
              '</span>';
   }
   
   sub send_message_link {
       my ($ressymb) = @_;
       my $output = '<span class="LC_message_link">'.
                    &discussion_link($ressymb,
                       '<img alt="" class="LC_noBorder" src="'.
                       &Apache::loncommon::lonhttpdurl('/res/adm/pages/feedback.png').
                       '" border="0" /><span class="LC_menubuttons_inline_text">'.&mt('Send Feedback').'</span>',
                       'sendmessageonly').
                    '</span>';
       return $output;
   }
   
   sub action_links_bar {
       my ($colspan,$ressymb,$visible,$newpostsflag,$group,$prevread,$markondisp) = @_;
       my $discussion = '<tr><td colspan="'.$colspan.'">'.
                        '<table width="100%"><tr>'.
                        '<td class="LC_disc_action_left">';
       my $escsymb=&escape($ressymb);
       if ($visible) {
           $discussion .= '<a href="/adm/feedback?cmd=threadedon&amp;symb='.$escsymb;
           if ($newpostsflag) {
               $discussion .= '&amp;previous='.$prevread;
           }
           $discussion .= &group_args($group);
           $discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.
                         '<a href="/adm/feedback?cmd=threadedoff&amp;symb='.$escsymb;
           if ($newpostsflag) {
               $discussion .= '&amp;previous='.$prevread;
           }
           $discussion .= &group_args($group);
           $discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;';
   
           my $otherviewurl='/adm/feedback?cmd=sortfilter&amp;symb='.$escsymb.'&amp;inhibitmenu=yes&amp;modal=yes';
           if ($newpostsflag) {
               $otherviewurl .= '&amp;previous='.$prevread;
           }
           $otherviewurl .= &group_args($group);
           $discussion .= &Apache::loncommon::modal_link($otherviewurl,&mt('Other Views ...'),800,340);
           $discussion .= '<br />';
       }
       $discussion .='<a href="/adm/feedback?export='.$escsymb;
       if ($newpostsflag) {
           $discussion .= '&amp;previous='.$prevread;
       }
       $discussion .= &group_args($group);
       $discussion .= '">'.&mt('Export').'</a>';
       if (&Apache::lonnet::allowed('rin',$env{'request.course.id'})) {
           $discussion .= '&nbsp;&nbsp;';
           $discussion .='<a href="/adm/feedback?undeleteall='.$escsymb;
           if ($newpostsflag) {
               $discussion .= '&amp;previous='.$prevread;
           }
           $discussion .= &group_args($group);
           $discussion .= '">'.&mt('Undelete all deleted entries').'</a>';
       }
       $discussion.='</td>';
       if ($newpostsflag) {
           if (!$markondisp) {
               $discussion .='<td class="LC_disc_action_right"><a href="/adm/preferences?action=changediscussions';
               $discussion .= &group_args($group);
               $discussion .= '">'.
                              &mt('My general preferences on what is marked as NEW').
                              '</a><br /><a href="/adm/feedback?markread=1&amp;symb='.$escsymb;
               $discussion .= &group_args($group);
               $discussion .= '">'.&mt('Mark NEW posts no longer new').'</a></td>';
           } else {
               $discussion .= '<td>&nbsp;</td>';
           }
       } else {
           $discussion .= '<td>&nbsp;</td>';
       }
       $discussion .= '</tr></table></td></tr>';
       return $discussion;
   }
   
   sub postingform_display {
       my ($mode,$ressymb,$now,$subject,$comment,$outputtarget,$attachnum,
           $currnewattach,$currdelold,$group,$crstype) = @_;
       my $newattachmsg;
       my %lt = &Apache::lonlocal::texthash(
                 'note' => 'Note: in anonymous discussion, your name is visible only to course faculty',
                'title' => 'Title',
                'podi' => 'Post Discussion',
                'poan' => 'Post Anonymous Discussion',
                'newa' => 'New attachments',
       );
       if ($crstype eq 'Community') {
           $lt{'note'} = &mt('Note: in anonymous discussion, your name is visible only to community facilitators');
       }
       my ($postingform,$textareaclass);
       if (&Apache::lonhtmlcommon::htmlareabrowser()) {
           $postingform = &Apache::lonhtmlcommon::htmlareaselectactive();
           $textareaclass = 'class="LC_richDefaultOff"';
           if ($env{'request.course.id'}) {
               unless (($env{'course.'.$env{'request.course.id'}.'.allow_limited_html_in_feedback'} =~ /^\s*yes\s*$/i) || ($env{'form.sendmessageonly'})) {
                   undef($textareaclass);
               }
           }
       }
       $postingform .= (<<ENDDISCUSS);
   <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data"> <input type="submit" name="discuss" value="$lt{'podi'}" />
   <input type="submit" name="anondiscuss" value="$lt{'poan'}" /> <input type="hidden" name="symb" value="$ressymb" />
   <input type="hidden" name="sendit" value="true" />
   <input type="hidden" name="timestamp" value="$now" />
   <a name="newpost"></a>
   <font size="1">$lt{'note'}</font><br />
   <b>$lt{'title'}:</b>&nbsp;<input type="text" name="subject" value="$subject" size="30" /><br />
   <textarea name="comment" cols="80" rows="14" id="comment" $textareaclass>$comment</textarea>
   ENDDISCUSS
       if ($env{'form.origpage'}) {
           $postingform .= '<input type="hidden" name="origpage" value="'.
                           $env{'form.origpage'}.'" />'."\n";
           foreach my $att (@{$currnewattach}) {
               $postingform .= '<input type="hidden" name="currnewattach" '.
                               'value="'.$att.'" />'."\n";
           }
       }
       if (exists($env{'form.ref'})) {
           $postingform .= '<input type="hidden" name="ref" value="'.
                           $env{'form.ref'}.'" />';
       }
       if ($group ne '') {
           $postingform .='<input type="hidden" name="group" value="'.$group.'" />';
       }
       my $blockblog = &Apache::loncommon::blocking_status('blogs');
       if (!$blockblog) {
           $postingform .= &add_blog_checkbox($crstype);
       }
       $postingform .= "</form>\n";
       $postingform .= &generate_attachments_button('',$attachnum,$ressymb,
                                                        $now,$currnewattach,
                                                        $currdelold,'',$mode,
                                                        $blockblog);
       if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) {
           $newattachmsg = '<br /><b>'.$lt{'newa'}.'</b><br />';
           if (@{$currnewattach} > 1) {
                $newattachmsg .= '<ol>';
                foreach my $item (@{$currnewattach}) {
                   $item =~ m#.*/([^/]+)$#;
                   $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";
            }
       }
       $postingform .= $newattachmsg;
       $postingform .= &generate_preview_button();
       return $postingform;
   }
   
 sub build_posting_display {  sub build_posting_display {
     my ($usernamesort,$subjectsort,$namesort,$notshown,$newitem,$dischash,$shown,$alldiscussion,$imsitems,$imsfiles,$roleinfo,$discussionitems,$replies,$depth,$posters,$maxdepth,$visible,$newpostsflag,$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$ressymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$statusfilter,$toggkey,$outputtarget,$anonhash,$anoncnt) = @_;      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,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,$anonhash,$anoncnt,$group) = @_;
     my @original=();      my @original=();
     my @index=();      my @index=();
       my $skip_group_check = 0;
     my $symb=&Apache::lonenc::check_decrypt($ressymb);      my $symb=&Apache::lonenc::check_decrypt($ressymb);
     my $escsymb=&Apache::lonnet::escape($ressymb);      my $escsymb=&escape($ressymb);
   # These are the discussion contributions
     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},      my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
   $env{'course.'.$env{'request.course.id'}.'.domain'},    $env{'course.'.$env{'request.course.id'}.'.domain'},
   $env{'course.'.$env{'request.course.id'}.'.num'});    $env{'course.'.$env{'request.course.id'}.'.num'});
   # And these are the likes/unlikes
       my %likes=&Apache::lonnet::dump('disclikes',
                             $env{'course.'.$env{'request.course.id'}.'.domain'},
                             $env{'course.'.$env{'request.course.id'}.'.num'},
                             '^'.$symb.':');
       my $thisuser=$env{'user.name'}.':'.$env{'user.domain'};
   # Array with likes to figure out averages, etc.
       my @theselikes=();
   # Is the user allowed to see the real name behind anonymous postings?
       my $see_anonymous = 
    &Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
   
       if ((@{$grouppick} == 0) || (grep(/^all$/,@{$grouppick}))) {
           $skip_group_check = 1;
       }
   # Deletions and hiddens are just lists. Split them up into a hash for quicker lookup
       my (%deletions,%hiddens);
       if ($contrib{'deleted'}) {
          my $deleted = $contrib{'deleted'};
          $deleted =~ s/^\.//;
          $deleted =~ s/\.$//;
          %deletions = map { $_ => 1 } (split(/\.\./,$deleted));
       }
       if ($contrib{'hidden'}) {
          my $hidden = $contrib{'hidden'};
          $hidden =~ s/^\.//;
          $hidden =~ s/\.$//;
          %hiddens = map { $_ => 1 } (split(/\.\./,$hidden));
       }
   # Versions if store/restore are used to actually store the messages. 
     if ($contrib{'version'}) {      if ($contrib{'version'}) {
         my $oldest = $contrib{'1:timestamp'};          my $oldest = $contrib{'1:timestamp'};
         if ($prevread eq '0') {          if ($prevread eq '0') {
Line 776  sub build_posting_display { Line 984  sub build_posting_display {
         }          }
         my ($skiptest,$rolematch,$roleregexp,$secregexp,$statusregexp);          my ($skiptest,$rolematch,$roleregexp,$secregexp,$statusregexp);
         if ($sortposts) {          if ($sortposts) {
             ($skiptest,$roleregexp,$secregexp,$statusregexp) = &filter_regexp($rolefilter,$sectionpick,$statusfilter);              ($skiptest,$roleregexp,$secregexp,$statusregexp) = 
                        &filter_regexp($rolefilter,$sectionpick,$statusfilter);
             $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;              $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;
         }           }
   # We need to go through this twice, first to get the likes/dislikes, then to actually build the display
           for (my $id=1;$id<=$contrib{'version'};$id++) {
               my $idx=$id;
               next if ($contrib{$idx.':deleted'});
               next if ($contrib{$idx.':hidden'});
               unless ((($hiddens{$idx}) && (!$seeid)) || ($deletions{$idx}) || (!$contrib{$idx.':message'})) {
                   push(@theselikes,$likes{$symb.':'.$idx.':likes'});
               }
           }
   # Figure out average likes and standard deviation if there are enough discussions to warrant that
           my $ave=0;
           my $stddev=10000;
           if ($#theselikes>1) {
               my $sum=0;
               my $num=$#theselikes+1;
               foreach my $thislike (@theselikes) {
                   $sum+=$thislike;
               }
               $ave=$sum/$num;
               my $sumsq=0;
               foreach my $thislike (@theselikes) {
                   $sumsq+=($thislike-$ave)*($thislike-$ave);
               }
               $stddev=sqrt($sumsq/$num);
           }
   # Now we know the average likes $ave and the standard deviation $stddev
   # Get the boundaries for markup
           my $oneplus=$ave+$stddev;
           my $twoplus=$ave+2.*$stddev;
           my $oneminus=$ave-$stddev;
           my $twominus=$ave-2.*$stddev;
   #            &Apache::lonnet::logthis(join(',',@theselikes)." Ave $ave StdDev $stddev $twominus $oneminus $oneplus $twoplus");
   #
   # This is now the real loop. Go through all entries, pick up what we need
   # 
  for (my $id=1;$id<=$contrib{'version'};$id++) {   for (my $id=1;$id<=$contrib{'version'};$id++) {
     my $idx=$id;      my $idx=$id;
               next if ($contrib{$idx.':deleted'});
               next if ($contrib{$idx.':hidden'});
   # If we get here, we are actually going to display the message - we don't know where and we don't know if we display
   # previous edits, but it counts as one entry
             my $posttime = $contrib{$idx.':timestamp'};              my $posttime = $contrib{$idx.':timestamp'};
             if ($prevread <= $posttime) {              if ($prevread <= $posttime) {
                 $$newpostsflag = 1;                  $$newpostsflag = 1;
             }              }
     my $hidden=($contrib{'hidden'}=~/\.$idx\./);  
             my $studenthidden=($contrib{'studenthidden'}=~/\.$idx\./);              my $studenthidden=($contrib{'studenthidden'}=~/\.$idx\./);
     my $deleted=($contrib{'deleted'}=~/\.$idx\./);  
     my $origindex='0.';      my $origindex='0.';
             my $numoldver=0;              my $numoldver=0;
     if ($contrib{$idx.':replyto'}) {      if ($contrib{$idx.':replyto'}) {
Line 811  sub build_posting_display { Line 1057  sub build_posting_display {
     } else {      } else {
  $$replies[$$depth[$idx]]=1;   $$replies[$$depth[$idx]]=1;
     }      }
     unless ((($hidden) && (!$seeid)) || ($deleted)) {              unless ((($hiddens{$idx}) && (!$seeid)) || ($deletions{$idx})) {
  $$visible++;   $$visible++;
                 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'});
                         $numoldver = @oldversions;                          $numoldver = @oldversions;
                     } else {                      } else {
                         $numoldver = 1;                          $numoldver = 1;
Line 845  sub build_posting_display { Line 1091  sub build_posting_display {
                     $message.=$attachtxt{$numoldver};                      $message.=$attachtxt{$numoldver};
                     $subject=$subjects{$numoldver};                      $subject=$subjects{$numoldver};
                     if ($message) {                      if ($message) {
           if ($hidden) {            if ($hiddens{$idx}) {
     $message='<font color="#888888">'.$message.'</font>';      $message='<font color="#888888">'.$message.'</font>';
                             if ($studenthidden) {                              if ($studenthidden) {
                                 $message .='<br /><br />Deleted by poster (student).';                                  $message .='<br /><br />Deleted by poster (student).';
Line 854  sub build_posting_display { Line 1100  sub build_posting_display {
   
                         if ($subject eq '') {                          if ($subject eq '') {
                            if (defined($$subjectsort{'__No subject'})) {                             if (defined($$subjectsort{'__No subject'})) {
                                push @{$$subjectsort{'__No subject'}}, $idx;                                 push(@{$$subjectsort{'__No subject'}}, $idx);
                            } else {                             } else {
                                @{$$subjectsort{'__No subject'}} = ("$idx");                                 @{$$subjectsort{'__No subject'}} = ("$idx");
                            }                             }
                         } else {                          } else {
                             if (defined($$subjectsort{$subject})) {                              if (defined($$subjectsort{$subject})) {
                                push @{$$subjectsort{$subject}}, $idx;                                 push(@{$$subjectsort{$subject}}, $idx);
                             } else {                              } else {
                                @{$$subjectsort{$subject}} = ("$idx");                                 @{$$subjectsort{$subject}} = ("$idx");
                             }                              }
                         }                          }
         if ((!$contrib{$idx.':anonymous'}) || ($seeid)) {          if (!$contrib{$idx.':anonymous'} || $see_anonymous) {
     $sender=&Apache::loncommon::aboutmewrapper(      $sender=&Apache::loncommon::aboutmewrapper(
  $plainname,   $plainname,
  $contrib{$idx.':sendername'},   $contrib{$idx.':sendername'},
  $contrib{$idx.':senderdomain'}).' ('.   $contrib{$idx.':senderdomain'}).' ('.
  $contrib{$idx.':sendername'}.' at '.   $contrib{$idx.':sendername'}.':'.
  $contrib{$idx.':senderdomain'}.')';   $contrib{$idx.':senderdomain'}.')';
                               $sender = '<b>'.$sender.'</b>';
     if ($contrib{$idx.':anonymous'}) {      if ($contrib{$idx.':anonymous'}) {
         $sender.=' <font color="red"><b>['.$$anonhash{$key}.']</b></font> '.          $sender.=' <font color="red"><b>['.$$anonhash{$key}.']</b></font> '.
     $screenname;      $screenname;
     }      }
       if ($see_anonymous) {
    $sender.=&Apache::loncommon::student_image_tag($contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
       }
 # Set up for sorting by domain, then username  # Set up for sorting by domain, then username
                             unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) {                              unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) {
                                 %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = ();                                  %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = ();
                             }                              }
                             if (defined($$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}})) {                              if (defined($$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}})) {
                                 push @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx;                                  push(@{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx);
                             } else {                              } else {
                                 @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}} = ("$idx");                                  @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}} = ("$idx");
                             }                              }
Line 902  sub build_posting_display { Line 1151  sub build_posting_display {
                                 %{$$namesort{$lastname}} = ();                                  %{$$namesort{$lastname}} = ();
                             }                              }
                             if (defined($$namesort{$lastname}{$firstname})) {                              if (defined($$namesort{$lastname}{$firstname})) {
                                 push @{$$namesort{$lastname}{$firstname}}, $idx;                                  push(@{$$namesort{$lastname}{$firstname}}, $idx);
                             } else {                              } else {
                                 @{$$namesort{$lastname}{$firstname}} = ("$idx");                                  @{$$namesort{$lastname}{$firstname}} = ("$idx");
                             }                              }
                             if (&editing_allowed()) {                              if ($outputtarget ne 'tex') {
                                 if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) {                                  unless ($likes{$symb.':'.$idx.':likers'}=~/\,\Q$thisuser\E\,/) {
                                     $sender.=' <a href="/adm/feedback?editdisc='.                                      $sender.='&nbsp;'.&discussion_link($symb,'<img border="0" src="/res/adm/pages/thumbsup.png" alt="'.&mt('Like').'" />','like',$idx,$$newpostsflag,$prevread,&group_args($group),&mt("Like this posting"));
                                          $escsymb.':::'.$idx;  
                                     if ($$newpostsflag) {  
                                         $sender .= '&previous='.$prevread;  
                                     }  
                                     $sender .= '" '.$target.'>'.&mt('Edit').'</a>';                                               
                                     unless ($seeid) {  
                                         $sender.=" <a href=\"javascript:studentdelete('$escsymb','$idx','$$newpostsflag','$prevread')";  
                                         $sender .= '">'.&mt('Delete').'</a>';  
                                     }  
                                 }                                  }
                             }                                   unless ($likes{$symb.':'.$idx.':unlikers'}=~/\,\Q$thisuser\E\,/) {
     if ($seeid) {                                      $sender.='&nbsp;'.&discussion_link($symb,'<img border="0" src="/res/adm/pages/thumbsdown.png" alt="'.&mt('Unlike').'" />',,'unlike',$idx,$$newpostsflag,$prevread,&group_args($group),&mt("Unlike this posting"));
         if ($hidden) {                                  }
                                     unless ($studenthidden) {                                  my $thislikes=$likes{$symb.':'.$idx.':likes'};
                 $sender.=' <a href="/adm/feedback?unhide='.                                  if ($thislikes>0) { 
                 $escsymb.':::'.$idx;                                      $sender.='&nbsp;('.&mt("[_1] likes",$thislikes).')';
                                         if ($$newpostsflag) {                                  } elsif ($thislikes<0) {
                                             $sender .= '&previous='.$prevread;                                      $sender.='&nbsp;('.&mt("[_1] unlikes",abs($thislikes)).')';
                                   }
                                   if (&editing_allowed($escsymb.':::'.$idx,$group)) {
                                       if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) {
                                           $sender.=' '.
                                            &discussion_link($symb,&mt('Edit'),'editdisc',$idx,$$newpostsflag,$prevread,&group_args($group));
                                           unless ($seeid) {
                                               my $grpargs = &group_args($group);
                                               $sender.=" <a href=\"javascript:verifydelete('studentdelete','$escsymb','$idx','$$newpostsflag','$prevread','$grpargs')";
                                               $sender .= '">'.&mt('Delete').'</a>';
                                         }                                          }
                                         $sender .= '">'.&mt('Make Visible').'</a>';  
                                     }                                      }
         } else {  
     $sender.=' <a href="/adm/feedback?hide='.  
         $escsymb.':::'.$idx;  
                                     if ($$newpostsflag) {  
                                         $sender .= '&previous='.$prevread;  
                                     }  
                                     $sender .= '">'.&mt('Hide').'</a>';  
         }                       
         $sender.=' <a href="/adm/feedback?deldisc='.  
         $escsymb.':::'.$idx;  
                                 if ($$newpostsflag) {  
                                     $sender .= '&previous='.$prevread;  
                                 }                                  }
                                 $sender .= '">'.&mt('Delete').'</a>';          if ($seeid) {
               if ($hiddens{$idx}) {
                                           unless ($studenthidden) {
                               $sender.=' '.
                                               &discussion_link($symb,&mt('Make Visible'),'unhide',$idx,$$newpostsflag,$prevread,&group_args($group));
                                           }
               } else {
                                           $sender.=' '.
                                            &discussion_link($symb,&mt('Hide'),'hide',$idx,$$newpostsflag,$prevread,&group_args($group));
               }
                                       my $grpargs = &group_args($group);
               $sender.= 
                                           " <a href=\"javascript:verifydelete('seeiddelete','$escsymb','$idx','$$newpostsflag','$prevread','$grpargs')\">";
                                       $sender .= &mt('Delete').'</a>';
                                   }
                             }                              }
         } else {                          } else {
     if ($screenname) {      if ($screenname) {
         $sender='<i>'.$screenname.'</i>';          $sender='<i>'.$screenname.'</i>';
     } else {      } else {
  $sender='<i>'.$$anonhash{$key}.'</i>';   $sender='<i>'.$$anonhash{$key}.'</i>';
     }      }
                               $sender = '<b>'.$sender.'</b>';
 # Set up for sorting by domain, then username for anonymous  # Set up for sorting by domain, then username for anonymous
                             unless (defined($$usernamesort{'__anon'})) {                              unless (defined($$usernamesort{'__anon'})) {
                                 %{$$usernamesort{'__anon'}} = ();                                  %{$$usernamesort{'__anon'}} = ();
                             }                              }
                             if (defined($$usernamesort{'__anon'}{'__anon'})) {                              if (defined($$usernamesort{'__anon'}{'__anon'})) {
                                 push @{$$usernamesort{'__anon'}{'__anon'}}, $idx;                                  push(@{$$usernamesort{'__anon'}{'__anon'}}, $idx);
                             } else {                              } else {
                                 @{$$usernamesort{'__anon'}{'__anon'}} = ("$idx");                                  @{$$usernamesort{'__anon'}{'__anon'}} = ("$idx");
                             }                              }
Line 965  sub build_posting_display { Line 1216  sub build_posting_display {
                                 %{$$namesort{'__anon'}} = ();                                  %{$$namesort{'__anon'}} = ();
                             }                              }
                             if (defined($$namesort{'__anon'}{'__anon'})) {                              if (defined($$namesort{'__anon'}{'__anon'})) {
                                 push @{$$namesort{'__anon'}{'__anon'}}, $idx;                                  push(@{$$namesort{'__anon'}{'__anon'}}, $idx);
                             } else {                              } else {
                                 @{$$namesort{'__anon'}{'__anon'}} = ("$idx");                                  @{$$namesort{'__anon'}{'__anon'}} = ("$idx");
                             }                              }
         }          }
         if (&discussion_open($status) &&                          if ($outputtarget ne 'tex') {
         &Apache::lonnet::allowed('pch',              if (&discussion_open($status)) {
  $env{'request.course.id'}.                                  if (($group ne '') && 
  ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {                                      (&check_group_priv($group,'pgd') eq 'ok')) {
     $sender.=' <a href="/adm/feedback?replydisc='.                                       $sender.=' '.
             $escsymb.':::'.$idx;                                           &discussion_link($symb,&mt('Reply'),'replydisc',$idx,$$newpostsflag,$prevread,&group_args($group));
                             if ($$newpostsflag) {                                  } elsif (&Apache::lonnet::allowed('pch', 
                                 $sender .= '&previous='.$prevread;       $env{'request.course.id'}.
        ($env{'request.course.sec'}?'/'.
                                         $env{'request.course.sec'}:''))) {
                $sender.=' '.
                                            &discussion_link($symb,&mt('Reply'),'replydisc',$idx,$$newpostsflag,$prevread);
                                   }
                               }
               if ($viewgrades) {
           $vgrlink=&Apache::loncommon::submlink(&mt('Submissions'),
                                   $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);
               }
                               if ($$dischash{$readkey}=~/\.$idx\./) { 
                                   $ctlink = '<label><b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" /></label>';
                               } else {
                                   $ctlink = '<label><b>'.&mt('Mark read').'?</b>&nbsp;<input type="checkbox" name="postread_'.$idx.'" /></label>';
                             }                              }
                             $sender .= '" '.$target.'>'.&mt('Reply').'</a>';  
                         }  
         if ($viewgrades) {  
         $vgrlink=&Apache::loncommon::submlink('Submissions',  
                             $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);  
         }  
                         if ($$dischash{$readkey}=~/\.$idx\./) {   
                             $ctlink = '<label><b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" /></label>';  
                         } else {  
                             $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
Line 1005  sub build_posting_display { Line 1260  sub build_posting_display {
                 if ($outputtarget eq 'export') {                  if ($outputtarget eq 'export') {
                     %{$$imsitems{$idx}} = ();                      %{$$imsitems{$idx}} = ();
                     $$imsitems{$idx}{'isvisible'}='true';                      $$imsitems{$idx}{'isvisible'}='true';
                     if ($hidden) {                      if ($hiddens{$idx}) {
                         $$imsitems{$idx}{'isvisible'}='false';                          $$imsitems{$idx}{'isvisible'}='false';
                     }                      }
                     $$imsitems{$idx}{'title'}=$subjects{$numoldver};                      $$imsitems{$idx}{'title'}=$subjects{$numoldver};
Line 1013  sub build_posting_display { Line 1268  sub build_posting_display {
                     $$imsitems{$idx}{'attach'}=$attachtxt{$numoldver};                      $$imsitems{$idx}{'attach'}=$attachtxt{$numoldver};
                     $$imsitems{$idx}{'timestamp'}=$contrib{$idx.':timestamp'};                      $$imsitems{$idx}{'timestamp'}=$contrib{$idx.':timestamp'};
                     $$imsitems{$idx}{'sender'}=$plainname.' ('.                      $$imsitems{$idx}{'sender'}=$plainname.' ('.
                                          $contrib{$idx.':sendername'}.' at '.                                           $contrib{$idx.':sendername'}.':'.
                                          $contrib{$idx.':senderdomain'}.')';                                           $contrib{$idx.':senderdomain'}.')';
                     $$imsitems{$idx}{'isanonymous'}='false';                      $$imsitems{$idx}{'isanonymous'}='false';
                     if ($contrib{$idx.':anonymous'}) {                      if ($contrib{$idx.':anonymous'}) {
Line 1036  sub build_posting_display { Line 1291  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;
                             if (defined($env{'form.totposters'})) {                              if ($env{'form.totposters'} ne '') {
                                 if ($totposters == 0) {                                  if ($totposters == 0) {
                                     $$shown{$idx} = 0;                                      $$shown{$idx} = 0;
                                 } elsif ($totposters > 0) {                                  } elsif ($totposters > 0) {
Line 1061  sub build_posting_display { Line 1316  sub build_posting_display {
                                         }                                          }
                                     }                                      }
                                 }                                  }
                                   if ($$shown{$idx} && !$skip_group_check) {
                                       my $showflag = 0;
                                       if (ref($$classgroups{$poster}{active}) eq 'HASH') {
                                           foreach my $grp (@{$grouppick}) {
                                               if (grep/^\Q$grp\E$/,
                                    keys(%{$$classgroups{$poster}{active}})) {
                                                   $showflag = 1;
                                                   last;
                                               }
                                           }
                                       }
                                       if ($showflag) {
                                           $$shown{$idx} = 1;
                                       } else {
                                           $$shown{$idx} = 0;
                                       }
                                   }
                             } else {                              } else {
                                 $$shown{$idx} = 1;                                  $$shown{$idx} = 1;
                             }                              }
Line 1068  sub build_posting_display { Line 1340  sub build_posting_display {
                         unless ($$notshown{$idx} == 1) {                          unless ($$notshown{$idx} == 1) {
                             if ($prevread > 0 && $prevread <= $posttime) {                              if ($prevread > 0 && $prevread <= $posttime) {
                                 $$newitem{$idx} = 1;                                  $$newitem{$idx} = 1;
                                 $$discussionitems[$idx] .= '                                  $$discussionitems[$idx] .= '<font color="#FF0000"><b>'.&mt('NEW').'&nbsp;&nbsp;</b></font>';
                                  <p><table border="0" width="100%">  
                                   <tr><td align="left"><font color="#FF0000"><b>NEW</b></font></td>';  
                             } else {                              } else {
                                 $$newitem{$idx} = 0;                                  $$newitem{$idx} = 0;
                                 $$discussionitems[$idx] .= '                              }
                                  <p><table border="0" width="100%">                              $$discussionitems[$idx] .= '<b>'.$subject.'</b>&nbsp;&nbsp;'.
                                   <tr><td align="left">&nbsp;</td>';                                  $sender.' '.$vgrlink.' ('.
                             }                                  &Apache::lonlocal::locallocaltime($posttime).')';
                             $$discussionitems[$idx] .= '<td align ="left">&nbsp;&nbsp;'.  
                                 '<b>'.$subject.'</b>&nbsp;&nbsp;'.  
                                 $sender.'</b> '.$vgrlink.' ('.  
                                 &Apache::lonlocal::locallocaltime($posttime).')</td>';  
                             if ($$dischash{$toggkey}) {                              if ($$dischash{$toggkey}) {
                                 $$discussionitems[$idx].='<td align="right">&nbsp;&nbsp;'.                                  $$discussionitems[$idx].='&nbsp;&nbsp;'.$ctlink;
                                   $ctlink.'</td>';                              }
   # Figure out size based on likes
                               my $thislikes=$likes{$symb.':'.$idx.':likes'};
                               my $likesize="100";
                               if ($thislikes>$twoplus) {
                                   $likesize="200";
                               } elsif ($thislikes>$oneplus) {
                                   $likesize="150";
                             }                              }
                             $$discussionitems[$idx].= '</tr></table><blockquote>'.                              if ($thislikes<$twominus) {
                                     $message.'</blockquote></p>';                                  $likesize="50";
                               } elsif ($thislikes<$oneminus) {
                                   $likesize="75";
                               }
                               $$discussionitems[$idx].= '<br /><blockquote>'.
                                       "<div style='font-size:$likesize%'>".
                                       $message.
                                       '</div></blockquote>';
                             if ($contrib{$idx.':history'}) {                              if ($contrib{$idx.':history'}) {
                                 my @postversions = ();                                  my @postversions = ();
                                 $$discussionitems[$idx] .= &mt('This post has been edited by the author.');                                  $$discussionitems[$idx] .= &mt('This post has been edited by the author.');
                                 if ($seeid) {                                  if ($seeid) {
                                     $$discussionitems[$idx] .= '&nbsp;&nbsp;<a href="/adm/feedback?allversions='.$escsymb.':::'.$idx.'">'.&mt('Display all versions').'</a>';                                      $$discussionitems[$idx] .= '&nbsp;&nbsp;'.
                                            &discussion_link($symb,&mt('Display all versions'),'allversions',$idx,$$newpostsflag,$prevread,&group_args($group));
                                 }                                  }
                                 $$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/:/) {
                                     @postversions = split/:/,$contrib{$idx.':history'};                                      @postversions = split(/:/,$contrib{$idx.':history'});
                                 } else {                                  } else {
                                     @postversions = ("$contrib{$idx.':history'}");                                      @postversions = ("$contrib{$idx.':history'}");
                                 }                                  }
Line 1104  sub build_posting_display { Line 1385  sub build_posting_display {
                                     $$discussionitems[$idx] .= '<b>'.$version.'.</b> - '.&Apache::lonlocal::locallocaltime($postversions[$i]).'  ';                                      $$discussionitems[$idx] .= '<b>'.$version.'.</b> - '.&Apache::lonlocal::locallocaltime($postversions[$i]).'  ';
                                 }                                  }
                             }                              }
   # end of unless ($$notshown ...)
                         }                          }
   # end of if ($message) ...
                     }                      }
   # end of the else-branch of target being export
                 }                  }
   # end of unless hidden or deleted
             }              }
   # end of the loop over all discussion entries
  }   }
   # end of "if there actually are any discussions
     }      }
   # end of subroutine "build_posting_display" 
 }  }
   
 sub filter_regexp {  sub filter_regexp {
Line 1118  sub filter_regexp { Line 1406  sub filter_regexp {
     my $skiptest = 1;      my $skiptest = 1;
     if (@{$rolefilter} > 0) {      if (@{$rolefilter} > 0) {
         my @okrolefilter = ();          my @okrolefilter = ();
         foreach (@{$rolefilter}) {          foreach my $role (@{$rolefilter}) {
             unless ($_ eq '') {              unless ($role eq '') {
                 push @okrolefilter, $_;                  push(@okrolefilter, $role);
             }              }
         }          }
         if (@okrolefilter > 0) {          if (@okrolefilter > 0) {
Line 1138  sub filter_regexp { Line 1426  sub filter_regexp {
     }      }
     if (@{$sectionpick} > 0) {      if (@{$sectionpick} > 0) {
         my @oksectionpick = ();          my @oksectionpick = ();
         foreach (@{$sectionpick}) {          foreach my $sec (@{$sectionpick}) {
             unless ($_ eq '') {              unless ($sec eq '') {
                  push @oksectionpick, $_;                   push(@oksectionpick, $sec);
             }              }
         }          }
         if ((@oksectionpick > 0) && (!grep/^all$/,@oksectionpick)) {          if ((@oksectionpick > 0) && (!grep/^all$/,@oksectionpick)) {
Line 1154  sub filter_regexp { Line 1442  sub filter_regexp {
             $secregexp .= '[^:]*';              $secregexp .= '[^:]*';
         }          }
     }      }
   
     if (defined($statusfilter) && $statusfilter ne '') {      if (defined($statusfilter) && $statusfilter ne '') {
         if ($statusfilter eq 'all') {          if ($statusfilter eq 'all') {
             $statusregexp = '[^:]+';              $statusregexp = '[^:]+';
Line 1174  sub get_post_contents { Line 1463  sub get_post_contents {
     %{$$imsfiles{$idx}}=();      %{$$imsfiles{$idx}}=();
     if ($type eq 'allversions') {      if ($type eq 'allversions') {
        unless($seeid) {         unless($seeid) {
            $discussion=&mt('You do not have privileges to view all versions of posts.').&mt('Please select a different role');             $discussion=&mt('You do not have privileges to view all versions of posts.').' '.&mt('Please select a different role.');
            return $discussion;             return $discussion;
        }          } 
     }      }
Line 1190  sub get_post_contents { Line 1479  sub get_post_contents {
                                  $$plainname,                                   $$plainname,
                                  $$contrib{$idx.':sendername'},                                   $$contrib{$idx.':sendername'},
                                  $$contrib{$idx.':senderdomain'}).' ('.                                   $$contrib{$idx.':senderdomain'}).' ('.
                                  $$contrib{$idx.':sendername'}.' at '.                                   $$contrib{$idx.':sendername'}.':'.
                                  $$contrib{$idx.':senderdomain'}.')';                                   $$contrib{$idx.':senderdomain'}.')';
     my $attachmenturls = $$contrib{$idx.':attachmenturl'};      my $attachmenturls = $$contrib{$idx.':attachmenturl'};
     my @postversions = ();      my @postversions = ();
Line 1201  sub get_post_contents { Line 1490  sub get_post_contents {
         }          }
         &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);
         push @postversions,$$contrib{$idx.':timestamp'};          push(@postversions,$$contrib{$idx.':timestamp'});
         $end = @postversions;          $end = @postversions;
     } else {      } else {
         &get_post_versions($messages,$$contrib{$idx.':message'},1,$numver);          &get_post_versions($messages,$$contrib{$idx.':message'},1,$numver);
Line 1218  sub get_post_contents { Line 1507  sub get_post_contents {
         my ($timesent,$attachmsg);          my ($timesent,$attachmsg);
         my %currattach = ();          my %currattach = ();
         $timesent = &Apache::lonlocal::locallocaltime($postversions[$i]);          $timesent = &Apache::lonlocal::locallocaltime($postversions[$i]);
  &newline_to_br(\$messages->{$i});          unless (&contains_block_html($messages->{$i})) {
               &newline_to_br(\$messages->{$i});
           }
         $$messages{$i}=&Apache::lontexconvert::msgtexconverted($$messages{$i});          $$messages{$i}=&Apache::lontexconvert::msgtexconverted($$messages{$i});
         $$subjects{$i}=~s/\n/\<br \/\>/g;          $$subjects{$i}=~s/\n/\<br \/\>/g;
         $$subjects{$i}=&Apache::lontexconvert::msgtexconverted($$subjects{$i});          $$subjects{$i}=&Apache::lontexconvert::msgtexconverted($$subjects{$i});
Line 1228  sub get_post_contents { Line 1519  sub get_post_contents {
         if ($type eq 'export') {          if ($type eq 'export') {
             $$imsfiles{$idx}{$i} = '';              $$imsfiles{$idx}{$i} = '';
             if ($attachmsg) {              if ($attachmsg) {
                 $$attachtxt{$i} = '<br />Attachments:<br />';                  $$attachtxt{$i} = '<br />'.&mt('Attachments').':<br />';
                 foreach (sort keys %currattach) {                  foreach my $key (sort(keys(%currattach))) {
                     if ($$allattachments{$_}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {                      if ($$allattachments{$key}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {
                         my $fname = $1.$3.'/'.$4;                          my $fname = $1.$3.'/'.$4;
                         $$imsfiles{$idx}{$i} .= '<file href="'.$fname.'">'."\n";                          $$imsfiles{$idx}{$i} .= '<file href="'.$fname.'" />'."\n";
                         $$attachtxt{$i}.= '<a href="'.$fname.'">'.$4.'</a><br />';                          $$attachtxt{$i}.= '<a href="'.$fname.'">'.$4.'</a><br />';
                     }                      }
                 }                  }
             }              }
         } else {          } else {
             if ($attachmsg) {              if ($attachmsg) {
                 $$attachtxt{$i} = '<br />Attachments:'.$attachmsg.'<br />';                  $$attachtxt{$i} = '<br />'.&mt('Attachments').':'.$attachmsg.'<br />';
             } else {              } else {
                 $$attachtxt{$i} = '';                  $$attachtxt{$i} = '';
             }              }
Line 1253  END Line 1544  END
         }          }
     }      }
     if ($type eq 'allversions') {      if ($type eq 'allversions') {
         $discussion.=('</ul></body></html>');          $discussion.='</ul>';
         return $discussion;          return $discussion;
     } else {      } else {
         return;          return;
Line 1263  END Line 1554  END
 sub replicate_attachments {  sub replicate_attachments {
     my ($attachrefs,$tempexport) = @_;      my ($attachrefs,$tempexport) = @_;
     my $response;      my $response;
     foreach my $id (keys %{$attachrefs}) {      foreach my $id (keys(%{$attachrefs})) {
         if ($$attachrefs{$id}{'filename'} =~ m-^/uploaded/([^/]+)/([^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {          if ($$attachrefs{$id}{'filename'} =~ m-^/uploaded/([^/]+)/([^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {
             my $path = $tempexport;              my $path = $tempexport;
             my $tail = $1.'/'.$2.$4;              my $tail = $1.'/'.$2.$4;
             my @extras = split/\//,$tail;              my @extras = split(/\//,$tail);
             my $destination = $tempexport.'/'.$1.'/'.$2.$4.'/'.$5;              my $destination = $tempexport.'/'.$1.'/'.$2.$4.'/'.$5;
             if (!-e $destination) {              if (!-e $destination) {
                 my $i= 0;                  my $i= 0;
Line 1286  sub replicate_attachments { Line 1577  sub replicate_attachments {
                         print $attachcopy $content;                          print $attachcopy $content;
                         close($attachcopy);                          close($attachcopy);
                     } else {                      } else {
                         $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$!.'<br />'."\n";                          $response .= &mt('Error copying file attachment - [_1] to IMS package',$5).': '.$!.'<br />'."\n";
                     }                      }
                 } else {                  } else {
                     &Apache::lonnet::logthis("Replication of attachment failed when building IMS export of discussion posts - domain: $1, course: $2, file: $$attachrefs{$id}{'filename'} -error: $rtncode");                      &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";                      $response .= &mt('Error copying file attachment - [_1] to IMS package: ',$5).$rtncode.'<br />'."\n";
                 }                  }
             }              }
         }          }
Line 1299  sub replicate_attachments { Line 1590  sub replicate_attachments {
 }  }
   
 sub mail_screen {  sub mail_screen {
   my ($r,$feedurl,$options) = @_;    my ($r,$feedurl,$options,$caller_symb,$attachmaxtext) = @_;
   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','blog']);        &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss','blog','group','ref']);
   }    }
   my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion',  
                                           '','onLoad="window.focus();setposttype();"');    my %lt = &Apache::lonlocal::texthash(
   my $title=&Apache::lonnet::gettitle($feedurl);              'myqu' => 'My question/comment/feedback:',
   if (!$title) { $title = $feedurl; }              'title' => 'Title',
               'reta' => 'Retained attachments',
               'atta' => 'Attachment',
              );
     my $restitle = &get_resource_title($caller_symb,$feedurl);
   my $quote='';    my $quote='';
   my $subject = '';    my $subject = '';
   my $comment = '';    my $comment = '';
Line 1324  sub mail_screen { Line 1619  sub mail_screen {
   my $attachnum = 0;    my $attachnum = 0;
   my $anonchk = (<<END);    my $anonchk = (<<END);
   function anonchk() {    function anonchk() {
      if (document.mailform.anondiscuss.checked == true) {        for (var i=0; i < document.mailform.discuss.length; i++) {
           document.attachment.anondiscuss.value = '1'    if (document.mailform.discuss[i].checked) {
      }        document.attachment.discuss.value = 
      if (document.mailform.discuss.checked == true) {    document.mailform.discuss[i].value;
           document.attachment.discuss.value = '1'    }
      }        }
         if (document.mailform.blog.checked) {
     document.attachment.blog.value = 1;
         }
      return       return
    }     }
 END  END
Line 1337  END Line 1635  END
   if (exists($env{'form.origpage'})) {    if (exists($env{'form.origpage'})) {
       $anonscript = (<<END);        $anonscript = (<<END);
   function setposttype() {    function setposttype() {
       var anondisc = $env{'form.anondiscuss'};        var disc = "$env{'form.discuss'}";
       var disc = $env{'form.discuss'};        for (var i=0; i < document.mailform.discuss.length; i++) {
       if (anondisc == 1) {    if (disc == document.mailform.discuss[i].value) {
           document.mailform.anondiscuss.checked = true        document.mailform.discuss[i].checked = 1;
     }
       }        }
       if (disc == 1) {        var blog = "$env{'form.blog'}";
           document.mailform.discuss.checked = true        if (blog == 1) {
             document.mailform.blog.checked=1;
       }        }
       return        return
   }    }
Line 1367  END Line 1667  END
       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'} =~ /:/) {
                   my @oldversions = split/:/,$contrib{$idx.':history'};                    my @oldversions = split(/:/,$contrib{$idx.':history'});
                   $numoldver = @oldversions;                    $numoldver = @oldversions;
               } else {                } else {
                   $numoldver = 1;                    $numoldver = 1;
Line 1376  END Line 1676  END
           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'});
                       $numoldver = @oldversions;                        $numoldver = @oldversions;
                   } else {                    } else {
                       $numoldver = 1;                        $numoldver = 1;
                   }                    }
               }                }
               my $message;  
               if ($idx > 0) {                if ($idx > 0) {
                   my %msgversions = ();                    my %msgversions = ();
                   &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);                    &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);
                   $message = $msgversions{$numoldver};                    $quote = $msgversions{$numoldver};
               }                }
       &newline_to_br(\$message);  
       $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message).'</blockquote>';  
               if ($idx > 0) {                if ($idx > 0) {
                   my %subversions = ();                    my %subversions = ();
                   &get_post_versions(\%subversions,$contrib{$idx.':subject'},1,$numoldver);                    &get_post_versions(\%subversions,$contrib{$idx.':subject'},1,$numoldver);
                   $subject = 'Re: '.$subversions{$numoldver};                    $subject = &mt('Re: ').$subversions{$numoldver};
               }                }
               $subject = &HTML::Entities::encode($subject,'<>&"');                $subject = &HTML::Entities::encode($subject,'<>&"');
           } else {            } else {
Line 1410  END Line 1707  END
                   $parentmsg = $contrib{$idx.':replyto'};                    $parentmsg = $contrib{$idx.':replyto'};
               }                }
               unless (exists($env{'form.origpage'})) {                unless (exists($env{'form.origpage'})) {
                   my $anonflag = 0;                    my $anonflag = 'nonanon';
                   if ($contrib{$idx.':anonymous'}) {                    if ($contrib{$idx.':anonymous'}) {
                       $anonflag = 1;                        $anonflag = 'anon';
                   }                    }
                   $anonscript = (<<END);                    $anonscript = (<<END);
   function setposttype () {    function setposttype () {
       var currtype = $anonflag        var currtype = "$anonflag";
       if (currtype == 1) {        for (var i=0; i<document.mailform.discuss.length; i++) {
           document.mailform.elements.discuss.checked = false    if (document.mailform.elements.discuss[i].value == currtype ) {
           document.mailform.elements.anondiscuss.checked = true        document.mailform.elements.discuss[i].checked=1;
       }    } 
       if (currtype == 0) {  
           document.mailform.elements.anondiscuss.checked = false  
           document.mailform.elements.discuss.checked = true  
       }        }
       return        return
   }    }
Line 1437  END Line 1731  END
   }    }
   
   if ($env{'form.origpage'}) {    if ($env{'form.origpage'}) {
       $subject = &Apache::lonnet::unescape($env{'form.subject'});        $subject = &unescape($env{'form.subject'});
       $comment = &Apache::lonnet::unescape($env{'form.comment'});        $comment = &unescape($env{'form.comment'});
       &process_attachments(\@currnewattach,\@currdelold,\@keepold);        &process_attachments(\@currnewattach,\@currdelold,\@keepold);
   }    }
   my $latexHelp=&Apache::loncommon::helpLatexCheatsheet();    my $latexHelp=&Apache::loncommon::helpLatexCheatsheet(undef,undef,1,($env{'form.modal'}?'popup':0));
   my $htmlheader=&Apache::lonhtmlcommon::htmlareaheaders();  
   my $send=&mt('Send');    my $send=&mt('Send');
   my $html=&Apache::lonxml::xmlbegin();    my $alert = &mt('Please select a feedback type.');
   $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() {
         var rec=0;          var rec=0;
         if (typeof(document.mailform.elements.author)!="undefined") {  
           if (document.mailform.elements.author.checked) {  
              rec=1;  
           }   
         }  
         if (typeof(document.mailform.elements.question)!="undefined") {  
           if (document.mailform.elements.question.checked) {  
              rec=1;  
           }   
         }  
         if (typeof(document.mailform.elements.course)!="undefined") {  
           if (document.mailform.elements.course.checked) {  
              rec=1;  
           }   
         }  
         if (typeof(document.mailform.elements.policy)!="undefined") {  
           if (document.mailform.elements.policy.checked) {  
              rec=1;  
           }   
         }  
         if (typeof(document.mailform.elements.discuss)!="undefined") {          if (typeof(document.mailform.elements.discuss)!="undefined") {
           if (document.mailform.elements.discuss.checked) {      if (typeof(document.mailform.elements.discuss.length) == "undefined") {
              rec=1;   if (document.mailform.elements.discuss.checked ) {
           }       rec=1;
         }   }
         if (typeof(document.mailform.elements.anondiscuss)!="undefined") {      } else {
           if (document.mailform.elements.anondiscuss.checked) {   for (var i=0; i<document.mailform.elements.discuss.length; i++) {
              rec=1;      if (document.mailform.elements.discuss[i].checked ) {
           }    rec=1;
         }      } 
    }
       }
    }
         if (typeof(document.mailform.elements.blog)!="undefined") {          if (typeof(document.mailform.elements.blog)!="undefined") {
           if (document.mailform.elements.blog.checked) {            if (document.mailform.elements.blog.checked) {
              rec=1;               rec=1;
Line 1497  $htmlheader Line 1768  $htmlheader
     }      }
     document.mailform.submit();      document.mailform.submit();
         } else {          } else {
             alert('Please check a feedback type.');              alert('$alert');
  }   }
     }      }
     $anonchk      $anonchk
     $anonscript      $anonscript
 //-->  //-->
 </script>  </script>
 </head>  END
 $bodytag  
 <h2><tt>$title</tt></h2>    my ($textareaheader,$textareaclass);
     if (&Apache::lonhtmlcommon::htmlareabrowser()) {
         $textareaheader = &Apache::lonhtmlcommon::htmlareaselectactive();
         $textareaclass = 'class="LC_richDefaultOff"';
         if ($env{'request.course.id'}) {
             unless (($env{'course.'.$env{'request.course.id'}.'.allow_limited_html_in_feedback'} =~ /^\s*yes\s*$/i) || ($env{'form.sendmessageonly'})) {
                 undef($textareaclass);
             }
         }
     }
   
     # Breadcrumbs
     my $brcrum = [{'href' => '',
                    'text' => 'Resource Feedback and Discussion'}];
   
     my %onload = ('onload' => 'window.focus();setposttype();');
     my %parms=('add_entries' => \%onload);
     if ($env{'form.modal'} ne 'yes') { 'bread_crumbs' => $brcrum }
     my $start_page=
         &Apache::loncommon::start_page('Resource Feedback and Discussion',$js,\%parms);
   
     if ($quote ne '') {
         $quote = &HTML::Entities::decode($quote);
         unless (&contains_block_html($quote)) {
             &newline_to_br(\$quote);
         }
         $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($quote).'</blockquote>';
     }
     my $header='';
     unless ($env{'form.modal'}) {
        $header="<h2><tt>$restitle</tt></h2>";
     }
     $r->print(<<END);
   $start_page
   $header
 <form action="/adm/feedback" method="post" name="mailform"  <form action="/adm/feedback" method="post" name="mailform"
 enctype="multipart/form-data">  enctype="multipart/form-data">
 $prevtag  $prevtag
 <input type="hidden" name="postdata" value="$feedurl" />  <input type="hidden" name="postdata" value="$feedurl" />
   <input type="hidden" name="modal" value="$env{'form.modal'}" />
 END  END
   if ($env{'form.replydisc'}) {    if ($env{'form.replydisc'}) {
       $r->print(<<END);        $r->print(<<END);
Line 1518  END Line 1824  END
 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
   }    }
   $r->print(<<END);    $r->print(<<END);
 Please check at least one of the following feedback types:  $options
 $options<hr />  
 $quote  $quote
 <p>My question/comment/feedback:</p>  <p>$lt{'myqu'}
   $textareaheader
   </p>
 <p>  <p>
 $latexHelp  $latexHelp
 Title: <input type="text" name="subject" size="30" value="$subject" /></p>  </p>
 <p>  <p>
 <textarea name="comment" id="comment" cols="60" rows="10" wrap="hard">$comment  $lt{'title'}: <input type="text" name="subject" size="30" value="$subject" /></p>
 </textarea></p>  
 <p>  <p>
   <textarea name="comment" id="comment" cols="60" rows="10" $textareaclass>$comment
   </textarea></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 my $attach (@currnewattach) {
                 $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");                  $r->print('<input type="hidden" name="currnewattach" value="'.$attach.'" />'."\n");
             }              }
             foreach (@currdelold) {              foreach my $oldatt (@currdelold) {
                 $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");                  $r->print('<input type="hidden" name="deloldattach" value="'.$oldatt.'" />'."\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));
                 foreach (keys %currattach) {                  foreach my $key (keys(%currattach)) {
                     $r->print('<input type="hidden" name="keepold" value="'.$_.'" />'."\n");                      $r->print('<input type="hidden" name="keepold" value="'.$key.'" />'."\n");
                 }                  }
             }              }
         }          }
     } else {      } else {
         $r->print(<<END);          $r->print(<<END);
 Attachment (128 KB max size): <input type="file" name="attachment" />  <p>
   $lt{'atta'} $attachmaxtext: <input type="file" name="attachment" />
 </p>  </p>
 END  END
     }      }
       if (exists($env{'form.group'})) {
           $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');
       }
       if (exists($env{'form.ref'})) {
           $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.'" />');
       }
     $r->print(<<END);      $r->print(<<END);
 <p>  <p>
 <input type="hidden" name="sendit" value="1" />  <input type="hidden" name="sendit" value="1" />
 <input type="button" value="$send" onClick='gosubmit();' />  <input type="button" value="$send" onclick='gosubmit();' />
 </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;
           &Apache::lonenc::check_encrypt(\$ressymb);
         my $postidx = '';          my $postidx = '';
         if ($env{'form.editdisc'}) {          if ($env{'form.editdisc'}) {
             $postidx = $idx;              $postidx = $idx;
Line 1576  END Line 1892  END
         if (@currnewattach > 0) {          if (@currnewattach > 0) {
             $attachnum += @currnewattach;              $attachnum += @currnewattach;
         }          }
         $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver));          my $blockblog = &Apache::loncommon::blocking_status('blogs');
           $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver,'',$blockblog));
         if ($attachnum > 0) {          if ($attachnum > 0) {
             if (@currnewattach > 0) {              if (@currnewattach > 0) {
                 $newattachmsg .= '<b>New attachments</b><br />';                  $newattachmsg .= '<br /><b>'.&mt('New attachments').'</b><br />';
                 if (@currnewattach > 1) {                  if (@currnewattach > 1) {
                     $newattachmsg .= '<ol>';                      $newattachmsg .= '<ol>';
                     foreach my $item (@currnewattach) {                      foreach my $item (@currnewattach) {
Line 1593  END Line 1910  END
                 }                  }
             }              }
             if ($attachmsg) {              if ($attachmsg) {
                 $r->print("<b>Retained attachments</b>:$attachmsg<br />\n");                  $r->print("<br /><b>$lt{'reta'}</b>:$attachmsg<br />\n");
             }              }
             if ($newattachmsg) {              if ($newattachmsg) {
                 $r->print("$newattachmsg<br />");                  $r->print("$newattachmsg<br />");
Line 1601  END Line 1918  END
         }          }
     }      }
     $r->print(&generate_preview_button().      $r->print(&generate_preview_button().
               &Apache::lonhtmlcommon::htmlareaselectactive('comment').        &Apache::loncommon::end_page());
               '</body></html>');  
 }  }
   
 sub print_display_options {  sub print_display_options {
Line 1613  sub print_display_options { Line 1930  sub print_display_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(
         'dido' => 'Discussion display options',  
         'pref' => 'Display Preference',          'pref' => 'Display Preference',
         'curr' => 'Current setting ',          'curr' => 'Current setting ',
         'actn' => 'Action',          'actn' => 'Action',
         'deff' => 'Default for all discussions',          'deff' => 'Default for all discussions',
         'prca' => 'Preferences can be set for this discussion that determine ....',          'prca' => 'Preferences can be set for this discussion that determine ....',
         'whpo' => 'Which posts are displayed when you display this bulletin board or resource, and',          'whpo' => 'Which posts are displayed when you display this discussion board or resource, and',
         'unwh' => 'Under what circumstances posts are identified as "NEW", and',          'unwh' => 'Under what circumstances posts are identified as "NEW", and',
         'wipa' => 'Whether individual posts can be marked as read/unread',          'wipa' => 'Whether individual posts can be marked as read/unread',
         'allposts' => 'All posts',          'allposts' => 'All posts',
         'unread' => 'New posts only',          'unread' => 'New posts only',
         'unmark' => 'Posts not marked read',          'unmark' => 'Posts not marked read',
         'ondisp' => 'Once displayed',          'ondisp' => 'Once displayed',
         'onmark' => 'Once marked not NEW ',          'onmark' => 'Once marked not NEW',
         'toggon' => 'Shown',          'toggon' => 'Shown',
         'toggoff' => 'Not shown',          'toggoff' => 'Not shown',
         'disa' => 'Posts displayed?',          'disa' => 'Posts displayed?',
Line 1675  sub print_display_options { Line 1989  sub print_display_options {
         $currtogg = $lt{'toggon'};          $currtogg = $lt{'toggon'};
         $disctogg = 'toggon';          $disctogg = 'toggon';
     }      }
     my $html=&Apache::lonxml::xmlbegin();  
     $r->print(<<END);      my $js = <<END;
 $html  <script type="text/javascript">
 <head>  
 <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 1748  function setDisp() { Line 2058  function setDisp() {
     }      }
 }  }
 </script>  </script>
 </head>  END
 $bodytag  
   
       my $start_page =
    &Apache::loncommon::start_page('Discussion display options',$js);
       my $end_page =
    &Apache::loncommon::end_page();
       $r->print(<<END);
   $start_page
 <form name="modifydisp" method="post" action="/adm/feedback">  <form name="modifydisp" method="post" 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">  END
  <tr>      $r->print(&Apache::loncommon::start_data_table());
   <td width="100%" bgcolor="#000000">      $r->print(<<END);
    <table width="100%" border="0" cellpadding="1" cellspacing="0">         <tr>
     <tr>          <th>$lt{'pref'}</td>
      <td width="100%" bgcolor="#000000">          <th>$lt{'curr'}</td>
       <table border="0" cellpadding="3" cellspacing="1" bgcolor="#FFFFFF">          <th>$lt{'actn'}?</td>
        <tr bgcolor="$tabcolor">  
         <td><b>$lt{'pref'}</b></td>  
         <td><b>$lt{'curr'}</b></td>  
         <td><b>$lt{'actn'}?</b></td>  
        </tr>         </tr>
        <tr bgcolor="#dddddd">  END
       $r->print(&Apache::loncommon::start_data_table_row());
       $r->print(<<END);
        <td>$lt{'disa'}</td>         <td>$lt{'disa'}</td>
        <td>$lt{$discdisp}</td>         <td>$lt{$discdisp}</td>
        <td><label><input type="checkbox" name="discdisp" onClick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"</label>         <td><label><input type="checkbox" name="discdisp" onclick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"</label>
            <br />             <br />
            <label><input type="checkbox" name="discdisp" onClick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"</label>             <label><input type="checkbox" name="discdisp" onclick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"</label>
        </td>         </td>
       </tr><tr bgcolor="#eeeeee">  END
       $r->print(&Apache::loncommon::end_data_table_row());
       $r->print(&Apache::loncommon::start_data_table_row());
       $r->print(<<END);
        <td>$lt{'npmr'}</td>         <td>$lt{'npmr'}</td>
        <td>$lt{$discmark}</td>         <td>$lt{$discmark}</td>
        <td><label><input type="checkbox" name="discmark" />$lt{'chgt'} "$markchange"</label></td>         <td><label><input type="checkbox" name="discmark" />$lt{'chgt'} "$markchange"</label></td>
       </tr><tr bgcolor="#dddddd">  END
       $r->print(&Apache::loncommon::end_data_table_row());
       $r->print(&Apache::loncommon::start_data_table_row());
       $r->print(<<END);
        <td>$lt{'dotm'}</td>         <td>$lt{'dotm'}</td>
        <td>$lt{$disctogg}</td>         <td>$lt{$disctogg}</td>
        <td><label><input type="checkbox" name="disctogg" onClick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</label></td>         <td><label><input type="checkbox" name="disctogg" onclick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</label></td>
       </tr>  END
      </table>      my $save = &mt('Save');
     </td>      $r->print(&Apache::loncommon::end_data_table_row());
    </tr>      $r->print(&Apache::loncommon::end_data_table());
   </table>      $r->print(<<END);
  </td>  
 </tr>  
 </table>  
 <br />  <br />
 <br />  <br />
 <input type="hidden" name="symb" value="$symb" />  <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="" />
 <input type="hidden" name="$markchg" value=""/>  <input type="hidden" name="$markchg" value="" />
 <input type="hidden" name="$toggchg" value="" />  <input type="hidden" name="$toggchg" value="" />
 <input type="button" name="sub" value="Store Changes" onClick="javascript:setDisp()" />  <input type="button" name="sub" value="$save" onclick="javascript:setDisp()" />
   END
       if (exists($env{'form.group'})) {
           $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');
       }
       if (exists($env{'form.ref'})) {
           $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.'" />');
       }
       $r->print("
 <br />  <br />
 <br />  <br />
 </form>  </form>
 </body>  $end_page
 </html>      ");
 END  
     return;      return;
 }  }
   
Line 1813  sub print_sortfilter_options { Line 2138  sub print_sortfilter_options {
     $r->send_http_header;      $r->send_http_header;
   
     &Apache::lonenc::check_encrypt(\$symb);      &Apache::lonenc::check_encrypt(\$symb);
     my @sections = ();      my @sections;
     my $section_sel = '';      my $section_sel = '';
     my $numsections = 0;  
     my $numvisible = 5;      my $numvisible = 5;
     my %sectioncount = ();      my @groups;
       my $group_sel = '';
     $numsections = &Apache::loncommon::get_sections($env{'course.'.$env{'request.course.id'}.'.domain'},$env{'course.'.$env{'request.course.id'}.'.num'},\%sectioncount);      my $numgroupvis = 5;
       my %sectioncount = &Apache::loncommon::get_sections();
       my @courseroles = qw(st ad ep ta in);
       my $crstype = &Apache::loncommon::course_type();
       my $ccrole = 'cc';
       if ($crstype eq 'Community') {
           $ccrole = 'co';
       }
       push(@courseroles,$ccrole);
       
     if ($env{'request.course.sec'} !~ /^\s*$/) {  #Restrict section choice to current section       if ($env{'request.course.sec'} !~ /^\s*$/) {  #Restrict section choice to current section 
         @sections = ('all',$env{'request.course.sec'});          @sections = ('all',$env{'request.course.sec'});
         $numvisible = 2;          $numvisible = 2;
     } else {      } else {
         @sections = sort {$a cmp $b} keys(%sectioncount);          @sections = sort {$a cmp $b} keys(%sectioncount);
           if (scalar(@sections) < 4) {
               $numvisible = scalar(@sections) + 1;
           }
         unshift(@sections,'all'); # Put 'all' at the front of the list          unshift(@sections,'all'); # Put 'all' at the front of the list
         if ($numsections < 4) {  
             $numvisible = $numsections + 1;      }
       foreach my $sec (@sections) {
           $section_sel .= "  <option value=\"$sec\">$sec</option>\n";
       }
   
       if (&check_group_priv() eq 'ok') {
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; 
           my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
           @groups = sort {$a cmp $b} keys(%curr_groups);
           if (scalar(@groups) < 4) {
               $numgroupvis = scalar(@groups) + 1;
           }
           unshift(@groups,'all'); # Put 'all' at the front of the list
       } else { 
           my @coursegroups = split(/:/,$env{'request.course.groups'});
           if (@coursegroups > 0) {
               @coursegroups = sort {$a cmp $b} @coursegroups;
               @groups = ('all',@coursegroups);
               if (scalar(@groups) < 4) {
                   $numgroupvis = scalar(@groups) + 1;
               }
           } else {
               @groups = ('all');
               $numgroupvis = 1;
         }          }
     }      }
     foreach (@sections) {      foreach my $group (@groups) {
         $section_sel .= "  <option value=\"$_\" />$_\n";          $group_sel .= "  <option value=\"$group\">$group</option>\n";
     }      }
                                                                                      
     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',
Line 1850  sub print_sortfilter_options { Line 2206  sub print_sortfilter_options {
         'spur' => 'Specific user roles',          'spur' => 'Specific user roles',
         'sprs' => 'Specific role status',          'sprs' => 'Specific role status',
         'spse' => 'Specific sections',          'spse' => 'Specific sections',
           'spgr' => 'Specific groups',
         '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',
           'stor' => 'Save changes',
     );      );
   
     my %sort_types = ();      my %sort_types = ();
     my %role_types = ();      my %role_types = ();
     my %status_types = ();      my %status_types = ();
     &sort_filter_names(\%sort_types,\%role_types,\%status_types);      &sort_filter_names(\%sort_types,\%role_types,\%status_types,$crstype);
     my $html=&Apache::lonxml::xmlbegin();  
     $r->print(<<END);      my $js = <<END;
 $html  
 <head>  
 <title>$lt{'diso'}</title>  
 <meta http-equiv="pragma" content="no-cache" />  
 <script type="text/javascript">  <script type="text/javascript">
 function verifyFilter() {  function verifyFilter() {
     var rolenum = 0      var rolenum = 0
Line 1885  function verifyFilter() { Line 2239  function verifyFilter() {
     if (secnum == 0) {      if (secnum == 0) {
         document.modifyshown.sectionpick.options[0].selected = true          document.modifyshown.sectionpick.options[0].selected = true
     }      }
   
       var grpnum = 0
       for (var i=0; i<document.modifyshown.grouppick.length; i++) {
           if (document.modifyshown.grouppick.options[i].selected == true) {
               grpnum ++
           }
       }
       if (grpnum == 0) {
           document.modifyshown.grouppick.options[0].selected = true
       }
   
     document.modifyshown.submit();      document.modifyshown.submit();
 }  }
 </script>  </script>
 </head>  END
 $bodytag  
       my $start_page=
    &Apache::loncommon::start_page('Discussion options',$js);
       my $end_page=
    &Apache::loncommon::end_page();
   
       $r->print(<<END);
   $start_page
 <form name="modifyshown" method="post" action="/adm/feedback">  <form name="modifyshown" method="post" action="/adm/feedback">
 <b>$lt{'diso'}</b><br/> $lt{'prca'}  <b>$lt{'diso'}</b><br/> $lt{'prca'}
 <br /><br />  <br />
 <table border="0">  <table border="0">
  <tr>   <tr>
   <td><b>$lt{'soor'}</b></td>    <th>$lt{'soor'}</th>
   <td>&nbsp;</td>    <th>&nbsp;</th>
   <td><b>$lt{'sprs'}</b></td>    <th>$lt{'sprs'}</th>
   <td>&nbsp;</td>    <th>&nbsp;</th>
   <td><b>$lt{'spur'}</b></td>    <th>$lt{'spur'}</th>
   <td>&nbsp;</td>    <th>&nbsp;</th>
   <td><b>$lt{'spse'}</b></td>    <th>$lt{'spse'}</th>
   <td>&nbsp;</td>    <th>&nbsp;</th>
   <td><b>$lt{'psub'}</b></td>    <th>$lt{'spgr'}</th>
     <th>&nbsp;</th>
     <th>$lt{'psub'}</th>
  </tr>   </tr>
  <tr>   <tr>
   <td align="center">    <td align="center" valign="top">
    <select name="sortposts">     <select name="sortposts">
     <option value="ascdate" selected="selected" />$sort_types{'ascdate'}      <option value="ascdate" selected="selected">$sort_types{'ascdate'}</option>
     <option value="descdate" />$sort_types{'descdate'}      <option value="descdate">$sort_types{'descdate'}</option>
     <option value="thread" />$sort_types{'thread'}      <option value="thread">$sort_types{'thread'}</option>
     <option value="subject" />$sort_types{'subject'}      <option value="subject">$sort_types{'subject'}</option>
     <option value="username" />$sort_types{'username'}      <option value="username">$sort_types{'username'}</option>
     <option value="lastfirst" />$sort_types{'lastfirst'}      <option value="lastfirst">$sort_types{'lastfirst'}</option>
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td align="center">    <td align="center" valign="top">
    <select name="statusfilter">     <select name="statusfilter">
     <option value="all" selected="selected" />$status_types{'all'}      <option value="all" selected="selected">$status_types{'all'}</option>
     <option value="Active" />$status_types{'Active'}      <option value="Active">$status_types{'Active'}</option>
     <option value="Expired" />$status_types{'Expired'}      <option value="Expired">$status_types{'Expired'}</option>
       <option value="Future">$status_types{'Future'}</option>
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td align="center">    <td align="center" valign="top">
    <select name="rolefilter" multiple="true" size="5">     <select name="rolefilter" multiple="multiple" size="5">
     <option value="all" />$role_types{'all'}      <option value="all">$role_types{'all'}</option>
     <option value="st" />$role_types{'st'}      <option value="st">$role_types{'st'}</option>
     <option value="cc" />$role_types{'cc'}      <option value="$ccrole">$role_types{$ccrole}</option>
     <option value="in" />$role_types{'in'}      <option value="in">$role_types{'in'}</option>
     <option value="ta" />$role_types{'ta'}      <option value="ta">$role_types{'ta'}</option>
     <option value="ep" />$role_types{'ep'}      <option value="ep">$role_types{'ep'}</option>
     <option value="ad" />$role_types{'ad'}      <option value="ad">$role_types{'ad'}</option>
     <option value="cr" />$role_types{'cr'}      <option value="cr">$role_types{'cr'}</option>
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td align="center">    <td align="center" valign="top">
    <select name="sectionpick" multiple="true" size="$numvisible">     <select name="sectionpick" multiple="multiple" size="$numvisible">
     $section_sel      $section_sel
    </select>     </select>
   </td>    </td>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td><label><input type="checkbox" name="posterlist" value="$symb" />$lt{'shal'}</label></td>    <td align="center" valign="top">
      <select name="grouppick" multiple="multiple" size="$numvisible">
       $group_sel
      </select>
     </td>
     <td>&nbsp;</td>
     <td valign="top"><label><input type="checkbox" name="posterlist" value="$symb" />$lt{'shal'}</label></td>
  </tr>   </tr>
 </table>  </table>
 <br />  <br />
 <br />  <input type="hidden" name="inhibitmenu" value="$env{'form.inhibitmenu'}" />
   <input type="hidden" name="modal" value="$env{'form.modal'}" />
 <input type="hidden" name="previous" value="$previous" />  <input type="hidden" name="previous" value="$previous" />
 <input type="hidden" name="applysort" value="$symb" />  <input type="hidden" name="applysort" value="$symb" />
 <input type="button" name="sub" value="Store Changes" onClick="verifyFilter()" />  <input type="button" name="sub" value="$lt{'stor'}" onclick="verifyFilter()" />
   END
       if (exists($env{'form.group'})) {
           $r->print('<input type="hidden" name="group" value="'.$env{'form.group'}.'" />');
       }
       if (exists($env{'form.ref'})) {
           $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.'" />');
       }
       $r->print("
 <br />  <br />
 <br />  <br />
 </form>  </form>
 </body>  $end_page
 </html>  ");
 END  
 }  }
   
 sub print_showposters {  sub print_showposters {
Line 1972  sub print_showposters { Line 2361  sub print_showposters {
         $crs.='_'.$env{'request.course.sec'};          $crs.='_'.$env{'request.course.sec'};
     }      }
     $crs=~s/\_/\//g;      $crs=~s/\_/\//g;
     my $seeid=&Apache::lonnet::allowed('rin',$crs);      my $seeid;
       my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       my $group = $env{'form.group'};
       my $ressymb = &wrap_symb($symb);
       if (($group ne '') &&
           ($ressymb =~ m|^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|)) {
           if (&check_group_priv($group,'dgp') eq 'ok') {
               $seeid = 1;
           }
       } else {
           $seeid=&Apache::lonnet::allowed('rin',$crs);
       }
     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},      my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                           $env{'course.'.$env{'request.course.id'}.'.domain'},                                           $cdom,$cnum);
                           $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 %lt = &Apache::lonlocal::texthash(
     );                                            sele => 'Select',
     my $bodytag=&Apache::loncommon::bodytag('Discussion options',                                            full => 'Fullname',
                                           '','');                                            usdo => 'Username:domain',
                                             post => 'Posts',
                                           );
     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\./);
             my $deleted=($contrib{'deleted'}=~/\.$idx\./);              my $deleted=($contrib{'deleted'}=~/\.$idx\./);
             unless ((($hidden) && (!$seeid)) || ($deleted)) {              unless ((($hidden) && (!$seeid)) || ($deleted)) {
                 if ((!$contrib{$idx.':anonymous'}) || ($seeid)) {                  if ((!$contrib{$idx.':anonymous'}) || (&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')))) {
                     my %names = &Apache::lonnet::get('environment',['firstname','lastname'],$contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});                      my %names = &Apache::lonnet::get('environment',['firstname','lastname'],$contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
                     my $lastname = $names{'lastname'};                      my $lastname = $names{'lastname'};
                     my $firstname = $names{'firstname'};                      my $firstname = $names{'firstname'};
Line 2005  sub print_showposters { Line 2407  sub print_showposters {
                     $postcounts{$poster} ++;                      $postcounts{$poster} ++;
                     if (defined($namesort{$lastname}{$firstname})) {                      if (defined($namesort{$lastname}{$firstname})) {
                         if (!grep/^$poster$/,@{$namesort{$lastname}{$firstname}}) {                          if (!grep/^$poster$/,@{$namesort{$lastname}{$firstname}}) {
                             push @{$namesort{$lastname}{$firstname}}, $poster;                              push(@{$namesort{$lastname}{$firstname}}, $poster);
                         }                          }
                     } else {                      } else {
                         @{$namesort{$lastname}{$firstname}} = ("$poster");                          @{$namesort{$lastname}{$firstname}} = ("$poster");
Line 2014  sub print_showposters { Line 2416  sub print_showposters {
             }              }
         }          }
     }      }
     my $html=&Apache::lonxml::xmlbegin();  
       my $start_page = &Apache::loncommon::start_page('Discussion options');
       my $table_start =&Apache::loncommon::start_data_table();
     $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">   <br />
    <tr>      $table_start
     <td bgcolor="#777777">        <tr>
      <table border="0" cellpadding="3">         <th>#</th>
       <tr bgcolor="#e6ffff">         <th>$lt{'sele'}</th>
        <td><b>No.</b></td>         <th>$lt{'full'} <font color="#999999">($lt{'usdo'})</font></th>
        <td><b>Select</b></td>         <th>$lt{'post'}</th>
        <td><b>Fullname</b><font color="#999999">(Username/domain)</font></td>  
        <td><b>Posts</td>  
       </tr>        </tr>
 END  END
     my $count = 0;      my $count = 0;
     foreach my $last (sort keys %namesort) {      foreach my $last (sort(keys(%namesort))) {
         foreach my $first (sort keys %{$namesort{$last}}) {          foreach my $first (sort(keys(%{$namesort{$last}}))) {
             foreach (sort @{$namesort{$last}{$first}}) {              foreach my $user (sort(@{$namesort{$last}{$first}})) {
                 my ($uname,$udom) = split/:/,$_;                  my ($uname,$udom) = split(/:/,$user);
                 if (!$uname || !$udom) {                   if (!$uname || !$udom) { 
                     next;                      next;
                 } else {                  } else {
                     $count ++;                      $count ++;
                     $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>');                      $r->print(&Apache::loncommon::start_data_table_row().
         '<td align="right">'.$count.'</td>
                                  <td align="center"><label><input name="stuinfo" type="checkbox" value="'.$user.'" /></td>
                                  <td>'.$last.', '.$first.' ('.$uname.':'.$udom.')</label></td>
                                  <td>'.$postcounts{$user}.'</td>'.
         &Apache::loncommon::end_data_table_row());
                 }                  }
             }              }
         }          }
     }      }
       $r->print(&Apache::loncommon::end_data_table());
       my $end_page   = &Apache::loncommon::end_page();
     $r->print(<<END);      $r->print(<<END);
      </table>  
     </td>  
    </tr>  
   </table>  
 <br />  <br />
 <input type="hidden" name="sortposts" value="$sortposts" />  <input type="hidden" name="sortposts" value="$sortposts" />
   <input type="hidden" name="modal" value="$env{'form.modal'}" />
 <input type="hidden" name="userpick" value="$symb" />  <input type="hidden" name="userpick" value="$symb" />
 <input type="button" name="store" value="Display posts" onClick="javascript:document.pickpostersform.submit()" />  <input type="button" name="store" value="Display posts" onclick="javascript:document.pickpostersform.submit()" />
 </form>  </form>
 </body>  $end_page
 </html>  
 END  END
 }  }
   
Line 2067  sub get_post_versions { Line 2467  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 2127  sub get_post_attachments { Line 2528  sub get_post_attachments {
 sub fail_redirect {  sub fail_redirect {
   my ($r,$feedurl) = @_;    my ($r,$feedurl) = @_;
   if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };    if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
     my %lt = &Apache::lonlocal::texthash(
                    'sorr' => 'Sorry, no recipients ...',
     );
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   my $html=&Apache::lonxml::xmlbegin();    $r->print(&Apache::loncommon::start_page('Feedback not sent',undef,
   $r->print (<<ENDFAILREDIR);     {'redirect'  => [2,$feedurl],
 $html      'only_body' => 1,}));
 <head>    $r->print(<<ENDFAILREDIR);
 <title>Feedback not sent</title>  
 <meta http-equiv="pragma" content="no-cache" />  
 <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />  
 </head>  
 <body bgcolor="#FFFFFF">  
 <img align="right" src="$logo" />  <img align="right" src="$logo" />
 <b>Sorry, no recipients  ...</b>  <b>$lt{'sorr'}</b>
 <br /><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,$blog,$status,$previous,$sort,$rolefilter,$statusfilter,$sectionpick,$numpicks) = @_;    my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$blog,$status,$previous,$sort,$rolefilter,$statusfilter,$sectionpick,$grouppick,$numpicks,$group,$toolarge) = @_;
   my $sorttag = '';    my $sorttag = '';
   my $roletag = '';    my $roletag = '';
   my $statustag = '';    my $statustag = '';
   my $sectag = '';    my $sectag = '';
     my $grptag = '';
   my $userpicktag = '';    my $userpicktag = '';
   my $qrystr = '';    my $qrystr = '';
   my $prevtag = '';    my $prevtag = '';
   
   &Apache::loncommon::content_type($r,'text/html');    &Apache::loncommon::content_type($r,'text/html');
   $r->send_http_header;    $r->send_http_header;
   
   &dewrapper(\$feedurl);    &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;
       if ($feedurl =~ /\?register=1/) {        if ($feedurl =~ /\?register=1/) {
           $feedurl .= '&'.$qrystr;            $feedurl .= '&amp;'.$qrystr;
       } else {        } else {
           $feedurl .= '?'.$qrystr;            $feedurl .= '?'.$qrystr;
       }        }
Line 2172  sub redirect_back { Line 2569  sub redirect_back {
   if (defined($sort)) {    if (defined($sort)) {
       my $sortqry = 'sortposts='.$sort;        my $sortqry = 'sortposts='.$sort;
       if (($feedurl =~ /\?register=1/) || ($feedurl =~ /\?previous=/)) {        if (($feedurl =~ /\?register=1/) || ($feedurl =~ /\?previous=/)) {
           $feedurl .= '&'.$sortqry;            $feedurl .= '&amp;'.$sortqry;
       } else {        } else {
           $feedurl .= '?'.$sortqry;            $feedurl .= '?'.$sortqry;
       }        }
       $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';        $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';
       if (defined($numpicks)) {        if (defined($numpicks)) {
           my $userpickqry = 'totposters='.$numpicks;            my $userpickqry = 'totposters='.$numpicks;
           $feedurl .= '&'.$userpickqry;            $feedurl .= '&amp;'.$userpickqry;
           $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';            $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';
       } else {        } else {
           if (ref($sectionpick) eq 'ARRAY') {            if (ref($sectionpick) eq 'ARRAY') {
               $feedurl .= '&sectionpick=';                $feedurl .= '&amp;sectionpick=';
               $sectag .=  '<input type="hidden" name="sectionpick" value="';                $sectag .=  '<input type="hidden" name="sectionpick" value="';
               foreach (@{$sectionpick}) {                foreach my $sec (@{$sectionpick}) {
                   $feedurl .= $_.',';                    $feedurl .= $sec.',';
                   $sectag .= $_.',';                    $sectag .= $sec.',';
               }                }
               $feedurl =~ s/,$//;                $feedurl =~ s/,$//;
               $sectag =~ s/,$//;                $sectag =~ s/,$//;
               $sectag .= '" />';                $sectag .= '" />';
           } else {            } else {
               $feedurl .= '&sectionpick='.$sectionpick;                $feedurl .= '&amp;sectionpick='.$sectionpick;
               $sectag = '<input type="hidden" name="sectionpick" value="'.$sectionpick.'" />';                $sectag = '<input type="hidden" name="sectionpick" value="'.$sectionpick.'" />';
           }            }
             if (ref($grouppick) eq 'ARRAY') {
                 $feedurl .= '&amp;grouppick=';
                 $sectag .=  '<input type="hidden" name="grouppick" value="';
                 foreach my $grp (@{$grouppick}) {
                     $feedurl .= $grp.',';
                     $grptag .= $grp.',';
                 }
                 $feedurl =~ s/,$//;
                 $grptag =~ s/,$//;
                 $grptag .= '" />';
             } else {
                 $feedurl .= '&amp;grouppick='.$grouppick;
                 $grptag = '<input type="hidden" name="grouppick" value="'.$grouppick.'" />';
             }
           if (ref($rolefilter) eq 'ARRAY') {            if (ref($rolefilter) eq 'ARRAY') {
               $feedurl .= '&rolefilter=';                $feedurl .= '&amp;rolefilter=';
               $roletag .=  '<input type="hidden" name="rolefilter" value="';                $roletag .=  '<input type="hidden" name="rolefilter" value="';
               foreach (@{$rolefilter}) {                foreach my $role (@{$rolefilter}) {
                   $feedurl .= $_.',';                    $feedurl .= $role.',';
                   $roletag .= $_.',';                    $roletag .= $role.',';
               }                }
               $feedurl =~ s/,$//;                $feedurl =~ s/,$//;
               $roletag =~ s/,$//;                $roletag =~ s/,$//;
               $roletag .= '" />';                $roletag .= '" />';
           } else {            } else {
               $feedurl .= '&rolefilter='.$rolefilter;                $feedurl .= '&amp;rolefilter='.$rolefilter;
               $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';                $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';
           }            }
           $feedurl .= '&statusfilter='.$statusfilter;            $feedurl .= '&amp;statusfilter='.$statusfilter;
           $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';            $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';
       }        }
   }    }
   $feedurl=&Apache::lonenc::check_encrypt($feedurl);    my $grouptag;
     if ($group ne '') {
         $grouptag = '<input type="hidden" name="group" value="'.$group.'" />';
         my $refarg;
         if (exists($env{'form.ref'})) {
             $refarg = '&amp;ref='.$env{'form.ref'};
             $grouptag .= '<input type="hidden" name="ref" value="'.$env{'form.ref'}.'" />';
         }
         if ($feedurl =~ /\?/) {
             $feedurl .= '&amp;group='.$group.$refarg;
         } else {
             $feedurl .= '?group='.$group.$refarg;
         }
     } 
     &Apache::lonenc::check_encrypt(\$feedurl);
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   my $html=&Apache::lonxml::xmlbegin();    my %parms=('only_body'   => 1);
   $r->print (<<ENDREDIR);    if ($env{'form.modal'}) {
 $html        $parms{'add_entries'}={'onLoad' => 'document.forms.reldt.submit()'};
 <head>    } else {
 <title>Feedback sent</title>        $parms{'redirect'}=[0,$feedurl];
 <meta http-equiv="pragma" content="no-cache" />    }
 <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />    my $start_page=
 </head>        &Apache::loncommon::start_page('Feedback sent',undef,\%parms);
 <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.window.close(); }'>    my $end_page = &Apache::loncommon::end_page();
     $r->print(<<ENDREDIR);
   $start_page
 <img align="right" src="$logo" />  <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  $blog
   $toolarge
 <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 2236  $sorttag Line 2664  $sorttag
 $statustag  $statustag
 $roletag  $roletag
 $sectag  $sectag
   $grptag
 $userpicktag  $userpicktag
   $grouptag
 </form>  </form>
 <br /><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');   
   my $html=&Apache::lonxml::xmlbegin();    my %onload;
   $r->print (<<ENDNOREDIR);  
 $html    my %body_options = ('only_body'   => 1,
 <head>        'bgcolor'     => '#FFFFFF',
 <title>Feedback not sent</title>        'add_entries' => \%onload,);
 <meta http-equiv="pragma" content="no-cache" />  
 ENDNOREDIR    if ($feedurl !~ m{^/adm/feedback}) { 
         $body_options{'rediect'} = [2,$feedurl];
   if ($feedurl!~/^\/adm\/feedback/) {   
       $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2; url='.  
  &Apache::lonenc::check_encrypt($feedurl).'">');  
   }    }
   $feedurl=&Apache::lonenc::check_encrypt($feedurl);    my $start_page=
         &Apache::loncommon::start_page('Feedback not sent',undef,
        \%body_options);
         
     my $end_page = &Apache::loncommon::end_page();
   
     &Apache::lonenc::check_encrypt(\$feedurl);
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');    my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   $r->print (<<ENDNOREDIRTWO);    $r->print (<<ENDNOREDIRTWO);
 </head>  $start_page
 <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { self.window.close(); }'>  
 <img align="right" src="$logo" />  <img align="right" src="$logo" />
 <b>$nofeed</b>  <b>$nofeed</b>
 <br /><a href="$feedurl">$continue</a>  <br />
 </body>  $end_page
 </html>  
 ENDNOREDIRTWO  ENDNOREDIRTWO
 }  }
   
 sub screen_header {  sub screen_header {
     my ($feedurl,$symb) = @_;      my ($feedurl,$symb,$group) = @_;
       my $crscontent = &mt('Question/Comment/Feedback about course content');
       my $crspolicy = &mt('Question/Comment/Feedback about course policy');
       my $contribdisc = &mt('Contribution to course discussion of resource');
       my $anoncontrib = &mt('Anonymous contribution to course discussion of resource');
       my $namevis = &mt('name only visible to course faculty');
       my $crstype;
       if ($env{'request.course.id'}) {
           $crstype = &Apache::loncommon::course_type();
           if ($crstype eq 'Community') {
               $crscontent = &mt('Question/Comment/Feedback about community content');
               $crspolicy = &mt('Question/Comment/Feedback about community policy');
               $contribdisc = &mt('Contribution to community discussion of resource');
               $anoncontrib = &mt('Anonymous contribution to community discussion of resource');
               $namevis = &mt('name only visible to community facilitators');
           }
       }
     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/) && ($env{'user.adv'})) {   if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/) && ($env{'user.adv'})) {
     $msgoptions=       $msgoptions= 
  '<p><label><input type="checkbox" name="author" /> '.   '<label><input type="radio" name="discuss" value="author" /> '.
  &mt('Feedback to resource author').'</label></p>';   &mt('Feedback to resource author').'</label><br />';
    }
           my %optionhash=();
           foreach my $type ('question','comment','policy') {
       $optionhash{$type}=$env{'course.'.$env{'request.course.id'}.'.'.$type.'.email.text'};
  }   }
  if (&feedback_available(1)) {   if (&feedback_available(1)) {
     $msgoptions.=      $msgoptions.=
  '<p><label><input type="checkbox" name="question" /> '.   '<label><input type="radio" name="discuss" value="question" /> '.
  &mt('Question about resource content').'</label></p>';   ($optionhash{'question'}?$optionhash{'question'}:&mt('Question about resource content')).'</label><br />';
  }   }
  if (&feedback_available(0,1)) {   if (&feedback_available(0,1)) {
     $msgoptions.=      $msgoptions.=
  '<p><label><input type="checkbox" name="course" /> '.   '<label><input type="radio" name="discuss" value="course" /> '.
  &mt('Question/Comment/Feedback about course content').   ($optionhash{'comment'}?$optionhash{'comment'}:$crscontent).
  '</label></p>';   '</label><br />';
  }   }
  if (&feedback_available(0,0,1)) {   if (&feedback_available(0,0,1)) {
     $msgoptions.=      $msgoptions.=
  '<p><label><input type="checkbox" name="policy" /> '.   '<label><input type="radio" name="discuss" value="policy" /> '.
  &mt('Question/Comment/Feedback about course policy').   ($optionhash{'policy'}?$optionhash{'policy'}:$crspolicy).
  '</label></p>';   '</label><br />';
  }   }
     }      }
     if ($env{'request.course.id'}) {      if (($env{'request.course.id'}) && (!$env{'form.sendmessageonly'})) {
  if (&discussion_open(undef,$symb) &&          my ($blocked,$blocktext) = &Apache::loncommon::blocking_status('boards');
     &Apache::lonnet::allowed('pch',          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
      $env{'request.course.id'}.          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
      ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {          my $realsymb = $symb;
     $discussoptions='<label><input type="checkbox" name="discuss" onClick="this.form.anondiscuss.checked=false;" '.          if ($symb=~/^bulletin___/) {
  ($env{'form.replydisc'}?' checked="1"':'').' /> '.              my $filename=(&Apache::lonnet::decode_symb($symb))[2];
  &mt('Contribution to course discussion of resource');              $filename=~s|^adm/wrapper/||;
     $discussoptions.='</label><br /><label><input type="checkbox" name="anondiscuss" onClick="this.form.discuss.checked=false;" /> '.              $realsymb=&Apache::lonnet::symbread($filename);
  &mt('Anonymous contribution to course discussion of resource').          }
  ' <i>('.&mt('name only visible to course faculty').')</i></label> '.          if (!$blocked && &discussion_open(undef,$realsymb) && 
       (&Apache::lonnet::allowed('pch',
         $env{'request.course.id'}.
         ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')) || 
               (($group ne '') && ($symb =~ m{^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$}) && (&check_group_priv($group,'pgd') eq 'ok')))) {
       $discussoptions='<label><input type="radio" name="discuss" value="nonanon" checked="checked" /> '.
    $contribdisc.
           '</label><br /><label><input type="radio" name="discuss" value="anon" /> '.
    $anoncontrib.
    ' <i>('.$namevis.')</i></label> '.
  '<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';   '<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';
               my $blockblog = &Apache::loncommon::blocking_status('blogs');
               if (!$blockblog) {
                   $discussoptions.= &add_blog_checkbox($crstype);
               }
         }          }
         $discussoptions.='<br /><label><input type="checkbox" name="blog" /> '.  
     &mt('Add to my public course blog').'</label>';  
     }      }
     if ($msgoptions) { $msgoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').'" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }      if ($msgoptions) {
           $msgoptions='<tr><th><img src="'.&Apache::loncommon::lonhttpdurl('/res/adm/pages/feedback.png').'" />'
                      .'<br />'.&mt('Send Feedback').'<br />'.&Apache::lonhtmlcommon::coursepreflink(&mt('Feedback Settings'),'feedback').'</th>'.
                      '<td>'.$msgoptions.'</td></tr>';
       }
     if ($discussoptions) {       if ($discussoptions) { 
  $discussoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" />'.&mt('Discussion Contributions').'</h2>'.$discussoptions; }   $discussoptions='<tr><th><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" alt="" />'
     return $msgoptions.$discussoptions;                          .'<br />'.&mt('Discussion Contributions').'<br />'.&Apache::lonhtmlcommon::coursepreflink(&mt('Discussion Settings'),'discussion').'</th>'.
                           '<td>'.$discussoptions.'</td></tr>';
       }
       return  &Apache::loncommon::start_data_table().$msgoptions.$discussoptions.&Apache::loncommon::end_data_table();
 }  }
   
 sub resource_output {  sub resource_output {
Line 2338  sub resource_output { Line 2805  sub resource_output {
   
 sub clear_out_html {  sub clear_out_html {
   my ($message,$override)=@_;    my ($message,$override)=@_;
   unless (&Apache::lonhtmlcommon::htmlareablocked()) { return $message; }  
 # Always allow the <m>-tag  # Always allow the <m>-tag
   my %html=(M=>1);    my %html=(M=>1);
 # Check if more is allowed  # Check if more is allowed
Line 2347  sub clear_out_html { Line 2813  sub clear_out_html {
       ($override)) {        ($override)) {
       # allows <B> <I> <P> <A> <LI> <OL> <UL> <EM> <BR> <TT> <STRONG>         # allows <B> <I> <P> <A> <LI> <OL> <UL> <EM> <BR> <TT> <STRONG> 
       # <BLOCKQUOTE> <DIV .*> <DIV> <IMG> <M> <SPAN> <H1> <H2> <H3> <H4> <SUB>        # <BLOCKQUOTE> <DIV .*> <DIV> <IMG> <M> <SPAN> <H1> <H2> <H3> <H4> <SUB>
       # <SUP>        # <SUP> <TABLE> <TR> <TD> <TH> <TBODY>
       %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1,        %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1,
      BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, DIV=>1, IMG=>1,       BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, PRE=>1, DIV=>1, IMG=>1,
      M=>1, ALGEBRA=>1, SUB=>1, SUP=>1, SPAN=>1,        M=>1, CHEM=>1, ALGEBRA=>1, SUB=>1, SUP=>1, SPAN=>1,  
      H1=>1, H2=>1, H3=>1, H4=>1, H5=>1);       H1=>1, H2=>1, H3=>1, H4=>1, H5=>1, H6=>1, 
        TABLE=>1, TR=>1, TD=>1, TH=>1, TBODY=>1);
   }    }
 # Do the substitution of everything that is not explicitly allowed  # Do the substitution of everything that is not explicitly allowed
   $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/    $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/
Line 2362  sub clear_out_html { Line 2829  sub clear_out_html {
 }  }
   
 sub assemble_email {  sub assemble_email {
   my ($feedurl,$message,$prevattempts,$usersaw,$useranswer)=@_;    my ($message,$prevattempts,$usersaw,$useranswer)=@_;
     my %lt = &Apache::lonlocal::texthash(
                'prev' => 'Previous attempts of student (if applicable)',
                'orig' => 'Original screen output (if applicable)',
                'corr' => 'Correct Answer(s) (if applicable)',
     );
     if (&Apache::loncommon::course_type() eq 'Community') {
         $lt{'prev'} = &mt('Previous attempts of member (if applicable)');
     }
   my $email=<<"ENDEMAIL";    my $email=<<"ENDEMAIL";
 $message  $message
 ENDEMAIL  ENDEMAIL
     my $citations=<<"ENDCITE";      my $citations=<<"ENDCITE";
 <h2>Previous attempts of student (if applicable)</h2>  <h2>$lt{'prev'}</h2>
 $prevattempts  $prevattempts
 <br /><hr />  <br /><hr />
 <h2>Original screen output (if applicable)</h2>  <h2>$lt{'orig'}</h2>
 $usersaw  $usersaw
 <h2>Correct Answer(s) (if applicable)</h2>  <h2>$lt{'corr'}</h2>
 $useranswer  $useranswer
 ENDCITE  ENDCITE
   return ($email,$citations);    return ($email,$citations);
 }  }
   
 sub secapply {  
     my $rec=shift;  
     my $defaultflag=shift;  
     $rec=~s/\s+//g;  
     $rec=~s/\@/\:/g;  
     my ($adr,$sections)=($rec=~/^([^\(]+)\(([^\)]+)\)/);  
     if ($sections) {  
  foreach (split(/\;/,$sections)) {  
             if (($_ eq $env{'request.course.sec'}) ||  
                 ($defaultflag && ($_ eq '*'))) {  
                 return $adr;   
             }  
         }  
     } else {  
        return $rec;  
     }  
     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 {  
   my ($feedurl,$author,$question,$course,$policy,$defaultflag) = @_;  
   my $typestyle='';  
   my %to=();  
   if ($env{'form.author'}||$author) {  
     $typestyle.='Submitting as Author Feedback<br />';  
     $feedurl=~/^\/res\/(\w+)\/(\w+)\//;  
     $to{$2.':'.$1}=1;  
   }  
   if ($env{'form.question'}||$question) {  
     $typestyle.='Submitting as Question<br />';  
     foreach (split(/\,/,  
    $env{'course.'.$env{'request.course.id'}.'.question.email'})  
      ) {  
  my $rec=&secapply($_,$defaultflag);  
         if ($rec) { $to{$rec}=1; }  
     }   
   }  
   if ($env{'form.course'}||$course) {  
     $typestyle.='Submitting as Comment<br />';  
     foreach (split(/\,/,  
    $env{'course.'.$env{'request.course.id'}.'.comment.email'})  
      ) {  
  my $rec=&secapply($_,$defaultflag);  
         if ($rec) { $to{$rec}=1; }  
     }   
   }  
   if ($env{'form.policy'}||$policy) {  
     $typestyle.='Submitting as Policy Feedback<br />';  
     foreach (split(/\,/,  
    $env{'course.'.$env{'request.course.id'}.'.policy.email'})  
      ) {  
  my $rec=&secapply($_,$defaultflag);  
         if ($rec) { $to{$rec}=1; }  
     }   
   }  
   if ((scalar(%to) eq '0') && (!$defaultflag)) {  
      ($typestyle,%to)=  
  &decide_receiver($feedurl,$author,$question,$course,$policy,1);  
   }  
   return ($typestyle,%to);  
 }  
   
 sub feedback_available {  sub feedback_available {
     my ($question,$course,$policy)=@_;      my ($question,$course,$policy)=@_;
     my ($typestyle,%to)=&decide_receiver('',0,$question,$course,$policy);      my ($typestyle,%to)=&Apache::lonmsg::decide_receiver('',0,$question,
    $course,$policy);
     return scalar(%to);      return scalar(%to);
 }  }
   
 sub send_msg {  sub send_msg {
   my ($title,$feedurl,$email,$citations,$attachmenturl,%to)=@_;      my ($title,$feedurl,$email,$citations,$attachmenturl,$symb,%to)=@_;
   my $status='';      my $status='';
   my $sendsomething=0;      my $sendsomething=0;
   if ($title=~/^Error/) { $title=&mt('Feedback').': '.$title; }      my $restitle = &get_resource_title($symb,$feedurl);
   unless ($title=~/\w/) { $title=&mt('Feedback'); }      if ($title=~/^Error/) { $title=&mt('Feedback').': '.$title; }
   foreach (keys %to) {      unless ($title=~/\w/) { $title=&mt('Feedback'); }
     if ($_) {      foreach my $key (keys(%to)) {
       my $declutter=&Apache::lonnet::declutter($feedurl);   if ($key) {
       unless (&Apache::lonmsg::user_normal_msg(split(/\:/,$_),      my ($user,$domain) = split(/\:/,$key,2);
                $title.' ['.$declutter.']',$email,$citations,$feedurl,      if (!defined($user)) {
                 $attachmenturl)=~/ok/) {   $status.='<br />'.&mt('Error sending message to [_1], no user specified.',$key);
  $status.='<br />'.&mt('Error sending message to').' '.$_.'<br />';      } elsif (!defined($domain)) {
       } else {   $status.='<br />'.&mt('Error sending message to [_1], no domain specified.',$key);
  $sendsomething++;      } else {
       }   unless (&Apache::lonmsg::user_normal_msg($user,$domain,
    $title.' ['.$restitle.']',$email,$citations,$feedurl,
    $attachmenturl,undef,undef,$symb,$restitle)=~/ok/) {
       $status.='<br />'.&mt('Error sending message to').' '.$key.'<br />';
    } else {
       $sendsomething++;
    }
       }
    }
     }      }
   }  
   
     my %record=&Apache::lonnet::restore('_feedback');  # Records of number of feedback messages are kept under the "symb" called "_feedback"
     my ($temp)=keys %record;  # There are two entries within the framework of a course:
     unless ($temp=~/^error\:/) {  # - the URLs for which feedback was provided
        my %newrecord=();  # - the total number of contributions
        $newrecord{'resource'}=$feedurl;      if ($sendsomething) {
        $newrecord{'subnumber'}=$record{'subnumber'}+1;          my %record=&getfeedbackrecords();
        unless (&Apache::lonnet::cstore(\%newrecord,'_feedback') eq 'ok') {          my ($temp)=keys(%record);
    $status.='<br />'.&mt('Not registered').'<br />';          unless ($temp=~/^error\:/) {
        }      my %newrecord=();
       $newrecord{'resource'}=$feedurl;
       $newrecord{'subnumber'}=$record{'subnumber'}+1;
       unless (&Apache::lonnet::cstore(\%newrecord,'_feedback') eq 'ok') {
           $status.='<br />'.&mt('Not registered').'<br />';
       }
           }
     }      }
              return ($status,$sendsomething);
   return ($status,$sendsomething);  }
   
   # Routine to get the complete feedback records
   
   sub getfeedbackrecords {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&Apache::lonnet::restore('_feedback',$course,$udom,$uname);
       return %record;
   }
   
   # Routine to get feedback statistics
   
   sub getfeedbackstats {
       my %record=&getfeedbackrecords(@_);
       return ($record{'subnumber'},$record{'points'},$record{'totallikes'});
   }
   
   # Store feedback credit
   
   sub storefeedbackpoints {
       my ($points,$uname,$udom,$course)=@_;
       unless ($points) { $points=0; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=('grader_user'   => $env{'user.name'},
                   'grader_domain' => $env{'user.domain'},
                   'points' => $points);
       return &Apache::lonnet::cstore(\%record,'_feedback',$course,$udom,$uname);
   }
   
   # Store feedback "likes"
   
   sub storefeedbacklikes {
       my ($likes,$uname,$udom,$course)=@_;
       unless ($likes) { $likes=0; }
       if ($likes>0) { $likes=1; }
       if ($likes<0) { $likes=-1; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&getfeedbackrecords($uname,$udom,$course);
       my $totallikes=$record{'totallikes'};
       $totallikes+=$likes;
       my %newrecord=('likes_user'   => $env{'user.name'},
                      'likes_domain' => $env{'user.domain'},
                      'likes' => $likes,
                      'totallikes' => $totallikes);
       return &Apache::lonnet::cstore(\%newrecord,'_feedback',$course,$udom,$uname);
 }  }
   
   
 sub adddiscuss {  sub adddiscuss {
     my ($symb,$email,$anon,$attachmenturl,$subject)=@_;      my ($symb,$email,$anon,$attachmenturl,$subject,$group)=@_;
     my $status='';      my $status='';
     my $realsymb;      my $realsymb;
     if ($symb=~/^bulletin___/) {      if ($symb=~/^bulletin___/) {
Line 2519  sub adddiscuss { Line 2968  sub adddiscuss {
  $filename=~s|^adm/wrapper/||;   $filename=~s|^adm/wrapper/||;
  $realsymb=&Apache::lonnet::symbread($filename);   $realsymb=&Apache::lonnet::symbread($filename);
     }      }
       my ($cnum,$cdom);
       if ($env{'request.course.id'}) {
           $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       }
     if (&discussion_open(undef,$realsymb) &&      if (&discussion_open(undef,$realsymb) &&
  &Apache::lonnet::allowed('pch',$env{'request.course.id'}.   (&Apache::lonnet::allowed('pch',$env{'request.course.id'}.
         ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {           ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')) || 
            (($group ne '') && (&check_group_priv($group,'pgd') eq 'ok') && 
            ($symb =~ m{^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$})))) {
   
     my %contrib=('message'      => $email,      my %contrib=('message'      => $email,
                  'sendername'   => $env{'user.name'},                   'sendername'   => $env{'user.name'},
Line 2540  sub adddiscuss { Line 2996  sub adddiscuss {
  $contrib{'anonymous'}='true';   $contrib{'anonymous'}='true';
     }      }
     if (($symb) && ($email)) {      if (($symb) && ($email)) {
           my $now = time;
         if ($env{'form.editdisc'}) {          if ($env{'form.editdisc'}) {
             $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'} = $now;
             $contrib{'history'} = '';              $contrib{'history'} = '';
             my $numoldver = 0;              my $numoldver = 0;
             my ($oldsymb,$oldidx)=split(/\:\:\:/,$env{'form.editdisc'});              my ($oldsymb,$oldidx)=split(/\:\:\:/,$env{'form.editdisc'});
Line 2558  sub adddiscuss { Line 3015  sub adddiscuss {
             }              }
             if (defined($oldcontrib{$oldidx.':history'})) {              if (defined($oldcontrib{$oldidx.':history'})) {
                 if ($oldcontrib{$oldidx.':history'} =~ /:/) {                  if ($oldcontrib{$oldidx.':history'} =~ /:/) {
                     my @oldversions = split/:/,$oldcontrib{$oldidx.':history'};                      my @oldversions = split(/:/,$oldcontrib{$oldidx.':history'});
                     $numoldver = @oldversions;                      $numoldver = @oldversions;
                 } else {                  } else {
                     $numoldver = 1;                      $numoldver = 1;
Line 2594  sub adddiscuss { Line 3051  sub adddiscuss {
                      $env{'course.'.$env{'request.course.id'}.'.domain'},                       $env{'course.'.$env{'request.course.id'}.'.domain'},
      $env{'course.'.$env{'request.course.id'}.'.num'});       $env{'course.'.$env{'request.course.id'}.'.num'});
         }          }
         my %storenewentry=($symb => time);          my %storenewentry=($symb => $now);
         $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=&getdiscussionrecords();
     my ($temp)=keys %record;      my ($temp)=keys(%record);
     unless ($temp=~/^error\:/) {      unless ($temp=~/^error\:/) {
        my %newrecord=();         my %newrecord=();
        $newrecord{'resource'}=$symb;         $newrecord{'resource'}=$symb;
Line 2615  sub adddiscuss { Line 3072  sub adddiscuss {
     return $status.'<br />';         return $status.'<br />';   
 }  }
   
   
   # Routine to get the complete discussion records
   
   sub getdiscussionrecords {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&Apache::lonnet::restore('_discussion',$course,$udom,$uname);
       return %record;
   }
   
   # Routine to get discussion statistics
   
   sub getdiscussionstats {
       my %record=&getdiscussionrecords(@_);
       return ($record{'subnumber'},$record{'points'},$record{'totallikes'},$record{'totalvotes'});
   }
   
   # Calculate discussion karma
   
   sub calcdiscussionkarma {    
       my ($subs,$pts,$likes,$votes)=&getdiscussionstats(@_);
       my $karma=0;
       if ($votes>0) {
           $karma=int(.1+5.*(1.-exp(-$subs/10.))*$likes/$votes);
           if ($karma<0) { $karma=0; }
           if ($karma>5) { $karma=5; }
       }
       return $karma;
   }
   
   # Update karma
   
   sub updatekarma {
       my ($uname,$udom,$course)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my $karma=&calcdiscussionkarma($uname,$udom,$course);
   }
   
   # Store discussion credit
   
   sub storediscussionpoints {
       my ($points,$uname,$udom,$course)=@_;
       unless ($points) { $points=0; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=('grader_user'   => $env{'user.name'},
                   'grader_domain' => $env{'user.domain'},
                   'points' => $points);
       return &Apache::lonnet::cstore(\%record,'_discussion',$course,$udom,$uname);
   }
   
   # Store discussion "likes"
   
   sub storediscussionlikes {
       my ($likes,$uname,$udom,$course)=@_;
       unless ($likes) { $likes=0; }
       if ($likes>0) { $likes=1; }
       if ($likes<0) { $likes=-1; }
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       unless ($course) { $course=$env{'request.course.id'}; }
       my %record=&getdiscussionrecords($uname,$udom,$course);
       my $totallikes=$record{'totallikes'};
       my $totalvotes=$record{'totalvotes'};
       $totallikes+=$likes;
       $totalvotes++;
       my %newrecord=('likes_user'   => $env{'user.name'},
                      'likes_domain' => $env{'user.domain'},
                      'likes' => $likes,
                      'totallikes' => $totallikes,
                      'totalvotes' => $totalvotes);
       return &Apache::lonnet::cstore(\%newrecord,'_discussion',$course,$udom,$uname);
   }
   
   sub get_discussion_info {
       my ($idx,%contrib) = @_;
       my $changelast = 0;
       my $count = 0;
       my $hiddenflag = 0;
       my $deletedflag = 0;
       my ($hidden,$deleted,%info,$newlastdisc);
       my $version = $contrib{'version'};
       if ($version) {
           for (my $id=$version; $id>0; $id--) {
               my $vkeys=$contrib{$id.':keys'};
               my @keys=split(/:/,$vkeys);
               if (grep(/^hidden$/,@keys)) {
                   if (!$hiddenflag) {
                       $hidden = $contrib{$id.':hidden'};
                       $hiddenflag = 1;
                   }
               } elsif (grep(/^deleted$/,@keys)) {
                   if (!$deletedflag) {
                       $deleted = $contrib{$id.':deleted'};
                       $deletedflag = 1;
                   }
               } else {
                   if (($hidden !~/\.$id\./) && ($deleted !~/\.$id\./)) {
                       $count++;
                       $info{$count}{'id'} = $id;
                       $info{$count}{'timestamp'}=$contrib{$id.':timestamp'}; 
                   }
               }
           }
           if ($info{'1'}{'id'} == $idx) {
               $changelast = 1;
               if ($count > 1) { 
                   $newlastdisc =  $info{'2'}{'timestamp'};
               } else {
                   $newlastdisc = 0;
               }
           }
       }
       return ($changelast,$newlastdisc);
   }
   
 # ----------------------------------------------------------- Preview function  # ----------------------------------------------------------- Preview function
   
 sub show_preview {  sub show_preview {
     my $r=shift;      my ($r) = @_;
     &Apache::loncommon::content_type($r,'text/html');      &Apache::loncommon::content_type($r,'text/html');
     $r->send_http_header;      $r->send_http_header;
       my $start_page=
    &Apache::loncommon::start_page('Preview',undef,
          {'only_body'   => 1,});
   
     my $message=&clear_out_html($env{'form.comment'});      my $message=&clear_out_html($env{'form.comment'});
     &newline_to_br(\$message);      &newline_to_br(\$message);
     $message=&Apache::lonspeller::markeduptext($message);      $message=&Apache::lonspeller::markeduptext($message);
Line 2628  sub show_preview { Line 3210  sub show_preview {
     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);
     my $html=&Apache::lonxml::xmlbegin();  
     $r->print($html.'<head>'.      my $end_page = &Apache::loncommon::end_page();
       '</head><body><table border="2"><tr><td>'.  
       '<b>Subject:</b> '.$subject.'<br /><br />'.      $r->print($start_page
       $message.'</td></tr></table></body></html>');               .'<h1>'.&mt('Preview').'</h1>'
                .&Apache::lonhtmlcommon::start_pick_box()
                .&Apache::lonhtmlcommon::row_title(&mt('Subject'))
                .$subject
                .&Apache::lonhtmlcommon::row_closure()
                .&Apache::lonhtmlcommon::row_title(&mt('Message'))
                .$message
                .&Apache::lonhtmlcommon::row_closure(1)
                .&Apache::lonhtmlcommon::end_pick_box()
                .$end_page
       );
 }  }
   
   sub contains_block_html {
       my ($message)=@_;
       return ($message =~ m{
           <(br|h1|h2|h3|h4|h5|h6|p|ol|ul|table|pre|address|blockquote|center|div) 
     \s*
    (\w+\=['"]\w+['"])*
     \s*
    (
     \s*/>|
     >.*</\1\s*>
    )}xs 
       );
   }
   
   sub tidy_html {
    my ($message)=@_;
   # my $tidy = HTML::Tidy::libXML->new();
   # my $xhtml = $tidy->clean($message, 'utf-8', 1);
   # $xhtml =~ m/<body>(.*)<\/body>/is;
   # my $clean = $1;
   # # remove any empty block-level tags
   # $clean =~ s/<(table|p|div|tbody|blockquote|m|pre|algebra|center|ol|ul|span|h1|h2|h3|h4|h5|h6)\s*\/>//i;
   # $message=$clean;
    return $message;
   }
   
 sub newline_to_br {  sub newline_to_br {
     my ($message)=@_;      my ($message)=@_;
Line 2663  sub generate_preview_button { Line 3280  sub generate_preview_button {
     unless ($fieldname) { $fieldname='comment'; }      unless ($fieldname) { $fieldname='comment'; }
     my $pre=&mt("Show Preview and Check Spelling");      my $pre=&mt("Show Preview and Check Spelling");
     return(<<ENDPREVIEW);      return(<<ENDPREVIEW);
   <br />
 <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.$formname.onsubmit)=='function') {document.$formname.onsubmit();};this.form.comment.value=document.$formname.$fieldname.value;this.form.subject.value=document.$formname.subject.value;this.form.submit();" />  onclick="if (typeof(document.$formname.onsubmit)=='function') {document.$formname.onsubmit();};this.form.comment.value=document.$formname.$fieldname.value;this.form.subject.value=document.$formname.subject.value;this.form.submit();" />
 </form>  </form>
 ENDPREVIEW  ENDPREVIEW
 }  }
   
 sub modify_attachments {  sub modify_attachments {
     my ($r,$currnewattach,$currdelold,$symb,$idx,$attachmenturls)=@_;      my ($r,$currnewattach,$currdelold,$symb,$idx,$attachmenturls,
     my $orig_subject = &Apache::lonnet::unescape($env{'form.subject'});          $attachmaxtext,$toolarge)=@_;
   
       my %lt = &Apache::lonlocal::texthash(
                  'subj' => 'Subject',
                  'thfo' => 'The following attachments were part of the most recent saved version of this posting.',
                  'chth' => 'Check the checkboxes for any you wish to remove.',
                  'thef' => 'The following attachments have been uploaded for inclusion with this posting.',
                  'adda' => 'Add a new attachment to this post.',
                  'stch' => 'Save Changes',
                );
       my $js = <<END;
   <script type="text/javascript">
    function setAction () {
      document.modattachments.action = document.modattachments.origpage.value;
      document.modattachments.submit();
    }
   </script> 
   END
   
       # Breadcrumbs
       my $brcrum = [{'href' => '',
                      'text' => 'Discussion Post Attachments'}];
       my %parms=();
       if ($env{'form.modal'} ne 'yes') { 'bread_crumbs' => $brcrum }
   
       my $start_page = 
    &Apache::loncommon::start_page('Discussion Post Attachments',$js,\%parms);
   
       my $orig_subject = &unescape($env{'form.subject'});
     my $subject=&clear_out_html($orig_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 = ();
Line 2689  sub modify_attachments { Line 3334  sub modify_attachments {
         &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);          &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);
     }      }
     &Apache::lonenc::check_encrypt(\$symb);      &Apache::lonenc::check_encrypt(\$symb);
     my $html=&Apache::lonxml::xmlbegin();  
       my $end_page = 
    &Apache::loncommon::end_page();
          
     $r->print(<<END);      $r->print(<<END);
 $html  $start_page
 <head>  $toolarge
 <title>Managing Attachments</title>  
 <script>  
  function setAction () {  
    document.modattachments.action = document.modattachments.origpage.value;  
    document.modattachments.submit();  
  }  
 </script>   
 </head>  
 $bodytag  
 <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">   <br />
    <table class="LC_data_table">
   <tr>    <tr>
    <td>     <td colspan="2">
     <b>Subject:</b> $subject</b><br /><br />      <b>Subject:</b> <b>$subject</b><br /><br />
 END  END
     if ($idx) {      if ($idx) {
         if ($attachmenturls) {          if ($attachmenturls) {
             my @currold = keys %currattach;              my @currold = keys(%currattach);
             if (@currold > 0) {              if (@currold > 0) {
                 $r->print("The following attachments were part of the most recent saved version of this posting.<br />Check the checkboxes for any you wish to remove<br />\n");                    $r->print($lt{'thfo'}.'<br />'.$lt{'chth'}.'<br />'."\n");  
                 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#/([^/]+)$#;
Line 2722  END Line 3362  END
             }              }
         }          }
     }      }
     if (@{$currnewattach} > 0) {      if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) {
         $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($lt{'thef'}.'<br />'.$lt{'chth'}.'<br />'."\n");
         foreach (@{$currnewattach}) {          foreach my $attach (@{$currnewattach}) {
             $_ =~ m#/([^/]+)$#;              $attach =~ m#/([^/]+)$#;
             $r->print('<label><input type="checkbox" name="delnewattach" value="'.$_.'" />&nbsp;'.$1.'</label><br />'."\n");              $r->print('<label><input type="checkbox" name="delnewattach" value="'.$attach.'" />&nbsp;'.$1.'</label><br />'."\n");
         }          }
         $r->print("<br />");           $r->print("<br />"); 
     }      }
     $r->print(<<END);      $r->print(<<END);
    Add a new attachment to this post.&nbsp;<input type="file" name="addnewattach" /><input type="button" name="upload" value="Upload" onClick="this.form.submit()" />         </td></tr>
      <tr>
       <td>
      $lt{'adda'}</td><td><input type="file" name="addnewattach" /><input type="button" name="upload" value="Upload" onclick="this.form.submit()" />    
    </td>     </td>
   </tr>    </tr>
     <tr>
      <td colspan="2">$attachmaxtext</td>
     </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'}" />
Line 2741  END Line 3387  END
 <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="blog" value="$env{'form.blog'}" />  <input type="hidden" name="blog" value="$env{'form.blog'}" />
 <input type="hidden" name="discuss" value="$env{'form.discuss'}" />  <input type="hidden" name="discuss" value="$env{'form.discuss'}" />
 END  END
     foreach (@{$currnewattach}) {      foreach my $item (@{$currnewattach}) {
         $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");          $r->print('<input type="hidden" name="currnewattach" value="'.$item.'" />'."\n");
     }      }
     foreach (@{$currdelold}) {      foreach my $item (@{$currdelold}) {
         $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");          $r->print('<input type="hidden" name="deloldattach" value="'.$item.'" />'."\n");
     }      }
     $r->print(<<END);      $r->print(<<END);
  <input type="button" name="rtntoedit" value="Store Changes" onClick="setAction()"/>   <input type="button" name="rtntoedit" value="$lt{'stch'}" onclick="setAction()" />
 </form>  </form>
 </body>  $end_page
 </html>  
 END  END
     return;      return;
 }  }
Line 2773  sub process_attachments { Line 3417  sub process_attachments {
         my @currnew = ();          my @currnew = ();
         foreach my $newone (@{$currnewattach}) {          foreach my $newone (@{$currnewattach}) {
             my $delflag = 0;              my $delflag = 0;
             foreach (@currdelnew) {              foreach my $item (@currdelnew) {
                 if ($newone eq $_) {                  if ($newone eq $item) {
                     $delflag = 1;                      $delflag = 1;
                     last;                      last;
                 }                  }
             }              }
             unless ($delflag) {              unless ($delflag) {
                 push @currnew, $newone;                  push(@currnew, $newone);
             }              }
         }          }
         @{$currnewattach} = @currnew;          @{$currnewattach} = @currnew;
Line 2789  sub process_attachments { Line 3433  sub process_attachments {
 }  }
   
 sub generate_attachments_button {  sub generate_attachments_button {
     my ($idx,$attachnum,$ressymb,$now,$currnewattach,$deloldattach,$numoldver,$mode) = @_;      my ($idx,$attachnum,$ressymb,$now,$currnewattach,$deloldattach,
           $numoldver,$mode,$blockblog) = @_;
     my $origpage = $ENV{'REQUEST_URI'};      my $origpage = $ENV{'REQUEST_URI'};
     my $att=$attachnum.' '.&mt("attachments");      my $att=$attachnum.' '.&mt("attachments");
       my %lt = &Apache::lonlocal::texthash(
                   'clic' => 'Click to add/remove attachments',
       ); 
     my $response = (<<END);      my $response = (<<END);
   <br />
 <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"  $lt{'clic'}:&nbsp;<input type="button" value="$att"
 onClick="if (typeof(document.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=escape(document.mailform.comment.value);this.form.subject.value=escape(document.mailform.subject.value);  onclick="if (typeof(document.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=escape(document.mailform.comment.value);this.form.subject.value=escape(document.mailform.subject.value);
 END  END
       if (!$blockblog) {
           $response .= 'setblogvalue();';
       }
     unless ($mode eq 'board') {      unless ($mode eq 'board') {
         $response .= 'javascript:anonchk();';          $response .= 'javascript:anonchk();';
     }      }
Line 2807  this.form.submit();" /> Line 3459  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="blog" value = "0" />  <input type="hidden" name="blog" value="0" />
 <input type="hidden" name="anondiscuss" value = "0" />  <input type="hidden" name="discuss" 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)) {
         if (@{$deloldattach} > 0) {          if (@{$deloldattach} > 0) {
             foreach (@{$deloldattach}) {              foreach my $delatt (@{$deloldattach}) {
                 $response .= '<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n";                  $response .= '<input type="hidden" name="deloldattach" value="'.$delatt.'" />'."\n";
             }              }
         }          }
     }      }
     if (defined($currnewattach)) {      if (defined($currnewattach)) {
         if (@{$currnewattach} > 0) {          if (@{$currnewattach} > 0) {
             foreach (@{$currnewattach}) {              foreach my $attach (@{$currnewattach}) {
                 $response .= '<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";                  $response .= '<input type="hidden" name="currnewattach" value="'.$attach.'" />'."\n";
             }              }
         }          }
     }      }
Line 2834  sub extract_attachments { Line 3485  sub extract_attachments {
     my ($attachmenturls,$idx,$numoldver,$message,$attachments,$currattach,$currdelold) = @_;      my ($attachmenturls,$idx,$numoldver,$message,$attachments,$currattach,$currdelold) = @_;
     %{$attachments}=();      %{$attachments}=();
     &get_post_attachments($attachments,$attachmenturls);      &get_post_attachments($attachments,$attachmenturls);
     foreach my $id (sort keys %{$attachments}) {      foreach my $id (sort(keys(%{$attachments}))) {
         if (exists($$attachments{$id}{$numoldver})) {          if (exists($$attachments{$id}{$numoldver})) {
             if (defined($currdelold)) {              if (defined($currdelold)) {
                 if (@{$currdelold} > 0) {                  if (@{$currdelold} > 0) {
Line 2849  sub extract_attachments { Line 3500  sub extract_attachments {
             }              }
         }          }
     }      }
     my @attached = (sort { $a <=> $b } keys %{$currattach});      my @attached = (sort { $a <=> $b } keys(%{$currattach}));
     if (@attached == 1) {      if (@attached == 1) {
         my $id = $attached[0];          my $id = $attached[0];
         my $attachurl;          my $attachurl;
Line 2865  sub extract_attachments { Line 3516  sub extract_attachments {
                                $attachurl);                                 $attachurl);
     } elsif (@attached > 1) {      } elsif (@attached > 1) {
         $$message.='<ol>';          $$message.='<ol>';
         foreach (@attached) {          foreach my $attach (@attached) {
             my $id = $_;              my $id = $attach;
             my $attachurl = &HTML::Entities::decode($$attachments{$id}{'filename'});              my $attachurl = &HTML::Entities::decode($$attachments{$id}{'filename'});
             my ($fname)              my ($fname)
               =($attachurl=~m|/([^/]+)$|);                =($attachurl=~m|/([^/]+)$|);
Line 2893  sub construct_attachmenturl { Line 3544  sub construct_attachmenturl {
         $oldattachmenturl = $contrib{$idx.':attachmenturl'};          $oldattachmenturl = $contrib{$idx.':attachmenturl'};
         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'});
                 $currver = 1 + scalar(@oldversions);                  $currver = 1 + scalar(@oldversions);
             } else {              } else {
                 $currver = 2;                  $currver = 2;
Line 2906  sub construct_attachmenturl { Line 3557  sub construct_attachmenturl {
                 my %attachments = ();                  my %attachments = ();
                 my $prevver = $currver-1;                  my $prevver = $currver-1;
                 &get_post_attachments(\%attachments,$oldattachmenturl);                  &get_post_attachments(\%attachments,$oldattachmenturl);
                 my $numattach = scalar(keys %attachments);                  my $numattach = scalar(keys(%attachments));
                 $startnum += $numattach;                  $startnum += $numattach;
                 foreach my $num (sort {$a <=> $b} keys %attachments) {                  foreach my $num (sort {$a <=> $b} keys(%attachments)) {
                     $newattachmenturl .= '<attachment id="'.$num.'"><filename>'.$attachments{$num}{'filename'}.'</filename>';                      $newattachmenturl .= '<attachment id="'.$num.'"><filename>'.$attachments{$num}{'filename'}.'</filename>';
                     foreach $_ (sort {$a <=> $b} keys %{$attachments{$num}}) {                      foreach my $item (sort {$a <=> $b} keys(%{$attachments{$num}})) {
                         unless ($_ eq 'filename') {                          unless ($item eq 'filename') {
                             $newattachmenturl .= '<post id="'.$_.'">'.$attachments{$num}{$_}.'</post>';                              $newattachmenturl .= '<post id="'.$item.'">'.$attachments{$num}{$item}.'</post>';
                         }                          }
                     }                      }
                     if (grep/^$num$/,@{$keepold}) {                      if (grep/^$num$/,@{$keepold}) {
Line 2937  sub construct_attachmenturl { Line 3588  sub construct_attachmenturl {
     return $newattachmenturl;       return $newattachmenturl; 
 }  }
   
   sub add_blog_checkbox {
       my ($crstype) = @_;
       my $checkstatus;
       if ($env{'form.blog'}) {
           $checkstatus = 'checked="checked"';
       }
       my $output = '
   <script type="text/javascript">
   function setblogvalue() {
       if (document.mailform.blog.checked) {
           document.attachment.blog.value = 1;
       } else {
           document.attachment.blog.value = 0;
       }
   }
   </script><br />
   <label><input type="checkbox" name="blog" '.$checkstatus.' /> ';
       if ($crstype eq 'Community') {
           $output .= &mt('Add to my public community blog');
       } else {
           $output .= &mt('Add to my public course blog');
       } 
       $output .= '</label><br />'."\n";
       return $output;
   }
   
 sub has_discussion {  sub has_discussion {
     my $resourcesref = shift;      my $resourcesref = shift;
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
     my @allres=$navmap->retrieveResources();      if (defined($navmap)) {
     foreach my $resource (@allres) {          my @allres=$navmap->retrieveResources();
         if ($resource->hasDiscussion()) {          foreach my $resource (@allres) {
             my $ressymb = $resource->wrap_symb();              if ($resource->hasDiscussion()) {
             push @{$resourcesref}, $ressymb;                  my $ressymb = $resource->wrap_symb();
                   if (ref($resourcesref) eq 'ARRAY') {
                       push(@{$resourcesref}, $ressymb);
                   }
               }
         }          }
       } else {
           &Apache::lonnet::logthis('Has discussion check failed - could not create navmap object.');
     }      }
     return;      return;
 }  }
   
 sub sort_filter_names {  sub sort_filter_names {
     my ($sort_types,$role_types,$status_types) = @_;      my ($sort_types,$role_types,$status_types,$crstype) = @_;
     %{$sort_types} = (      if (ref($sort_types) eq 'HASH') {
           %{$sort_types} = (
                      ascdate => 'Date order - oldest first',                       ascdate => 'Date order - oldest first',
                      descdate => 'Date order - newest first',                       descdate => 'Date order - newest first',
                      thread => 'Threaded',                       thread => 'Threaded',
Line 2960  sub sort_filter_names { Line 3644  sub sort_filter_names {
                      username => 'By domain and username',                       username => 'By domain and username',
                      lastfirst => 'By last name, first name'                       lastfirst => 'By last name, first name'
                    );                     );
     %{$role_types} = (      }
                      all => 'All roles',      my @courseroles = qw(st in ta ep ad);
                      st  => 'Students',      if ($crstype eq 'Community') {
                      cc  => 'Course Coordinators',          push(@courseroles,'co');
                      in  => 'Instructors',      } else {
                      ta  => 'TAs',          push(@courseroles,'cc');
                      ep  => 'Exam proctors',      }
                      ad  => 'Administrators',      if (ref($role_types) eq 'HASH') {
                      cr  => 'Custom roles'          foreach my $role (@courseroles) {
                    );              $role_types->{$role} = &Apache::lonnet::plaintext($role,$crstype);
     %{$status_types} = (          }
           $role_types->{'all'} = 'All roles';
           $role_types->{'cr'} = 'Custom role';
       }
       if (ref($status_types) eq 'HASH') {
           %{$status_types} = (
                      all     => 'Roles of any status',                       all     => 'Roles of any status',
                      Active => 'Only active roles',                       Active  => 'Only active roles',
                      Expired => 'Only inactive roles'                       Expired => 'Only past roles',
                        Future  => 'Only future roles',
                    );                     );
       }
 }  }
       
 sub handler {  sub handler {
Line 2988  sub handler { Line 3679  sub handler {
 # --------------------------- Get query string for limited number of parameters  # --------------------------- Get query string for limited number of parameters
   
   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
          ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export']);           ['like','unlike','modal','hide','unhide','deldisc','undeleteall','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','groupick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export','sendmessageonly','group','ref']);
     my $group = $env{'form.group'};
     my %attachmax = (
                       text => &mt('(128 KB max size)'),
                       num  => 131072,
                     );
   if ($env{'form.editdisc'}) {    if ($env{'form.editdisc'}) {
       if (!(&editing_allowed())) {        if (!(&editing_allowed($env{'form.editdisc'},$env{'form.group'}))) {
           my $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];            my $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
           my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);            my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
           my $feedurl=&Apache::lonnet::clutter($url);            my $feedurl=&Apache::lonnet::clutter($url);
           &redirect_back($r,$feedurl,&mt('Editing not permitted').'<br />',                     '0','0','','',$env{'form.previous'},'','','',);            &redirect_back($r,$feedurl,&mt('Editing not permitted').'<br />',                     '0','0','','',$env{'form.previous'},undef,undef,undef,
                       undef,undef,undef,$group);
           return OK;            return OK;
       }        }
   }     } 
Line 3003  sub handler { Line 3700  sub handler {
       my $readkey = $symb.'_read';        my $readkey = $symb.'_read';
       my $chgcount = 0;        my $chgcount = 0;
       my %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 3021  sub handler { Line 3718  sub handler {
   \%readinghash,$env{'user.domain'},$env{'user.name'});    \%readinghash,$env{'user.domain'},$env{'user.name'});
       }        }
       &redirect_back($r,$feedurl,&mt('Marked postings read/unread').'<br />',        &redirect_back($r,$feedurl,&mt('Marked postings read/unread').'<br />',
      '0','0','','',$env{'form.previous'},'','','',);       '0','0','','',$env{'form.previous'},'','','',
                        undef,undef,undef,$group);
       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 $html=&Apache::lonxml::xmlbegin();  
       my $bodytag=&Apache::loncommon::bodytag('Discussion Post Versions');        # Breadcrumbs
       $r->print(<<END);        my $brcrum = [{'href' => '',
 $html                       'text' => 'Discussion Post Versions'}];
 <head>        
 <title>Post Versions</title>        my %parms=();
 <meta http-equiv="pragma" content="no-cache" />        if ($env{'form.modal'} ne 'yes') { 'bread_crumbs' => $brcrum }
 </head>  
 $bodytag        $r->print(&Apache::loncommon::start_page('Discussion Post Versions',undef,\%parms));
 END  
       my $crs='/'.$env{'request.course.id'};        my $crs='/'.$env{'request.course.id'};
       if ($env{'request.course.sec'}) {        if ($env{'request.course.sec'}) {
           $crs.='_'.$env{'request.course.sec'};            $crs.='_'.$env{'request.course.sec'};
       }        }
       $crs=~s|_|/|g;        $crs=~s|_|/|g;
       my $seeid=&Apache::lonnet::allowed('rin',$crs);        my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       my ($symb,$idx)=split(/\:\:\:/,$env{'form.allversions'});        my ($symb,$idx)=split(/\:\:\:/,$env{'form.allversions'});
       ($symb)=&get_feedurl_and_clean_symb($symb);        ($symb)=&get_feedurl_and_clean_symb($symb);
         my $ressymb = &wrap_symb($symb);
         my $group = $env{'form.group'};
         my $seeid;
         if (($group ne '') && (($ressymb =~ m|^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|))) {
             if (&check_group_priv($group,'dgp') eq 'ok') {
                 $seeid = 1;
             }
         } else {
             $seeid = &Apache::lonnet::allowed('rin',$crs);
         }
       if ($idx > 0) {        if ($idx > 0) {
           my %messages = ();            my %messages = ();
           my %subjects = ();            my %subjects = ();
Line 3057  END Line 3767  END
                            $env{'course.'.$env{'request.course.id'}.'.num'});                             $env{'course.'.$env{'request.course.id'}.'.num'});
           $r->print(&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(&Apache::loncommon::end_page());
       return OK;        return OK;
   }    }
   if ($env{'form.posterlist'}) {    if ($env{'form.posterlist'}) {
Line 3075  END Line 3786  END
    \%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','',        &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0','',
      '',$env{'form.previous'},$env{'form.sortposts'},'','','',       '',$env{'form.previous'},$env{'form.sortposts'},'','','',
      $numpicks);       '',$numpicks,$group);
       return OK;        return OK;
   }    }
   if ($env{'form.applysort'}) {    if ($env{'form.applysort'}) {
Line 3083  END Line 3794  END
       &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0','',        &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0','',
      '',$env{'form.previous'},$env{'form.sortposts'},       '',$env{'form.previous'},$env{'form.sortposts'},
      $env{'form.rolefilter'},$env{'form.statusfilter'},       $env{'form.rolefilter'},$env{'form.statusfilter'},
      $env{'form.sectionpick'});       $env{'form.sectionpick'},$env{'form.grouppick'},
                        undef,$group);
       return OK;        return OK;
   } elsif ($env{'form.cmd'} eq 'sortfilter') {    } elsif ($env{'form.cmd'} eq 'sortfilter') {
       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
Line 3094  END Line 3806  END
       my @resources = ();        my @resources = ();
       if (defined($env{'form.navmaps'})) {        if (defined($env{'form.navmaps'})) {
           if ($env{'form.navmaps'} =~ /:/) {            if ($env{'form.navmaps'} =~ /:/) {
               @resources = split/:/,$env{'form.navmaps'};                @resources = split(/:/,$env{'form.navmaps'});
           } else {            } else {
               @resources = ("$env{'form.navmaps'}");                @resources = ("$env{'form.navmaps'}");
           }            }
Line 3107  END Line 3819  END
       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.'            'twnp' => 'There are currently no resources or discussion boards with unread discussion postings.'
       );               );       
       foreach (@resources) {        foreach my $res (@resources) {
           my $ressymb=$_;            my $ressymb=$res;
   &Apache::lonenc::check_decrypt(\$ressymb);    &Apache::lonenc::check_decrypt(\$ressymb);
           my $lastkey = $ressymb.'_lastread';            my $lastkey = $ressymb.'_lastread';
           $discinfo{$lastkey} = $env{'form.navtime'};            $discinfo{$lastkey} = $env{'form.navtime'};
Line 3125  END Line 3837  END
       &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 $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
       my $html=&Apache::lonxml::xmlbegin();        my %onload;
   
         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>  
 <title>New posts marked as read</title>  
 <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.window.close(); }'>  
 <img align="right" src="$logo" />  <img align="right" src="$logo" />
 $textline  $textline
 <form name="reldt" action="$feedurl" target="loncapaclient">  <form name="reldt" action="$feedurl" target="loncapaclient">
 </form>  </form>
 <br /><a href="$feedurl">Continue</a>  <br />
 </body>  $end_page
 </html>  
 ENDREDIR  ENDREDIR
       return OK;        return OK;
   } elsif ($env{'form.modifydisp'}) {    } elsif ($env{'form.modifydisp'}) {
Line 3184  ENDREDIR Line 3896  ENDREDIR
       my $previous=$env{'form.previous'};        my $previous=$env{'form.previous'};
       if ($env{'form.markondisp'}) { $previous=undef; }        if ($env{'form.markondisp'}) { $previous=undef; }
       &redirect_back($r,$feedurl,&mt('Changed display status').'<br />',        &redirect_back($r,$feedurl,&mt('Changed display status').'<br />',
      '0','0','','',$previous);       '0','0','','',$previous,'','','','','','',$group);
       return OK;        return OK;
   } elsif (($env{'form.hide'}) || ($env{'form.unhide'})) {    } elsif (($env{'form.hide'}) || ($env{'form.unhide'})) {
 # ----------------------------------------------------------------- Hide/unhide  # ----------------------------------------------------------------- Hide/unhide
Line 3199  ENDREDIR Line 3911  ENDREDIR
       $crs=~s/\_/\//g;        $crs=~s/\_/\//g;
       my $seeid=&Apache::lonnet::allowed('rin',$crs);        my $seeid=&Apache::lonnet::allowed('rin',$crs);
   
       if ($env{'form.hide'} && !$seeid && !(&editing_allowed())) {        if ($env{'form.hide'} && !$seeid && !(&editing_allowed($env{'form.hide'},$env{'form.group'}))) {
           &redirect_back($r,$feedurl,&mt('Deletion not permitted').'<br />',                 '0','0','','',$env{'form.previous'},'','','',);            &redirect_back($r,$feedurl,&mt('Deletion not permitted').'<br />',                 '0','0','','',$env{'form.previous'},'','','','',
                    undef,undef,$group,);
           return OK;            return OK;
       }        }
   
Line 3223  ENDREDIR Line 3936  ENDREDIR
       if ( ($env{'form.hide'}) && (!$seeid) ) {        if ( ($env{'form.hide'}) && (!$seeid) ) {
   $newhash{'studenthidden'} = $currentstudenthidden;    $newhash{'studenthidden'} = $currentstudenthidden;
       }        }
         if ($env{'form.hide'}) {
             my $changelast = 0;
             my $newlast;
             ($changelast,$newlast) = &get_discussion_info($idx,%contrib);
             if ($changelast) {
                 &Apache::lonnet::put('discussiontimes',{$symb => $newlast},
                        $env{'course.'.$env{'request.course.id'}.'.domain'},
                        $env{'course.'.$env{'request.course.id'}.'.num'});
             }
         }
       &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,$feedurl,&mt('Changed discussion status').'<br />',        &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',
      '0','0','','',$env{'form.previous'});       '0','0','','',$env{'form.previous'},undef,undef,undef,
                        undef,undef,undef,$group);
         return OK;
     } elsif (($env{'form.like'}) || ($env{'form.unlike'})) {
   # ----------------------------------------------------------------- Like/unlike
         my $entry=$env{'form.like'}?$env{'form.like'}:$env{'form.unlike'};
         my ($symb,$idx)=split(/\:\:\:/,$entry);
         ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
   #
   # Likes and unlikes are in db-file "disclikes" of the course
   # The prefix is the $symb to identify the resource discussion,
   # and the $idx to identify the entry
   #
         my $prefix=$symb.':'.$idx.':';
         my %contrib=&Apache::lonnet::dump('disclikes',
                                           $env{'course.'.$env{'request.course.id'}.'.domain'},
                                           $env{'course.'.$env{'request.course.id'}.'.num'},
                                           '^'.$prefix);
   # Get all who like or unlike this
         my $currentlikers=$contrib{$prefix.'likers'};
         my $currentunlikers=$contrib{$prefix.'unlikers'};
   # Get the current "likes" count
         my $likes=$contrib{$prefix.'likes'};
   # Find out if they already voted
   # Users cannot like a post twice, or unlike it twice. They can change their mind, though
         my $alreadyflag=0;
         my $thisuser=$env{'user.name'}.':'.$env{'user.domain'};
         if ($env{'form.like'}) {
             if ($currentlikers=~/\,\Q$thisuser\E\,/) {
                 $alreadyflag=1;
             } else {
                 if ($currentunlikers=~/\,\Q$thisuser\E\,/) {
                     $currentunlikers=~s/\,\Q$thisuser\E\,//g;
                 } else {
                     $currentlikers.=','.$thisuser.',';
                 }
                 $likes++;
             } 
         } else {
             if ($currentunlikers=~/\,\Q$thisuser\E\,/) {
                 $alreadyflag=1;
             } else {
                 if ($currentlikers=~/\,\Q$thisuser\E\,/) {
                     $currentlikers=~s/\,\Q$thisuser\E\,//g;
                 } else {
                     $currentunlikers.=','.$thisuser.',';
                 }
                 $likes--;
             } 
         }
         my $result;
   # $alreadyflag would be 1 if they tried to double-like or double-unlike
         unless ($alreadyflag) {
             my %newhash=($prefix.'likes'    => $likes,
                          $prefix.'likers'   => $currentlikers,
                          $prefix.'unlikers' => $currentunlikers);
   # Store data in db-file "disclikes"
             if (&Apache::lonnet::put('disclikes',
                                      \%newhash,
                                      $env{'course.'.$env{'request.course.id'}.'.domain'},
                                      $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
   # Also store with the person who posted the liked/unliked entry
                 if ($env{'form.like'}) {
                     &storediscussionlikes(1,$contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'});
                     $result=&mt("Registered 'Like'");
                 } else {
                     &storediscussionlikes(-1,$contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'});
                     $result=&mt("Registered 'Unlike'");
                 }
             } else {
   # Oops, something went wrong
                 $result=&mt("Failed to register vote");
             }
         }
         &redirect_back($r,$feedurl,$result.'<br />',
                        '0','0','','',$env{'form.previous'},undef,undef,undef,
                        undef,undef,undef,$group);
       return OK;        return OK;
   } elsif ($env{'form.cmd'}=~/^(threadedoff|threadedon)$/) {    } elsif ($env{'form.cmd'}=~/^(threadedoff|threadedon)$/) {
       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});        my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
       if ($env{'form.cmd'} eq 'threadedon') {        if ($env{'form.cmd'} eq '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');
       }        }
       &redirect_back($r,$feedurl,&mt('Changed discussion view mode').'<br />',        &redirect_back($r,$feedurl,&mt('Changed discussion view mode').'<br />',
      '0','0','','',$env{'form.previous'});       '0','0','','',$env{'form.previous'},undef,undef,undef,
                        undef,undef,undef,$group);
       return OK;        return OK;
   } elsif ($env{'form.deldisc'}) {    } elsif ($env{'form.deldisc'}) {
 # --------------------------------------------------------------- Hide for good  # --------------------------------------------------------------- Hide for good
Line 3250  ENDREDIR Line 4049  ENDREDIR
       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},        my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                           $env{'course.'.$env{'request.course.id'}.'.domain'},                            $env{'course.'.$env{'request.course.id'}.'.domain'},
           $env{'course.'.$env{'request.course.id'}.'.num'});            $env{'course.'.$env{'request.course.id'}.'.num'});
         my ($changelast,$newlast) = &get_discussion_info($idx,%contrib);
         if ($changelast) {
             &Apache::lonnet::put('discussiontimes',{$symb => $newlast},
                      $env{'course.'.$env{'request.course.id'}.'.domain'},                   $env{'course.'.$env{'request.course.id'}.'.num'});
         }
       my %newhash=('deleted' => $contrib{'deleted'}.".$idx.");        my %newhash=('deleted' => $contrib{'deleted'}.".$idx.");
       &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,$feedurl,&mt('Changed discussion status').'<br />',        &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',
      '0','0','','',$env{'form.previous'});       '0','0','','',$env{'form.previous'},undef,undef,undef,
                        undef,undef,undef,$group);
       return OK;        return OK;
   } elsif ($env{'form.preview'}) {    } elsif ($env{'form.preview'}) {
 # -------------------------------------------------------- User wants a preview  # -------------------------------------------------------- User wants a preview
Line 3265  ENDREDIR Line 4070  ENDREDIR
 # -------------------------------------------------------- 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','blog']);        &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','addnewattach','delnewattach','timestamp','numoldver','idx','discuss','blog']);
       my (@currnewattach,@currdelold,@keepold);        my (@currnewattach,@currdelold,@keepold,$toolarge);
       &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) {            if (length($env{'form.addnewattach'})<=$attachmax{'num'}) {
               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);
             } else {
                 $toolarge = '<p><span class="LC_warning">'.&mt('Attachment not included - exceeded permitted length').'</span><br /></p>';
           }            }
       }        }
       my $attachmenturls;        my $attachmenturls;
Line 3285  ENDREDIR Line 4092  ENDREDIR
           $attachmenturls = $contrib{$idx.':attachmenturl'};            $attachmenturls = $contrib{$idx.':attachmenturl'};
       }        }
       &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,        &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,
   $attachmenturls);    $attachmenturls,$attachmax{'text'},$toolarge);
       return OK;        return OK;
   } elsif ($env{'form.export'}) {    } elsif ($env{'form.export'}) {
       &Apache::loncommon::content_type($r,'text/html');        &Apache::loncommon::content_type($r,'text/html');
Line 3294  ENDREDIR Line 4101  ENDREDIR
       my $mode='board';        my $mode='board';
       my $status='OPEN';        my $status='OPEN';
       my $previous=$env{'form.previous'};        my $previous=$env{'form.previous'};
       if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {        if ($feedurl =~ /$LONCAPA::assess_re/) {
           $mode='problem';            $mode='problem';
           $status=$Apache::inputtags::status[-1];            $status=$Apache::inputtags::status[-1];
       }        }
       my $discussion = &list_discussion($mode,$status,$symb);         my $discussion = &list_discussion($mode,$status,$symb); 
       my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion');        my $start_page = 
       $r->print($bodytag.$discussion);                                         &Apache::loncommon::start_page('Resource Feedback and Discussion');
         my $end_page = 
     &Apache::loncommon::end_page();
         $r->print($start_page.$discussion.$end_page);
         return OK;
   
     } elsif ($env{'form.undeleteall'}) {
         &Apache::loncommon::content_type($r,'text/html');
         $r->send_http_header;
         my ($symb,$feedurl) = &get_feedurl_and_clean_symb($env{'form.undeleteall'});
         $r->print(&Apache::loncommon::start_page('Undelete all deleted discussion entries'));
         if (&Apache::lonnet::allowed('rin',$env{'request.course.id'})) {
              if (&Apache::lonnet::store({'deleted' => ''},$symb,$env{'request.course.id'},
                        $env{'course.'.$env{'request.course.id'}.'.domain'},
                        $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
                  $r->print(&Apache::lonhtmlcommon::confirm_success(&mt("Undeleted all entries")));
              } else {
                  $r->print(&Apache::lonhtmlcommon::confirm_success(&mt("Failed to undelete entries"),1));
              }
              $r->print("<br /><a href='$feedurl'>".&mt("Return and reload")."</a>");
         }
         $r->print(&Apache::loncommon::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/^https?\:\/\///;
       $feedurl=~s/^$ENV{'SERVER_NAME'}//;        $feedurl=~s/^$ENV{'SERVER_NAME'}//;
       $feedurl=~s/^$ENV{'HTTP_HOST'}//;        $feedurl=~s/^$ENV{'HTTP_HOST'}//;
       $feedurl=~s/\?.+$//;        $feedurl=~s/\?.+$//;
Line 3313  ENDREDIR Line 4141  ENDREDIR
       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'}) {        } elsif ($env{'form.editdisc'}) {
   $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];    $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
   my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);  
   $feedurl=&Apache::lonnet::clutter($url);  
       } elsif ($env{'form.origpage'}) {        } elsif ($env{'form.origpage'}) {
   $symb="";     $symb=""; 
         } elsif ($env{'form.sendmessageonly'}) {
             $symb=(split(/\:\:\:/,$env{'form.sendmessageonly'}))[0];
       } else {        } else {
   $symb=&Apache::lonnet::symbread($feedurl);    $symb=&Apache::lonnet::symbread($feedurl);
       }        }
       unless ($symb) {        unless ($symb) {
   $symb=$env{'form.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);        if (defined($symb)) {
             ($symb,$feedurl)=&get_feedurl_and_clean_symb($symb);
         } else {
             # backward compatibility (bulletin boards used to be 'wrapped')
             &Apache::lonenc::check_decrypt(\$feedurl);
             &dewrapper(\$feedurl);
         }
       my $goahead=1;        my $goahead=1;
       if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form|task)$/) {        if ($feedurl=~/$LONCAPA::assess_re/) {
   unless ($symb) { $goahead=0; }    unless ($symb) { $goahead=0; }
       }        }
       # backward compatibility (bulletin boards used to be 'wrapped')  
       &dewrapper(\$feedurl);  
       if (!$goahead) {        if (!$goahead) {
           # Ambiguous Problem Resource            # Ambiguous Problem Resource
   $r->internal_redirect('/adm/ambiguous');    $r->internal_redirect('/adm/ambiguous');
Line 3356  ENDREDIR Line 4182  ENDREDIR
   &Apache::loncommon::content_type($r,'text/html');    &Apache::loncommon::content_type($r,'text/html');
   $r->send_http_header;    $r->send_http_header;
 # Unable to give feedback  # Unable to give feedback
             &Apache::lonenc::check_encrypt(\$feedurl);
   &no_redirect_back($r,$feedurl);    &no_redirect_back($r,$feedurl);
   return OK;    return OK;
       }        }
 # --------------------------------------------------- Print login screen header  # --------------------------------------------------- Print login screen header
       unless ($env{'form.sendit'}) {        unless ($env{'form.sendit'}) {
             &Apache::lonenc::check_encrypt(\$feedurl);
   &Apache::loncommon::content_type($r,'text/html');    &Apache::loncommon::content_type($r,'text/html');
   $r->send_http_header;    $r->send_http_header;
   my $options=&screen_header($feedurl,$symb);            if (($env{'form.replydisc'}) || ($env{'form.editdisc'})) {
                 my ($blocked,$blocktext) = 
                        &Apache::loncommon::blocking_status('boards');
                 if ($blocked) {
                     $r->print(&blocked_reply_or_edit($blocktext));
                     return OK;
                 }
             }
     my $options=&screen_header($feedurl,$symb,$group);
   if ($options) {    if ($options) {
       &mail_screen($r,$feedurl,$options);        &mail_screen($r,$feedurl,$options,$symb,$attachmax{'text'});
   } else {    } else {
       &fail_redirect($r,$feedurl);        &fail_redirect($r,$feedurl);
   }    }
Line 3378  ENDREDIR Line 4214  ENDREDIR
    $env{'request.course.id'});     $env{'request.course.id'});
   
 # Get output from resource  # Get output from resource
         &Apache::lonenc::check_encrypt(\$feedurl);
       my $usersaw=&resource_output($feedurl);        my $usersaw=&resource_output($feedurl);
   
 # 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 $usersymb = &Apache::lonenc::check_encrypt($symb);
                                    $symb,$env{'user.name'},$env{'user.domain'},        my $useranswer=
                    $env{'request.course.id'});            &Apache::loncommon::get_student_answers(
                 $usersymb,$env{'user.name'},$env{'user.domain'},
                 $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='';
         my $toolarge='';
       if (($env{'form.origpage'}) || ($env{'form.editdisc'}) ||        if (($env{'form.origpage'}) || ($env{'form.editdisc'}) ||
   ($env{'form.replydisc'})) {    ($env{'form.replydisc'})) {
   my ($symb,$idx);    my ($symb,$idx);
Line 3406  ENDREDIR Line 4246  ENDREDIR
   $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|;    $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|;
   $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);    $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);
       } elsif ($env{'form.attachment.filename'}) {        } elsif ($env{'form.attachment.filename'}) {
   unless (length($env{'form.attachment'})>131072) {    if (length($env{'form.attachment'})<=$attachmax{'num'}) {
       $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');                my $now = time;
   }                my $subdir = 'feedback/'.$now;
         $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,$subdir);
     } else {
                 $toolarge = '<p><span class="LC_warning">'.&mt('Attachment not included - exceeded permitted length').'</span><br /></p>';
             }
       }        }
 # Filter HTML out of message (could be nasty)  # Filter HTML out of message (could be nasty)
       my $message=&clear_out_html($env{'form.comment'});        my $override;
         if ($env{'form.discuss'} =~ /^(?:author|question|course|policy)$/) {
             $override = 1;
         }
         my $message=&clear_out_html($env{'form.comment'},$override);
   
 # Assemble email  # Assemble email
       my ($email,$citations)=&assemble_email($feedurl,$message,$prevattempts,        my ($email,$citations)=&assemble_email($message,$prevattempts,
      $usersaw,$useranswer);       $usersaw,$useranswer);
     
 # Who gets this?  # Who gets this?
       my ($typestyle,%to) = &decide_receiver($feedurl);        my ($typestyle,%to) = &Apache::lonmsg::decide_receiver($feedurl);
   
 # Actually send mail  # Actually send mail
       my ($status,$numsent)=&send_msg(&clear_out_html($env{'form.subject'}),$feedurl,$email,$citations,        my ($status,$numsent)=&send_msg(&clear_out_html($env{'form.subject'}),
       $attachmenturl,%to);        $feedurl,$email,$citations,
         $attachmenturl,$usersymb,%to);
   
 # Discussion? Store that.  # Discussion? Store that.
   
       my $numpost=0;        my $numpost=0;
       if ($env{'form.discuss'} || $env{'form.anondiscuss'}) {        if (  ($env{'form.discuss'} ne ''
        && $env{'form.discuss'} !~ /^(?:author|question|course|policy)/)
      || $env{'form.anondiscuss'} ne '') {
   my $subject = &clear_out_html($env{'form.subject'});    my $subject = &clear_out_html($env{'form.subject'});
   my $anonmode=(defined($env{'form.anondiscuss'}));    my $anonmode=($env{'form.discuss'} eq 'anon' || $env{'form.anondiscuss'} );
   $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,    $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,
   $subject);    $subject,$group);
   $numpost++;    $numpost++;
       }        }
   
Line 3444  ENDREDIR Line 4294  ENDREDIR
     $env{'user.domain'},      $env{'user.domain'},
     'CourseBlog_'.$env{'request.course.id'},      'CourseBlog_'.$env{'request.course.id'},
     $subject,$message,$feedurl,'public');      $subject,$message,$feedurl,'public');
   $blog='<br />'.&mt('Added to my course blog').'<br />';            if (&Apache::loncommon::course_type() eq 'Community') {
                 $blog='<br />'.&mt('Added to my community blog').'<br />';
             } else {
         $blog='<br />'.&mt('Added to my course blog').'<br />';
             }
       }        }
       
 # Receipt screen and redirect back to where came from  # Receipt screen and redirect back to where came from
       &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$blog,$status,$env{'form.previous'});        &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$blog,$status,$env{'form.previous'},undef,undef,undef,undef,undef,undef,$group,$toolarge);
   }    }
   return OK;    return OK;
   }
   
   sub blocked_reply_or_edit {
       my ($blocktext) = @_;
       return 
         &Apache::loncommon::start_page('Resource Feedback and Discussion').
         $blocktext.'<br /><br /><a href="javascript:history.go(-1)">'.
         &mt('Back to previous page').
         &Apache::loncommon::end_page();
 }   } 
   
 sub wrap_symb {  sub wrap_symb {
Line 3489  sub get_feedurl_and_clean_symb { Line 4352  sub get_feedurl_and_clean_symb {
 }  }
   
 sub editing_allowed {  sub editing_allowed {
       my ($postid,$group) = @_;
       $postid = &unescape($postid);
     my $can_edit = 0;      my $can_edit = 0;
       if ($group ne '') {
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           if ($postid =~ m|^bulletin___\d+___adm/wrapper(/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard)|) {
               if (&check_group_priv($group,'egp') eq 'ok') {
                   $can_edit = 1;
               }
               return $can_edit;
           }     
       } 
     my $cid = $env{'request.course.id'};      my $cid = $env{'request.course.id'};
     my $role = (split(/\./,$env{'request.role'}))[0];      my $role = (split(/\./,$env{'request.role'}))[0];
     my $section = $env{'request.course.sec'};      my $section = $env{'request.course.sec'};
Line 3516  sub editing_allowed { Line 4391  sub editing_allowed {
     return $can_edit;      return $can_edit;
 }  }
   
   sub check_group_priv {
       my ($group,$grp_priv) = @_;
       foreach my $priv ('mdg','vcg') {
           my $checkcourse = $env{'request.course.id'}.
               ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'');
           if (&Apache::lonnet::allowed($priv,$checkcourse)) {
               return 'ok';
           }
       }
       if ($grp_priv && $group ne '') {
           if (&Apache::lonnet::allowed($grp_priv,$env{'request.course.id'}.'/'.$group)) {
               return 'ok';
           }
       }
       return '';
   }
   
   sub group_args { 
       my ($group) = @_;
       if ($group eq '') { return ''; }
       my $extra_args = '&amp;group='.$group;
       if (exists($env{'form.ref'})) {
           $extra_args .= '&amp;ref='.$env{'form.ref'};
       }
       return $extra_args;
   }
   
   sub get_resource_title {
       my ($symb,$feedurl) = @_;
       my ($restitle,$plainurl);
       if (defined($symb)) {
           my $plain_symb = &Apache::lonenc::check_decrypt($symb);
           $restitle = &Apache::lonnet::gettitle($plain_symb);
       }
       if (defined($feedurl)) {
           $plainurl = &Apache::lonenc::check_decrypt($feedurl);
       }
       if (!defined($restitle)) {
           if (defined($feedurl)) {
               $restitle = &Apache::lonnet::gettitle($plainurl);
           }
       }
       if ($plainurl ne $feedurl) {
           my ($plain_filename) = ($plainurl =~ m-/([^/]+)$-);
           if ($plain_filename eq $restitle) {
               $restitle = &mt('Untitled resource');
           }
       }
       if ($restitle eq '') {
           $restitle = &mt('Untitled resource');
       }
       return $restitle;
   }
   
 1;  1;
 __END__  __END__
   
   
   =pod
   
   =head1 NAME
   
   Apache::lonfeedback.pm
   
   =head1 SYNOPSIS
   
   Handles feedback from students to instructors and system administrators.
   
   Provides a screenshot of the current resource, as well as previous attempts if the resource was a homework.
   
   Used by lonmsg.pm.
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   =head1 OVERVIEW
   
   None
   
   =head1 SUBROUTINES
   
   =over
   
   =item discussion_open()
   
   =item discussion_visible()
   
   =item list_discussion()
   
   =item send_feedback_link()
   
   =item send_message_link()
   
   =item action_links_bar()
   
   =item postingform_display()
   
   =item build_posting_display
   
   =item filter_regexp()
   
   =item get_post_contents()
   
   =item replicate_attachments()
   
   =item mail_screen()
   
   =item print_display_options()
   
   =item print_sortfilter_options()
   
   =item print_showposters()
   
   =item get_post_versions()
   
   =item get_post_attachments()
   
   =item fail_redirect()
   
   =item redirect_back()
   
   =item no_redirect_back()
   
   =item screen_header()
   
   =item resource_output()
   
   =item clear_out_html()
   
   =item assemble_email()
   
   =item feedback_available()
   
   =item send_msg()
   
   =item adddiscuss()
   
   =item get_discussion_info()
   
   =item show_preview()
   
   =item newline_to_br()
   
   =item tidy_html()
   
   =item generate_preview_button()
   
   =item modify_attachments()
   
   =item process_attachments()
   
   =item generate_attachments_button()
   
   =item extract_attachments()
   
   =item construct_attachmenturl()
   
   =item add_blog_checkbox()
   
   =item has_discussion()
   
   =item sort_filter_names()
   
   =item handler()
   
   =item blocked_reply_or_edit()
   
   =item wrap_symb()
   
   =item dewrapper()
   
   =item get_feedurl()
   
   =item get_feedurl_and_clean_symb()
   
   =item editing_allowed()
   
   =item check_group_priv()
   
   =item group_args()
   
   =item get_resource_title()
   
   =back
   
   =cut

Removed from v.1.185  
changed lines
  Added in v.1.331


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.