--- loncom/interface/lonfeedback.pm	2006/12/05 02:55:52	1.226
+++ loncom/interface/lonfeedback.pm	2007/02/28 16:30:40	1.244
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Feedback
 #
-# $Id: lonfeedback.pm,v 1.226 2006/12/05 02:55:52 albertel Exp $
+# $Id: lonfeedback.pm,v 1.244 2007/02/28 16:30:40 www Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -74,6 +74,9 @@ sub discussion_visible {
 
 sub list_discussion {
     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'};
     if (defined($env{'form.export'})) {
 	if($env{'form.export'}) {
@@ -85,16 +88,26 @@ sub list_discussion {
             $outputtarget = 'export';
         }
     }
-    if (not &discussion_visible($status)) { return ''; }
+    if (not &discussion_visible($status)) {
+        if ($mode ne 'board') {
+            &Apache::lonenc::check_encrypt(\$ressymb); 
+            return &send_message_link($ressymb);
+        }
+    }
     if ($group ne '' && $mode eq 'board') {
         if (&check_group_priv($group,'vgb') ne 'ok') {
             return '';
         }
     }
 
-    my ($blocked,$blocktext) = &blocking_posts('boards',1);
+    my ($blocked,$blocktext) = 
+        &Apache::loncommon::blocking_status('boards');
     if ($blocked) {
-        return $blocktext;
+        &Apache::lonenc::check_encrypt(\$ressymb);
+        if ($mode ne 'board') {
+            $blocktext.='<br />'.&send_message_link($ressymb);
+        }
+        return $blocktext; 
     }
 
     my @bgcols = ("#cccccc","#eeeeee");
@@ -107,9 +120,6 @@ sub list_discussion {
 	$crs.='_'.$env{'request.course.sec'};
     }
     $crs=~s/\_/\//g;
-    unless ($ressymb) {	$ressymb=&Apache::lonnet::symbread(); }
-    unless ($ressymb) { return ''; }
-    $ressymb=&wrap_symb($ressymb);
     my $encsymb=&Apache::lonenc::check_encrypt($ressymb);
     my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
 		  && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form|task)$/));
@@ -722,26 +732,45 @@ END
             }
 	}
     } else {
-	$discussion.='<table bgcolor="#BBBBBB"><tr><td>';
+        $discussion.='<table class="LC_feedback_link"><tr><td>';
         if (&discussion_open($status) &&
             &Apache::lonnet::allowed('pch',
     	        $env{'request.course.id'}.
 	        ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
 	    if ($outputtarget ne 'tex') {
-		$discussion.='<a href="/adm/feedback?replydisc='.
-		    &escape($ressymb).':::" '.$target.'>'.
-		    '<img alt="" src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" border="0" />'.
-		    &mt('Post Discussion').'</a><br />';
+		$discussion.= &send_feedback_link($ressymb,$target).
+                              '<br />';
             }
 	}
-	$discussion.='<a href="/adm/feedback?sendmessageonly=1&amp;symb='.
-	    &escape($ressymb).
-	    '"><img alt="" src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').'" border="0" />'.
-		    &mt('Send Message').'</a></td></tr></table>';
+        if ($outputtarget ne 'tex') {
+	    $discussion.= &send_message_link($ressymb);
+        }
+        $discussion.='</td></tr></table>';
     }
     return $discussion;
 }
 
+sub send_feedback_link {
+    my ($ressymb,$target) = @_;
+    my $output = '<span class="LC_feedback_link">'.
+                 ' <a href="/adm/feedback?replydisc='.
+                 &escape($ressymb).':::" '.$target.'>'.
+                 '<img alt="" src="'.
+                 &Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').
+                 '" border="0" />'.&mt('Post Discussion').'</a></span>';
+    return $output;
+}
+
+sub send_message_link {
+    my ($ressymb) = @_;
+    my $output = '<span class="LC_feedback_link">'.
+                 '  <a href="/adm/feedback?sendmessageonly=1&amp;symb='.
+                 &escape($ressymb).'"><img alt="" src="'.
+                 &Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').
+                 '" border="0" />'.&mt('Send Message').'</a></span>';
+    return $output;
+}
+
 sub action_links_bar {
     my ($colspan,$ressymb,$visible,$newpostsflag,$group,$prevread,$markondisp) = @_;
     my $discussion = '<tr><td bgcolor="#DDDDBB" colspan="'.$colspan.'">'.
@@ -795,25 +824,6 @@ sub action_links_bar {
     return $discussion;
 }
 
-sub blocking_posts {
-    my ($type,$showstatus) = @_;
-    my %setters;
-    my ($blocked,$output);
-    my ($startblock,$endblock) =
-          &Apache::loncommon::blockcheck(\%setters,$type);
-    if ($startblock && $endblock) {
-        $blocked = 1;
-        if ($showstatus) {
-            my $showstart = &Apache::lonlocal::locallocaltime($startblock);
-            my $showend = &Apache::lonlocal::locallocaltime($endblock);
-            $output = &mt('Discussion postings will not be viewable for resources in this course between [_1] and [_2] because communication is being blocked.',$showstart, $showend).'<br />'.
-                    &Apache::loncommon::build_block_table($startblock,$endblock,
-                                                         \%setters);
-        }
-    }
-    return ($blocked,$output);
-}
-
 sub postingform_display {
     my ($mode,$ressymb,$now,$subject,$comment,$outputtarget,$attachnum,
         $currnewattach,$currdelold,$group) = @_;
@@ -850,7 +860,7 @@ ENDDISCUSS
     if ($group ne '') {
         $postingform .='<input type="hidden" name="group" value="'.$group.'" />';
     }
-    my ($blockblog) = &blocking_posts('blogs');
+    my $blockblog = &Apache::loncommon::blocking_status('blogs');
     if (!$blockblog) {
         $postingform .= &add_blog_checkbox();
     }
@@ -1002,7 +1012,7 @@ sub build_posting_display {
 			        $sender.=' <font color="red"><b>['.$$anonhash{$key}.']</b></font> '.
 				    $screenname;
 			    }
-
+                            $sender.=&Apache::loncommon::studentimagetag($contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
 # Set up for sorting by domain, then username
                             unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) {
                                 %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = ();
@@ -1458,7 +1468,7 @@ sub replicate_attachments {
 }
 
 sub mail_screen {
-  my ($r,$feedurl,$options) = @_;
+  my ($r,$feedurl,$options,$caller_symb) = @_;
   if (exists($env{'form.origpage'})) {
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss','blog','group','ref']);
   }
@@ -1469,9 +1479,8 @@ sub mail_screen {
             'title' => 'Title',
             'reta' => 'Retained attachments',
             'atta' => 'Attachment (128 KB max size)',
-           ); 
-  my $title=&Apache::lonnet::gettitle($feedurl);
-  if (!$title) { $title = $feedurl; }
+           );
+  my $restitle = &get_resource_title($caller_symb,$feedurl);
   my $quote='';
   my $subject = '';
   my $comment = '';
@@ -1659,7 +1668,7 @@ END
 
   $r->print(<<END);
 $start_page
-<h2><tt>$title</tt></h2>
+<h2><tt>$restitle</tt></h2>
 <form action="/adm/feedback" method="post" name="mailform"
 enctype="multipart/form-data">
 $prevtag
@@ -1728,6 +1737,7 @@ END
     if ($env{'form.editdisc'} || $env{'form.replydisc'}) {
         my $now = time;
         my $ressymb = $symb;
+        &Apache::lonenc::check_encrypt(\$ressymb);
         my $postidx = '';
         if ($env{'form.editdisc'}) {
             $postidx = $idx;
@@ -1735,7 +1745,7 @@ END
         if (@currnewattach > 0) {
             $attachnum += @currnewattach;
         }
-        my ($blockblog) = &blocking_posts('blogs');
+        my $blockblog = &Apache::loncommon::blocking_status('blogs');
         $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver,'',$blockblog));
         if ($attachnum > 0) {
             if (@currnewattach > 0) {
@@ -2471,7 +2481,7 @@ sub redirect_back {
           $feedurl .= '?group='.$group.$refarg;
       }
   } 
-  $feedurl=&Apache::lonenc::check_encrypt($feedurl);
+  &Apache::lonenc::check_encrypt(\$feedurl);
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   my %onload;
   if ($env{'environment.remote'} ne 'off') {
@@ -2528,7 +2538,7 @@ sub no_redirect_back {
 				      
   my $end_page = &Apache::loncommon::end_page();
 
-  $feedurl=&Apache::lonenc::check_encrypt($feedurl);
+  &Apache::lonenc::check_encrypt(\$feedurl);
   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
   $r->print (<<ENDNOREDIRTWO);
 $start_page
@@ -2549,43 +2559,45 @@ sub screen_header {
 		'<p><label><input type="radio" name="discuss" value="author" /> '.
 		&mt('Feedback to resource author').'</label></p>';
 	}
+        my %optionhash=();
+        foreach my $type ('question','comment','policy') {
+	    $optionhash{$type}=$env{'course.'.$env{'request.course.id'}.'.'.$type.'.email.text'};
+	}
 	if (&feedback_available(1)) {
 	    $msgoptions.=
 		'<p><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></p>';
 	}
 	if (&feedback_available(0,1)) {
 	    $msgoptions.=
 		'<p><label><input type="radio" name="discuss" value="course" /> '.
-		&mt('Question/Comment/Feedback about course content').
+		($optionhash{'comment'}?$optionhash{'comment'}:&mt('Question/Comment/Feedback about course content')).
 		'</label></p>';
 	}
 	if (&feedback_available(0,0,1)) {
 	    $msgoptions.=
 		'<p><label><input type="radio" name="discuss" value="policy" /> '.
-		&mt('Question/Comment/Feedback about course policy').
+		($optionhash{'policy'}?$optionhash{'policy'}:&mt('Question/Comment/Feedback about course policy')).
 		'</label></p>';
 	}
     }
     if (($env{'request.course.id'}) && (!$env{'form.sendmessageonly'})) {
-	if (&discussion_open(undef,$symb) &&
+        my ($blocked,$blocktext) = &Apache::loncommon::blocking_status('boards');
+        if (!$blocked && &discussion_open(undef,$symb) && 
 	    &Apache::lonnet::allowed('pch',
 				     $env{'request.course.id'}.
 				     ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
-            my ($blocked) = &blocking_posts('boards');
-            if (!$blocked) {
-	        $discussoptions='<label><input type="radio" name="discuss" value="nonanon" checked="checked" /> '.
-		    &mt('Contribution to course discussion of resource');
+	    $discussoptions='<label><input type="radio" name="discuss" value="nonanon" checked="checked" /> '.
+		&mt('Contribution to course discussion of resource');
 	        $discussoptions.='</label><br /><label><input type="radio" name="discuss" value="anon" /> '.
-		    &mt('Anonymous contribution to course discussion of resource').
-		    ' <i>('.&mt('name only visible to course faculty').')</i></label> '.
-		    '<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';
+		&mt('Anonymous contribution to course discussion of resource').
+		' <i>('.&mt('name only visible to course faculty').')</i></label> '.
+		'<a href="/adm/preferences?action=changescreenname">'.&mt('Change Screenname').'</a>';
+            my $blockblog = &Apache::loncommon::blocking_status('blogs');
+            if (!$blockblog) {
+                $discussoptions.= &add_blog_checkbox();
             }
         }
-        my ($blockblog) = &blocking_posts('blogs');
-        if (!$blockblog) {
-            $discussoptions.= &add_blog_checkbox();
-        }
     }
     if ($msgoptions) { $msgoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').'" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }
     if ($discussoptions) { 
@@ -2633,7 +2645,7 @@ sub clear_out_html {
 }
 
 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)',
@@ -2654,117 +2666,26 @@ ENDCITE
   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 my $sec (split(/\;/,$sections)) {
-            if (($sec eq $env{'request.course.sec'}) ||
-                ($defaultflag && ($sec 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.discuss'} eq 'author' ||$author) {
-    $typestyle.='Submitting as Author Feedback<br />';
-    $feedurl=~{^/res/($LONAPA::domain_re)/($LONCAPA::username_re)/};
-    $to{$2.':'.$1}=1;
-  }
-  if ($env{'form.discuss'} eq 'question' ||$question) {
-    $typestyle.=&mt('Submitting as Question').'<br />';
-    foreach my $item (split(/\,/,
-		   $env{'course.'.$env{'request.course.id'}.'.question.email'})
-	     ) {
-	my $rec=&secapply($item,$defaultflag);
-        if ($rec) { $to{$rec}=1; }
-    } 
-  }
-  if ($env{'form.discuss'} eq 'course' ||$course) {
-    $typestyle.=&mt('Submitting as Comment').'<br />';
-    foreach my $item (split(/\,/,
-		   $env{'course.'.$env{'request.course.id'}.'.comment.email'})
-	     ) {
-	my $rec=&secapply($item,$defaultflag);
-        if ($rec) { $to{$rec}=1; }
-    } 
-  }
-  if ($env{'form.discuss'} eq 'policy' ||$policy) {
-    $typestyle.=&mt('Submitting as Policy Feedback').'<br />';
-    foreach my $item (split(/\,/,
-		   $env{'course.'.$env{'request.course.id'}.'.policy.email'})
-	     ) {
-	my $rec=&secapply($item,$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 {
     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);
 }
 
 sub send_msg {
-  my ($title,$feedurl,$email,$citations,$attachmenturl,%to)=@_;
+  my ($title,$feedurl,$email,$citations,$attachmenturl,$symb,%to)=@_;
   my $status='';
   my $sendsomething=0;
+  my $restitle = &get_resource_title($symb,$feedurl);
   if ($title=~/^Error/) { $title=&mt('Feedback').': '.$title; }
   unless ($title=~/\w/) { $title=&mt('Feedback'); }
   foreach my $key (keys(%to)) {
     if ($key) {
-      my $declutter=&Apache::lonnet::declutter($feedurl);
       unless (&Apache::lonmsg::user_normal_msg(split(/\:/,$key),
-               $title.' ['.$declutter.']',$email,$citations,$feedurl,
-                $attachmenturl)=~/ok/) {
+               $title.' ['.$restitle.']',$email,$citations,$feedurl,
+                $attachmenturl,undef,undef,$symb,$restitle)=~/ok/) {
 	$status.='<br />'.&mt('Error sending message to').' '.$key.'<br />';
       } else {
 	$sendsomething++;
@@ -2816,10 +2737,11 @@ sub adddiscuss {
 	$contrib{'anonymous'}='true';
     }
     if (($symb) && ($email)) {
+        my $now = time;
         if ($env{'form.editdisc'}) {
             $contrib{'ip'}=$ENV{'REMOTE_ADDR'};
             $contrib{'host'}=$Apache::lonnet::perlvar{'lonHostID'};
-            $contrib{'timestamp'} = time;
+            $contrib{'timestamp'} = $now;
             $contrib{'history'} = '';
             my $numoldver = 0;
             my ($oldsymb,$oldidx)=split(/\:\:\:/,$env{'form.editdisc'});
@@ -2870,7 +2792,7 @@ sub adddiscuss {
                      $env{'course.'.$env{'request.course.id'}.'.domain'},
 		     $env{'course.'.$env{'request.course.id'}.'.num'});
         }
-        my %storenewentry=($symb => time);
+        my %storenewentry=($symb => $now);
         $status.='<br />'.&mt('Updating discussion time').': '.
         &Apache::lonnet::put('discussiontimes',\%storenewentry,
                      $env{'course.'.$env{'request.course.id'}.'.domain'},
@@ -2891,6 +2813,48 @@ sub adddiscuss {
     return $status.'<br />';   
 }
 
+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
 
 sub show_preview {
@@ -3559,7 +3523,16 @@ ENDREDIR
       if ( ($env{'form.hide'}) && (!$seeid) ) {
 	  $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'},
                            $env{'course.'.$env{'request.course.id'}.'.domain'},
 			   $env{'course.'.$env{'request.course.id'}.'.num'});
@@ -3588,6 +3561,11 @@ ENDREDIR
       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                           $env{'course.'.$env{'request.course.id'}.'.domain'},
 		          $env{'course.'.$env{'request.course.id'}.'.num'});
+      my ($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.");
       &Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},
 			   $env{'course.'.$env{'request.course.id'}.'.domain'},
@@ -3655,12 +3633,8 @@ ENDREDIR
       my $symb;
       if ($env{'form.replydisc'}) {
 	  $symb=(split(/\:\:\:/,$env{'form.replydisc'}))[0];
-	  my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
-	  $feedurl=&Apache::lonnet::clutter($url);
       } elsif ($env{'form.editdisc'}) {
 	  $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
-	  my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
-	  $feedurl=&Apache::lonnet::clutter($url);
       } elsif ($env{'form.origpage'}) {
 	  $symb=""; 
       } else {
@@ -3668,18 +3642,18 @@ ENDREDIR
       }
       unless ($symb) {
 	  $symb=$env{'form.symb'};
-	  if ($symb) {
-	      my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
-	      $feedurl=&Apache::lonnet::clutter($url);
-	  }
       }
-      &Apache::lonenc::check_decrypt(\$symb);
+      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;
       if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form|task)$/) {
 	  unless ($symb) { $goahead=0; }
       }
-      # backward compatibility (bulletin boards used to be 'wrapped')
-      &dewrapper(\$feedurl);
       if (!$goahead) {
           # Ambiguous Problem Resource
 	  $r->internal_redirect('/adm/ambiguous');
@@ -3698,16 +3672,26 @@ ENDREDIR
 	  &Apache::loncommon::content_type($r,'text/html');
 	  $r->send_http_header;
 # Unable to give feedback
+          &Apache::lonenc::check_encrypt(\$feedurl);
 	  &no_redirect_back($r,$feedurl);
 	  return OK;
       }
 # --------------------------------------------------- Print login screen header
       unless ($env{'form.sendit'}) {
+          &Apache::lonenc::check_encrypt(\$feedurl);
 	  &Apache::loncommon::content_type($r,'text/html');
 	  $r->send_http_header;
+          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);
 	  if ($options) {
-	      &mail_screen($r,$feedurl,$options);
+	      &mail_screen($r,$feedurl,$options,$symb);
 	  } else {
 	      &fail_redirect($r,$feedurl);
 	  }
@@ -3720,13 +3704,16 @@ ENDREDIR
 				   $env{'request.course.id'});
 
 # Get output from resource
+      &Apache::lonenc::check_encrypt(\$feedurl);
       my $usersaw=&resource_output($feedurl);
 
 # Get resource answer (need to allow student to view grades for this to work)
       &Apache::lonnet::appenv(('allowed.vgr'=>'F'));
-      my $useranswer=&Apache::loncommon::get_student_answers(
-                                   $symb,$env{'user.name'},$env{'user.domain'},
-		                   $env{'request.course.id'});
+      my $usersymb = &Apache::lonenc::check_encrypt($symb);
+      my $useranswer=
+          &Apache::loncommon::get_student_answers(
+              $usersymb,$env{'user.name'},$env{'user.domain'},
+              $env{'request.course.id'});
       &Apache::lonnet::delenv('allowed.vgr');
 # Get attachments, if any, and not too large
       my $attachmenturl='';
@@ -3756,17 +3743,17 @@ ENDREDIR
       my $message=&clear_out_html($env{'form.comment'});
 
 # Assemble email
-      my ($email,$citations)=&assemble_email($feedurl,$message,$prevattempts,
+      my ($email,$citations)=&assemble_email($message,$prevattempts,
 					     $usersaw,$useranswer);
  
 # Who gets this?
-      my ($typestyle,%to) = &decide_receiver($feedurl);
+      my ($typestyle,%to) = &Apache::lonmsg::decide_receiver($feedurl);
 
 # Actually send mail
       my ($status,$numsent)=&send_msg(&clear_out_html($env{'form.subject'},
 						      undef,1),
 				      $feedurl,$email,$citations,
-				      $attachmenturl,%to);
+				      $attachmenturl,$usersymb,%to);
 
 # Discussion? Store that.
       my $numpost=0;
@@ -3796,6 +3783,15 @@ ENDREDIR
       &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$blog,$status,$env{'form.previous'},undef,undef,undef,undef,undef,undef,$group);
   }
   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 {
@@ -3900,5 +3896,32 @@ sub group_args {
     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;
 __END__