[LON-CAPA-cvs] cvs: loncom /interface lonfeedback.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Wed, 28 Jul 2004 18:50:26 -0000


This is a MIME encoded message

--raeburn1091040626
Content-Type: text/plain

raeburn		Wed Jul 28 14:50:26 2004 EDT

  Modified files:              
    /loncom/interface	lonfeedback.pm 
  Log:
  Allow multiple attachments in discussion posts.  Different edited versions can include different (or the same) attachments.  
  Work still required: clean-up interface, change storage of versioned attachmenturl, message and subject in .db file to XML, add interface for course coordinators (i.e., for lonnet::allowed('rin',$crs)) to display old versions of posts.
  Known issues: Edits are not currently stored for bulletin board posts. 
  
  
--raeburn1091040626
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20040728145026.txt"

Index: loncom/interface/lonfeedback.pm
diff -u loncom/interface/lonfeedback.pm:1.107 loncom/interface/lonfeedback.pm:1.108
--- loncom/interface/lonfeedback.pm:1.107	Tue Jul 27 19:35:34 2004
+++ loncom/interface/lonfeedback.pm	Wed Jul 28 14:50:26 2004
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Feedback
 #
-# $Id: lonfeedback.pm,v 1.107 2004/07/27 23:35:34 www Exp $
+# $Id: lonfeedback.pm,v 1.108 2004/07/28 18:50:26 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -125,7 +125,7 @@
         }
     }
 
-# Get information about students and non-stundents in course for filtering display of posts
+# Get information about students and non-students in course for filtering display of posts
     my %roleshash = ();
     my %roleinfo = ();
     if ($rolefilter) {
@@ -258,22 +258,36 @@
                         $numoldver = 1;
                     } 
                 }
-		my $message=$contrib{$idx.':message'};
+		my ($message,$subject);
+         	if ($idx > 0) {
+                    if ($contrib{$idx.':message'} =~ /.*::::\Q$numoldver\E::::(.+?)$/si) {
+                        $message = $1;
+                    } else {
+                        $message = $contrib{$idx.':message'};
+                    }
+                } else {
+                    $message=$contrib{$idx.':message'};
+                }
+                my $attachmenturls = $contrib{$idx.':attachmenturl'}; 
 		$message=~s/\n/\<br \/\>/g;
-		$message=&Apache::lontexconvert::msgtexconverted($message,undef,$numoldver);
-                my $subject=$contrib{$idx.':subject'};
+		$message=&Apache::lontexconvert::msgtexconverted($message);
+         	if ($idx > 0) {
+                    if ($contrib{$idx.':subject'} =~ /.*::::\Q$numoldver\E::::(.+?)$/si) {
+                        $subject = $1;
+                    } else {
+                        $subject = $contrib{$idx.':subject'};
+                    }
+                } else {
+                    $subject=$contrib{$idx.':subject'};
+                }
                 if (defined($subject)) {
                     $subject=~s/\n/\<br \/\>/g;
-                    $subject=&Apache::lontexconvert::msgtexconverted($subject,undef,$numoldver);
+                    $subject=&Apache::lontexconvert::msgtexconverted($subject);
                 }
-		if ($contrib{$idx.':attachmenturl'}) {
-		    my ($fname)
-                        =($contrib{$idx.':attachmenturl'}=~m|/([^/]+)$|);
-		    &Apache::lonnet::allowuploaded('/adm/feedback',
-					   $contrib{$idx.':attachmenturl'});
-		    $message.='<p>'.&mt('Attachment').
-			': <a href="'.$contrib{$idx.':attachmenturl'}.'"><tt>'.
-			$fname.'</tt></a></p>';
+		if ($attachmenturls) {
+                    my @attachments = ();
+                    my %currattach = ();
+                    &extract_attachments($attachmenturls,$idx,$numoldver,\$message,\@attachments,\%currattach);
 		}
 		if ($message) {
 		    if ($hidden) {
@@ -432,6 +446,7 @@
                     if ($showonlyunread && $prevread > $posttime) {
                         $notshown{$idx} = 1;
                     } else {
+# apply filters
                         my $uname = $contrib{$idx.':sendername'};
                         my $udom = $contrib{$idx.':senderdomain'};
                         my $poster = $uname.':'.$udom;
@@ -741,23 +756,60 @@
 	}
     }
     if ($discussiononly) {
+        my $now = time;
+        my $attachnum = 0;
+        my $newattachmsg = '';
+        my @currnewattach = ();
+        my @currdelold = ();
+        my $comment = '';
+        my $subject = '';
+        if ($ENV{'form.origpage'}) {
+            &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['addnewattach','deloldattach','delnewattach','timestamp','idx','subject','comment']);
+            $subject = &HTML::Entities::encode($ENV{'form.subject'},'<>&"');
+            $comment = &HTML::Entities::encode($ENV{'form.comment'},'<>&"');
+            my @keepold = ();
+            &process_attachments(\@currnewattach,\@currdelold,\@keepold);
+            if (@currnewattach > 0) {
+                $attachnum += @currnewattach;
+            }
+        }
 	$discussion.=(<<ENDDISCUSS);
 <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data">
 <input type="submit" name="discuss" value="Post Discussion" />
 <input type="submit" name="anondiscuss" value="Post Anonymous Discussion" />
 <input type="hidden" name="symb" value="$ressymb" />
 <input type="hidden" name="sendit" value="true" />
-<br />
-<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="" size="30" /><br /><br />
-<textarea name="comment" cols="80" rows="14" wrap="hard"></textarea>
-<p>
-Attachment (128 KB max size): <input type="file" name="attachment" />
-</p>
-</form>
+<input type="hidden" name="timestamp" value="$now" />
+<br /><a name="newpost"></a>
+<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;
 	    $discussion.=&generate_preview_button();
 	}
     } else {
@@ -778,22 +830,62 @@
 
 sub mail_screen {
   my ($r,$feedurl,$options) = @_;
+  if (exists($ENV{'form.origpage'})) {
+      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss']);
+  }
   my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion',
                                           '','onLoad="window.focus();setposttype();"');
   my $title=&Apache::lonnet::gettitle($feedurl);
   if (!$title) { $title = $feedurl; }
   my $quote='';
   my $subject = '';
-  my $oldmessage = '';
+  my $comment = '';
   my $prevtag = '';
   my $parentmsg = '';
-  my $anonscript = (<<END);
+  my ($symb,$idx,$attachmenturls);
+  my $numoldver = 0;
+  my $attachmsg = '';
+  my $newattachmsg = '';
+  my @currnewattach = ();
+  my @currdelold = ();
+  my @keepold = ();
+  my @attachments = ();
+  my %currattach = ();
+  my $attachnum = 0;
+  my $anonchk = (<<END);
+  function anonchk() {
+     if (document.mailform.anondiscuss.checked == true) {
+          document.attachment.anondiscuss.value = '1'
+     }
+     if (document.mailform.discuss.checked == true) {
+          document.attachment.discuss.value = '1'
+     }
+     return
+   }
+END
+  my $anonscript;
+  if (exists($ENV{'form.origpage'})) {
+      $anonscript = (<<END);
   function setposttype() {
+      var anondisc = $ENV{'form.anondiscuss'};
+      var disc = $ENV{'form.discuss'};
+      if (anondisc == 1) {
+          document.mailform.anondiscuss.checked = true
+      }
+      if (disc == 1) {
+          document.mailform.discuss.checked = true
+      }
       return
   }
 END
+  } else {
+      $anonscript = (<<END);
+  function setposttype() {
+      return
+  }
+END
+  }
   if (($ENV{'form.replydisc'}) || ($ENV{'form.editdisc'})) {
-      my ($symb,$idx);
       if ($ENV{'form.replydisc'}) {
           ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'});
       } else {
@@ -804,7 +896,6 @@
 					   $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
       unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {
           if ($ENV{'form.replydisc'}) {
-              my $numoldver = 0;
               if ($contrib{$idx.':history'}) {
                   if ($contrib{$idx.':history'} =~ /:/) {
                       my @oldversions = split/:/,$contrib{$idx.':history'};
@@ -813,37 +904,51 @@
                       $numoldver = 1;
                   }
               }
-	      my $message=$contrib{$idx.':message'};
+              my $message;
+              if ($idx > 0) {
+                  if ($contrib{$idx.':message'} =~ /::::\Q$numoldver\E::::(.+?)$/si) {
+                      $message = $1;
+                  } else {
+                      $message = $contrib{$idx.':message'};
+                  }
+              } else {
+	          $message=$contrib{$idx.':message'};
+              }
 	      $message=~s/\n/\<br \/\>/g;
-	      $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message,undef,$numoldver).'</blockquote>';
+	      $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message).'</blockquote>';
               if ($idx > 0) {
-                  if ($contrib{'subject'} =~ /::::\d+::::(.+)$/si) {
+                  if ($contrib{$idx.':subject'} =~ /::::\Q$numoldver\E::::(.+?)$/si) {
                       $subject = $1;
                   } else {
                       $subject = $contrib{$idx.':subject'};
                   }
                   $subject = 'Re: '.$subject;
               }
+              $subject = &HTML::Entities::encode($subject,'<>&"');
           } else {
-              if ($contrib{$idx.':message'} =~ /::::\d+::::(.+)$/si) {
-                  $oldmessage = $1;
+              $attachmenturls = $contrib{$idx.':attachmenturl'};
+              if ($contrib{$idx.':message'} =~ /.*::::(\d+)::::(.*?)$/si) {
+                  $numoldver = $1;
+                  $comment = $2;
               } else {
-                  $oldmessage = $contrib{$idx.':message'};
+                  $comment = $contrib{$idx.':message'};
               }
-	      $oldmessage=&HTML::Entities::encode($oldmessage,'<>&"');
-              if ($contrib{$idx.':subject'} =~ /::::\d+::::(.+)$/si) {
+              $comment = &HTML::Entities::encode($comment,'<>&"');
+              if ($contrib{$idx.':subject'} =~ /.*::::\d+::::(.+?)$/si) {
                   $subject = $1;
               } else {
                   $subject = $contrib{$idx.':subject'};
               }
+              $subject = &HTML::Entities::encode($subject,'<>&"');
               if (defined($contrib{$idx.':replyto'})) {
                   $parentmsg = $contrib{$idx.':replyto'};
               }
-              my $anonflag = 0;
-              if ($contrib{$idx.':anonymous'}) {
-                  $anonflag = 1;
-              }
-              $anonscript = (<<END);
+              unless (exists($ENV{'form.origpage'})) {
+                  my $anonflag = 0;
+                  if ($contrib{$idx.':anonymous'}) {
+                      $anonflag = 1;
+                  }
+                  $anonscript = (<<END);
   function setposttype () {
       var currtype = $anonflag
       if (currtype == 1) {
@@ -857,12 +962,19 @@
       return
   }
 END
+              }
           }
       }
       if ($ENV{'form.previous'}) {
           $prevtag = '<input type="hidden" name="previous" value="'.$ENV{'form.previous'}.'" />';
       }
   }
+
+  if ($ENV{'form.origpage'}) {
+      $subject = $ENV{'form.subject'};
+      $comment = $ENV{'form.comment'};
+      &process_attachments(\@currnewattach,\@currdelold,\@keepold);
+  }
   my $latexHelp=&Apache::loncommon::helpLatexCheatsheet();
   my $htmlheader=&Apache::lonhtmlcommon::htmlareaheaders();
   my $send=&mt('Send');
@@ -916,6 +1028,7 @@
             alert('Please check a feedback type.');
 	}
     }
+    $anonchk
     $anonscript
 //-->
 </script>
@@ -937,7 +1050,7 @@
 <input type="hidden" name="parentmsg" value ="$parentmsg" />
 END
   }
-  $r->print(<<ENDDOCUMENT);
+  $r->print(<<END);
 Please check at least one of the following feedback types:
 $options<hr />
 $quote
@@ -946,20 +1059,78 @@
 $latexHelp
 Title: <input type="text" name="subject" size="30" value="$subject" /></p>
 <p>
-<textarea name="comment" id="comment" cols="60" rows="10" wrap="hard">$oldmessage
+<textarea name="comment" id="comment" cols="60" rows="10" wrap="hard">$comment
 </textarea></p>
 <p>
+END
+    if ( ($ENV{'form.editdisc'}) || ($ENV{'form.replydisc'}) ) {
+        if ($ENV{'form.origpage'}) {
+            foreach (@currnewattach) {
+                $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");
+            }
+            foreach (@currdelold) {
+                $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");
+            }
+        }
+        if ($ENV{'form.editdisc'}) {
+            if ($attachmenturls) {
+                &extract_attachments($attachmenturls,$idx,$numoldver,\$attachmsg,\@attachments,\%currattach,\@currdelold);
+                $attachnum = scalar(keys %currattach);
+                foreach (keys %currattach) {
+                    $r->print('<input type="hidden" name="keepold" value="'.$_.'" />'."\n");
+                }
+            }
+        }
+    } else {
+        $r->print(<<END);
 Attachment (128 KB max size): <input type="file" name="attachment" />
 </p>
+END
+    }
+    $r->print(<<END);
 <p>
 <input type="hidden" name="sendit" value="1" />
 <input type="button" value="$send" onClick='gosubmit();' />
 </p>
 </form>
-ENDDOCUMENT
-$r->print(&generate_preview_button().
-&Apache::lonhtmlcommon::htmlareaselectactive('comment').
-'</body></html>');
+END
+    if ($ENV{'form.editdisc'} || $ENV{'form.replydisc'}) {
+        my $now = time;
+        my $ressymb = $symb;
+        my $postidx = '';
+        if ($ENV{'form.editdisc'}) {
+            $postidx = $idx;
+        }
+        if (@currnewattach > 0) {
+            $attachnum += @currnewattach;
+        }
+        $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver));
+        if ($attachnum > 0) {
+            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";
+                }
+            }
+            if ($attachmsg) {
+                $r->print("<b>Retained attachments</b>:$attachmsg<br />\n");
+            }
+            if ($newattachmsg) {
+                $r->print("$newattachmsg<br />");
+            }
+        }
+    }
+    $r->print(&generate_preview_button().
+              &Apache::lonhtmlcommon::htmlareaselectactive('comment').
+              '</body></html>');
 }
 
 sub print_display_options {
@@ -1698,11 +1869,20 @@
                 }
                 $contrib{'history'} = $oldcontrib{$oldidx.':history'}.':';
             }
+            my $numnewver = $numoldver + 1;
             if (defined($oldcontrib{$oldidx.':subject'})) {
-                $contrib{'subject'} = $oldcontrib{$oldidx.':subject'}.'::::'.$numoldver.'::::'.$contrib{'subject'};            
+                if ($oldcontrib{$oldidx.':subject'} =~ /::::\d+::::/) {
+                    $contrib{'subject'} = $oldcontrib{$oldidx.':subject'}.'::::'.$numnewver.'::::'.$contrib{'subject'};
+                } else {
+                     $contrib{'subject'} = '::::0::::'.$oldcontrib{$oldidx.':subject'}.'::::1::::'.$contrib{'subject'};
+                }
             } 
             if (defined($oldcontrib{$oldidx.':message'})) {
-                $contrib{'message'} = $oldcontrib{$oldidx.':message'}.'::::'.$numoldver.'::::'.$contrib{'message'};
+                if ($oldcontrib{$oldidx.':message'} =~ /::::\d+::::/) {
+                    $contrib{'message'} = $oldcontrib{$oldidx.':message'}.'::::'.$numnewver.'::::'.$contrib{'message'};
+                } else {
+                    $contrib{'message'} = '::::0::::'.$oldcontrib{$oldidx.':message'}.'::::1::::'.$contrib{'message'};
+                }
             }
             $contrib{'history'} .= $oldcontrib{$oldidx.':timestamp'};
             foreach (keys %contrib) {
@@ -1769,6 +1949,300 @@
 ENDPREVIEW
 }
 
+sub modify_attachments {
+    my ($r,$currnewattach,$currdelold,$symb,$idx,$attachmenturls)=@_;
+    my $subject=&clear_out_html($ENV{'form.subject'});
+    $subject=~s/\n/\<br \/\>/g;
+    $subject=&Apache::lontexconvert::msgtexconverted($subject);
+    my $timestamp=$ENV{'form.timestamp'};
+    my $numoldver=$ENV{'form.numoldver'};
+    my $bodytag=&Apache::loncommon::bodytag('Discussion Post Attachments',
+                                          '','');
+    my $msg = '';
+    my @attachments = ();
+    my %currattach = ();
+    if ($idx) {
+        &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\@attachments,\%currattach,$currdelold);
+    }
+    $r->print(<<END);
+<html>
+<head>
+<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">
+ <table border="2">
+  <tr>
+   <td>
+    <b>Subject:</b>$subject</b><br /><br />
+END
+    if ($idx) {
+        if ($attachmenturls) {
+            my @currold = keys %currattach;
+            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");  
+                foreach (@currold) {
+                    my $id = $_;
+                    $attachments[$id] =~ m#/([^/]+)$#;
+                    $r->print('<input type="checkbox" name="deloldattach" value="'.$_.'" />&nbsp;'.$1.'<br />'."\n");
+                }
+                $r->print("<br />");
+            }
+        }
+    }
+    if (@{$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");
+        foreach (@{$currnewattach}) {
+            $_ =~ m#/([^/]+)$#;
+            $r->print('<input type="checkbox" name="delnewattach" value="'.$_.'" />&nbsp;'.$1.'<br />'."\n");
+        }
+        $r->print("<br />"); 
+    }
+    $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>
+ </table>
+<input type="hidden" name="subject" value="$ENV{'form.subject'}" />
+<input type="hidden" name="comment" value="$ENV{'form.comment'}" />
+<input type="hidden" name="timestamp" value="$ENV{'form.timestamp'}" />
+<input type="hidden" name="idx" value="$ENV{'form.idx'}" />
+<input type="hidden" name="numoldver" value="$ENV{'form.numoldver'}" />
+<input type="hidden" name="origpage" value="$ENV{'form.origpage'}" />
+<input type="hidden" name="anondiscuss" value="$ENV{'form.anondiscuss'}" />
+<input type="hidden" name="discuss" value="$ENV{'form.discuss'}" />
+END
+    foreach (@{$currnewattach}) {
+        $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");
+    }
+    foreach (@{$currdelold}) {
+        $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");
+    }
+    $r->print(<<END);
+ <input type="button" name="rtntoedit" value="Store Changes" onClick="setAction()"/>
+</form>
+</body>
+</html>
+END
+    return;
+}
+
+sub process_attachments {
+    my ($currnewattach,$currdelold,$keepold) = @_;
+    if (exists($ENV{'form.currnewattach'})) {
+        if (ref($ENV{'form.currnewattach'}) eq 'ARRAY') {
+            @{$currnewattach} = @{$ENV{'form.currnewattach'}};
+        } else {
+            $$currnewattach[0] = $ENV{'form.currnewattach'};
+        }
+    }
+    if (exists($ENV{'form.deloldattach'})) {
+        if (ref($ENV{'form.deloldattach'}) eq 'ARRAY') {
+            @{$currdelold} = @{$ENV{'form.deloldattach'}};
+        } else {
+            $$currdelold[0] = $ENV{'form.deloldattach'};
+        }
+    }
+    if (exists($ENV{'form.delnewattach'})) {
+        my @currdelnew = ();
+        my @currnew = ();
+        if (ref($ENV{'form.delnewattach'}) eq 'ARRAY') {
+            @currdelnew = @{$ENV{'form.delnewattach'}};
+        } else {
+            $currdelnew[0] = $ENV{'form.delnewattach'};
+        }
+        foreach my $newone (@{$currnewattach}) {
+            my $delflag = 0;
+            foreach (@currdelnew) {
+                if ($newone eq $_) {
+                    $delflag = 1;
+                    last;
+                }
+            }
+            unless ($delflag) {
+                push @currnew, $newone;
+            }
+        }
+        @{$currnewattach} = @currnew;
+    }
+    if (exists($ENV{'form.keepold'})) {
+        if (ref($ENV{'form.keepold'}) eq 'ARRAY') {
+            @{$keepold} = @{$ENV{'form.keepold'}};
+        } else {
+            $$keepold[0] = $ENV{'form.keepold'};
+        }
+    }
+}
+
+sub generate_attachments_button {
+    my ($idx,$attachnum,$ressymb,$now,$currnewattach,$deloldattach,$numoldver,$mode) = @_;
+    my $origpage = $ENV{'REQUEST_URI'};
+    my $att=$attachnum.' '.&mt("attachments");
+    my $response = (<<END);
+<form name="attachment" action="/adm/feedback?attach=$ressymb" method="post">
+Click to add/remove attachments:&nbsp;<input type="button" value="$att"
+onClick="this.form.subject.value=document.mailform.subject.value;this.form.comment.value=document.mailform.comment.value;
+END
+    unless ($mode eq 'board') {
+        $response .= 'javascript:anonchk();';
+    }
+    $response .= (<<ENDATTACH);
+this.form.submit();" />
+<input type="hidden" name="origpage" value="$origpage" />
+<input type="hidden" name="idx" value="$idx" />
+<input type="hidden" name="timestamp" value="$now" />
+<input type="hidden" name="subject" />
+<input type="hidden" name="comment" />
+<input type="hidden" name="anondiscuss" value = "0";
+<input type="hidden" name="discuss" value = "0";
+<input type="hidden" name="numoldver" value="$numoldver" />
+ENDATTACH
+    if (defined($deloldattach)) {
+        if (@{$deloldattach} > 0) {
+            foreach (@{$deloldattach}) {
+                $response .= '<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n";
+            }
+        }
+    }
+    if (defined($currnewattach)) {
+        if (@{$currnewattach} > 0) {
+            foreach (@{$currnewattach}) {
+                $response .= '<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";
+            }
+        }
+    }
+    $response .= '</form>';
+    return $response;
+}
+
+sub extract_attachments {
+    my ($attachmenturls,$idx,$numoldver,$message,$attachments,$currattach,$currdelold) = @_;
+    if ($attachmenturls =~ m/::::\d+:[\.yn\d]+::::/) {
+        @{$attachments} = split/::::\d+:[\.yn\d]+::::/,$attachmenturls;
+        shift @{$attachments};
+        my $searchstr = '::::';
+        for (my $i=0; $i<@{$attachments}; $i++) {
+            if ($attachmenturls =~ m#^\Q$searchstr\E(\d+)(:[\.yn\d]+)::::#) {
+                my $info = $1.$2;
+                my $attachid = $1-1;
+                $searchstr .= $info.'::::'.$$attachments[$i].'::::';
+                if ($info =~ /\.$numoldver([yn])\./) {
+                    if (defined($currdelold)) {
+                        if (@{$currdelold} > 0) {
+                            unless (grep/^$attachid$/,@{$currdelold}) {
+                                my $id = $i;
+                                $$currattach{$id} = $1;
+                            }
+                        } else {
+                            my $id = $i;
+                            $$currattach{$id} = $1;
+                        }
+                    } else {
+                        my $id = $i;
+                        $$currattach{$id} = $1;
+                    }
+                }
+            }
+        }
+        my @attached = (sort { $a <=> $b } keys %{$currattach});
+        if (@attached == 1) {
+            my $id = $attached[0];
+            $$attachments[$attached[0]]=~m|/([^/]+)$|;
+            $$message.='<br /><a href="'.$$attachments[$id].'"><tt>'.
+            $1.'</tt></a><br />';
+            &Apache::lonnet::allowuploaded('/adm/feedback',
+                                   $$attachments[$id]);
+        } elsif (@attached > 1) {
+            $$message.='<ol>';
+            foreach (@attached) {
+                my $id = $_;
+                my ($fname)
+                  =($$attachments[$id]=~m|/([^/]+)$|);
+                $$message .= '<li><a href="'.$$attachments[$id].
+                  '"><tt>'.
+                  $fname.'</tt></a></li>';
+                &Apache::lonnet::allowuploaded('/adm/feedback',
+                                 $$attachments[$id]);
+            }
+            $$message .= '</ol><br />';
+        }
+    } else {
+        my ($fname)
+           =($attachmenturls=~m|/([^/]+)$|);
+        $$message .='<p>'.&mt('Attachment').
+           ': <a href="'.$attachmenturls.
+           '"><tt>'.
+           $fname.'</tt></a></p>';
+           $$attachments[0] = $attachmenturls;
+           $$currattach{'0'} = 'n';
+           &Apache::lonnet::allowuploaded('/adm/feedback',
+                             $attachmenturls);
+    }
+}
+
+sub construct_attachmenturl {
+    my ($currnewattach,$keepold,$symb,$idx)=@_;
+    my $oldattachmenturl;
+    my $newattachmenturl;
+    my $startnum = 1;
+    my $currver = 0;
+    if (($ENV{'form.editdisc'}) && ($idx)) {
+        my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
+                       $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+                       $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+        $oldattachmenturl = $contrib{$idx.':attachmenturl'};
+        if ($contrib{$idx.':history'}) {
+            if ($contrib{$idx.':history'} =~ /:/) {
+                my @oldversions = split/:/,$contrib{$idx.':history'};
+                $currver = 1 + scalar(@oldversions);
+            } else {
+                $currver = 2;
+            }
+        } else {
+            $currver = 1;
+        }
+        if ($oldattachmenturl) {
+            if ($oldattachmenturl =~ m/::::\d+:[\.yn\d]+::::/) {
+                my @attachments = split/::::\d+:[\.yn\d]+::::/,$oldattachmenturl;
+                shift @attachments;
+                $startnum += @attachments;
+                my $searchstr = '::::';
+                $newattachmenturl = '::::';
+                for (my $i=0; $i<@attachments; $i++) {
+                    if ($oldattachmenturl =~ m#^\Q$searchstr\E(\d+)(:[\.yn\d]+)::::#) {
+                        my $attachid = $1 - 1;
+                        $searchstr .= $1.$2.'::::'.$attachments[$i].'::::';
+                        $newattachmenturl .= $1.$2;
+                        if (grep/^$attachid$/,@{$keepold}) {
+                            $newattachmenturl .= '.'.$currver.'n.';
+                        }
+                        $newattachmenturl .= '::::'.$attachments[$i].'::::';
+                    }
+                }
+                $newattachmenturl =~ s/::::$//;
+            } else {
+                $newattachmenturl = '::::1:.0n.';
+                unless (grep/^0$/,@{$keepold}) {
+                    $newattachmenturl .= '.1n.';
+                }
+                $newattachmenturl .= '::::'.$oldattachmenturl;
+                $startnum ++;
+            }
+        }
+    }
+    for (my $i=0; $i<@{$currnewattach}; $i++) {
+        my $attachnum = $startnum + $i;
+        $newattachmenturl .= '::::'.$attachnum.':.'.$currver.'n.::::'.$$currnewattach[$i];
+    }
+    return $newattachmenturl; 
+}
+  
 sub handler {
   my $r = shift;
   if ($r->header_only) {
@@ -1780,7 +2254,7 @@
 # --------------------------- Get query string for limited number of parameters
 
   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-         ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','threadedon','threadedoff','onlyunread','allposts','previous','markread','markonread','markondisp','modifydisp','changes','navmaps','navurl','sortfilter','sortposts','applysort','rolefilter','statusfilter','sectionpick','posterlist','userpick']);
+         ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','threadedon','threadedoff','onlyunread','allposts','previous','markread','markonread','markondisp','modifydisp','changes','navmaps','navurl','sortfilter','sortposts','applysort','rolefilter','statusfilter','sectionpick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold']);
   if ($ENV{'form.posterlist'}) {
       &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;
@@ -2074,6 +2548,32 @@
       $r->content_type('text/html');
       $r->send_http_header;
       &show_preview($r);
+  } elsif ($ENV{'form.attach'}) {
+# -------------------------------------------------------- Work on attachments
+      &Apache::loncommon::content_type($r,'text/html');
+      $r->send_http_header;
+      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','addnewattach','delnewattach','timestamp','numoldver','idx','anondiscuss','discuss']);
+      my @currnewattach = ();
+      my @currdelold = ();
+      my @keepold = ();
+      &process_attachments(\@currnewattach,\@currdelold,\@keepold);
+      if (exists($ENV{'form.addnewattach.filename'})) {
+          unless (length($ENV{'form.addnewattach'})>131072) {
+              my $subdir = 'feedback/'.$ENV{'form.timestamp'};
+              my $newattachment=&Apache::lonnet::userfileupload('addnewattach',undef,$subdir);
+              push @currnewattach, $newattachment;
+          }
+      }
+      my $attachmenturls = '';
+      my $idx = $ENV{'form.idx'};
+      my $symb = $ENV{'form.attach'};
+      if ($idx) {
+          my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
+                         $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+                         $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+          $attachmenturls = $contrib{$idx.':attachmenturl'};
+      }
+      &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,$attachmenturls);
   } else {
 # ------------------------------------------------------------- Normal feedback
   my $feedurl=$ENV{'form.postdata'};
@@ -2091,6 +2591,8 @@
       $symb=(split(/\:\:\:/,$ENV{'form.editdisc'}))[0];
       my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
       $feedurl=&Apache::lonnet::clutter($url);
+  } elsif ($ENV{'form.origpage'}) {
+      $symb=""; 
   } else {
       $symb=&Apache::lonnet::symbread($feedurl);
   }
@@ -2127,7 +2629,7 @@
     unless ($ENV{'form.sendit'}) {
       my $options=&screen_header($feedurl);
       if ($options) {
-	&mail_screen($r,$feedurl,$options);
+        &mail_screen($r,$feedurl,$options);
       } else {
 	&fail_redirect($r,$feedurl);
       }
@@ -2149,7 +2651,21 @@
       &Apache::lonnet::delenv('allowed.vgr');
 # Get attachments, if any, and not too large
       my $attachmenturl='';
-      if ($ENV{'form.attachment.filename'}) {
+      if (($ENV{'form.origpage'}) || ($ENV{'form.editdisc'}) || ($ENV{'form.replydisc'})) {
+          my ($symb,$idx);
+          if ($ENV{'form.replydisc'}) {
+              ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'});
+          } elsif ($ENV{'form.editdisc'}) {
+              ($symb,$idx)=split(/\:\:\:/,$ENV{'form.editdisc'});
+          } elsif ($ENV{'form.origpage'}) {
+              $symb = $ENV{'form.symb'};
+          }
+          my @currnewattach = ();
+          my @deloldattach = ();
+          my @keepold = ();
+          &process_attachments(\@currnewattach,\@deloldattach,\@keepold);
+          $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);
+      } elsif ($ENV{'form.attachment.filename'}) {
 	  unless (length($ENV{'form.attachment'})>131072) {
 	      $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');
 	  }

--raeburn1091040626--