File:
[LON-CAPA] /
loncom /
interface /
lonfeedback.pm
Revision
1.84:
download - view:
text,
annotated -
select for diffs
Tue May 25 22:16:05 2004 UTC (20 years, 4 months ago) by
raeburn
Branches:
MAIN
CVS tags:
HEAD
Interface changes. User can toggle two settings:
1. display all posts/only new posts
2. new posts considered read when (a) users marks as read, or (b) automatically, following
display.
Settings for specific discussion override 'global' user preferences. If no global or local preferences have been set, default is to display all posts, and require user to iclick a link to mark new posts as read.
1: # The LearningOnline Network
2: # Feedback
3: #
4: # $Id: lonfeedback.pm,v 1.84 2004/05/25 22:16:05 raeburn Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: ###
29:
30: package Apache::lonfeedback;
31:
32: use strict;
33: use Apache::Constants qw(:common);
34: use Apache::lonmsg();
35: use Apache::loncommon();
36: use Apache::lontexconvert();
37: use Apache::lonlocal;
38:
39: sub list_discussion {
40: my ($mode,$status,$symb)=@_;
41: # &Apache::lonnet::logthis("status is $status");
42: if (!($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'
43: || $status eq 'OPEN')) {
44: return '';
45: }
46:
47: my @bgcols = ("#cccccc","#eeeeee");
48: my $discussiononly=0;
49: if ($mode eq 'board') { $discussiononly=1; }
50: unless ($ENV{'request.course.id'}) { return ''; }
51: my $crs='/'.$ENV{'request.course.id'};
52: if ($ENV{'request.course.sec'}) {
53: $crs.='_'.$ENV{'request.course.sec'};
54: }
55: $crs=~s/\_/\//g;
56: unless ($symb) {
57: $symb=&Apache::lonnet::symbread();
58: }
59: unless ($symb) { return ''; }
60:
61: # backward compatibility (bulletin boards used to be 'wrapped')
62: my $ressymb=$symb;
63: if ($mode eq 'board') {
64: unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
65: $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;
66: }
67: }
68:
69: # Get discussion display settings for this discussion
70: my $lastkey = $ressymb.'_lastread';
71: my $showkey = $ressymb.'_showonlyunread';
72: my $visitkey = $ressymb.'_visit';
73: my $ondispkey = $ressymb.'_markondisp';
74: my %dischash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$lastkey,$showkey,$visitkey,$ondispkey],$ENV{'user.domain'},$ENV{'user.name'});
75: my %discinfo = ();
76: my $showonlyunread = 0;
77: my $markondisp = 0;
78: my $prevread = 0;
79: my $previous = 0;
80: my $visit = 0;
81: my $newpostsflag = 0;
82:
83: # Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts.
84: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous']);
85: $previous = $ENV{'form.previous'};
86: if ($previous > 0) {
87: $prevread = $previous;
88: } elsif (defined($dischash{$lastkey})) {
89: unless ($dischash{$lastkey} eq '') {
90: $prevread = $dischash{$lastkey};
91: }
92: }
93:
94: # Get discussion display default settings for user
95: my %userenv = &Apache::lonnet::get('environment',['discdisplay','discmarkread'],$ENV{'user.domain'},$ENV{'user.name'});
96: my $discdisplay=$userenv{'discdisplay'};
97: if ($discdisplay eq 'unread') {
98: $showonlyunread = 1;
99: }
100: my $discmarkread=$userenv{'discmarkread'};
101: if ($discmarkread eq 'ondisp') {
102: $markondisp = 1;
103: }
104:
105: # Override user's default if user specified display setting for this discussion
106: if (defined($dischash{$ondispkey})) {
107: $markondisp = $dischash{$ondispkey};
108: }
109: if ($markondisp) {
110: $discinfo{$lastkey} = time;
111: }
112:
113: if (defined($dischash{$showkey})) {
114: $showonlyunread = $dischash{$showkey};
115: }
116:
117: if (defined($dischash{$visitkey})) {
118: $visit = $dischash{$visitkey};
119: }
120: $visit ++;
121:
122: my $seeid=&Apache::lonnet::allowed('rin',$crs);
123: my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
124: && ($symb=~/\.(problem|exam|quiz|assess|survey|form)$/));
125: my @discussionitems=();
126: my %contrib=&Apache::lonnet::restore($ressymb,$ENV{'request.course.id'},
127: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
128: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
129: my $visible=0;
130: my @depth=();
131: my @original=();
132: my @index=();
133: my @replies=();
134: my %alldiscussion=();
135: my %notshown = ();
136: my %newitem = ();
137: my $maxdepth=0;
138:
139: my $target='';
140: unless ($ENV{'browser.interface'} eq 'textual' ||
141: $ENV{'environment.remote'} eq 'off' ) {
142: $target='target="LONcom"';
143: }
144:
145: my $now = time;
146: $discinfo{$visitkey} = $visit;
147:
148: &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
149:
150: if ($contrib{'version'}) {
151: my $oldest = $contrib{'1:timestamp'};
152: if ($prevread eq '0') {
153: $prevread = $oldest-1;
154: }
155: for (my $id=1;$id<=$contrib{'version'};$id++) {
156: my $idx=$id;
157: my $posttime = $contrib{$idx.':timestamp'};
158: if ($prevread <= $posttime) {
159: $newpostsflag = 1;
160: }
161: my $hidden=($contrib{'hidden'}=~/\.$idx\./);
162: my $deleted=($contrib{'deleted'}=~/\.$idx\./);
163: my $origindex='0.';
164: if (($contrib{$idx.':replyto'}) && ($ENV{'environment.threadeddiscussion'})) {
165: # this is a follow-up message
166: $original[$idx]=$original[$contrib{$idx.':replyto'}];
167: $depth[$idx]=$depth[$contrib{$idx.':replyto'}]+1;
168: $origindex=$index[$contrib{$idx.':replyto'}];
169: if ($depth[$idx]>$maxdepth) { $maxdepth=$depth[$idx]; }
170: } else {
171: # this is an original message
172: $original[$idx]=0;
173: $depth[$idx]=0;
174: }
175: if ($replies[$depth[$idx]]) {
176: $replies[$depth[$idx]]++;
177: } else {
178: $replies[$depth[$idx]]=1;
179: }
180: unless ((($hidden) && (!$seeid)) || ($deleted)) {
181: $visible++;
182: my $message=$contrib{$idx.':message'};
183: $message=~s/\n/\<br \/\>/g;
184: $message=&Apache::lontexconvert::msgtexconverted($message);
185: my $subject=$contrib{$idx.':subject'};
186: if (defined($subject)) {
187: $subject=~s/\n/\<br \/\>/g;
188: $subject=&Apache::lontexconvert::msgtexconverted($subject);
189: }
190: if ($contrib{$idx.':attachmenturl'}) {
191: my ($fname)
192: =($contrib{$idx.':attachmenturl'}=~m|/([^/]+)$|);
193: &Apache::lonnet::allowuploaded('/adm/feedback',
194: $contrib{$idx.':attachmenturl'});
195: $message.='<p>'.&mt('Attachment').
196: ': <a href="'.$contrib{$idx.':attachmenturl'}.'"><tt>'.
197: $fname.'</tt></a></p>';
198: }
199: if ($message) {
200: if ($hidden) {
201: $message='<font color="#888888">'.$message.'</font>';
202: }
203: my $screenname=&Apache::loncommon::screenname(
204: $contrib{$idx.':sendername'},
205: $contrib{$idx.':senderdomain'});
206: my $plainname=&Apache::loncommon::nickname(
207: $contrib{$idx.':sendername'},
208: $contrib{$idx.':senderdomain'});
209:
210: my $sender=&mt('Anonymous');
211: if ((!$contrib{$idx.':anonymous'}) || ($seeid)) {
212: $sender=&Apache::loncommon::aboutmewrapper(
213: $plainname,
214: $contrib{$idx.':sendername'},
215: $contrib{$idx.':senderdomain'}).' ('.
216: $contrib{$idx.':sendername'}.' at '.
217: $contrib{$idx.':senderdomain'}.')';
218: if ($contrib{$idx.':anonymous'}) {
219: $sender.=' ['.&mt('anonymous').'] '.
220: $screenname;
221: }
222: if ($seeid) {
223: if ($hidden) {
224: $sender.=' <a href="/adm/feedback?unhide='.
225: $ressymb.':::'.$idx;
226: if ($newpostsflag) {
227: $sender .= '&previous='.$prevread;
228: }
229: $sender .= '">'.&mt('Make Visible').'</a>';
230: } else {
231: $sender.=' <a href="/adm/feedback?hide='.
232: $ressymb.':::'.$idx;
233: if ($newpostsflag) {
234: $sender .= '&previous='.$prevread;
235: }
236: $sender .= '">'.&mt('Hide').'</a>';
237: }
238: $sender.=' <a href="/adm/feedback?deldisc='.
239: $ressymb.':::'.$idx;
240: if ($newpostsflag) {
241: $sender .= '&previous='.$prevread;
242: }
243: $sender .= '">'.&mt('Delete').'</a>';
244: }
245: } else {
246: if ($screenname) {
247: $sender='<i>'.$screenname.'</i>';
248: }
249: }
250: if (&Apache::lonnet::allowed('pch',
251: $ENV{'request.course.id'}.
252: ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) {
253: $sender.=' <a href="/adm/feedback?replydisc='.
254: $ressymb.':::'.$idx;
255: if ($newpostsflag) {
256: $sender .= '&previous='.$prevread;
257: }
258: $sender .= '" '.$target.'>'.&mt('Reply').'</a>';
259: }
260: my $vgrlink;
261: if ($viewgrades) {
262: $vgrlink=&Apache::loncommon::submlink('Submissions',
263: $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$symb);
264: }
265: #figure out at what position this needs to print
266: my $thisindex=$idx;
267: if ($ENV{'environment.threadeddiscussion'}) {
268: $thisindex=$origindex.substr('00'.$replies[$depth[$idx]],-2,2);
269: }
270: $alldiscussion{$thisindex}=$idx;
271: $index[$idx]=$thisindex;
272: my $spansize = 2;
273: if ($showonlyunread && $prevread > $posttime) {
274: $notshown{$idx} = 1;
275: } else {
276: if ($prevread > 0 && $prevread <= $posttime) {
277: $newitem{$idx} = 1;
278: $discussionitems[$idx] .= '
279: <p><table border="0" width="100%">
280: <tr><td align="left"><font color="#FF0000"><b>NEW</b></font></td>';
281: } else {
282: $newitem{$idx} = 0;
283: $discussionitems[$idx] .= '
284: <p><table border="0" width="100%">
285: <tr><td align="left"> </td>';
286: }
287: $discussionitems[$idx] .= '<td align ="left"> '.
288: '<b>'.$subject.'</b> '.
289: $sender.'</b> '.$vgrlink.' ('.
290: localtime($posttime).')</td></tr>'.
291: '</table><blockquote>'.$message.'</blockquote></p>';
292: }
293: }
294: }
295: }
296: }
297:
298: my $discussion='';
299:
300: my $function = &Apache::loncommon::get_users_function();
301: my $color = &Apache::loncommon::designparm($function.'.tabbg',
302: $ENV{'user.domain'});
303: my %lt = &Apache::lonlocal::texthash(
304: 'cuse' => 'Current settings for this discussion',
305: 'allposts' => 'All posts',
306: 'unread' => 'New posts only',
307: 'ondisp' => 'Once displayed',
308: 'onmark' => 'Once marked read',
309: 'disa' => 'Posts to be displayed',
310: 'npce' => 'Posts cease to be marked "NEW"',
311: 'chgt' => 'Change to ',
312: );
313:
314: my $currdisp = $lt{'allposts'};
315: my $currmark = $lt{'onmark'};
316: my $dispchange = $lt{'unread'};
317: my $markchange = $lt{'ondisp'};
318: my $displink = '/adm/feedback?onlyunread='.$ressymb;
319: my $marklink = '/adm/feedback?markondisp='.$ressymb;
320:
321: if ($markondisp) {
322: $currmark = $lt{'ondisp'};
323: $markchange = $lt{'onmark'};
324: $marklink = '/adm/feedback?markonread='.$ressymb;
325: if ($newpostsflag) {
326: $marklink .= '&previous='.$prevread;
327: }
328: }
329:
330: if ($showonlyunread) {
331: $currdisp = $lt{'unread'};
332: $dispchange = $lt{'allposts'};
333: $displink = '/adm/feedback?allposts='.$ressymb;
334: }
335:
336: if ($newpostsflag) {
337: $displink .= '&previous='.$prevread;
338: }
339:
340: if ($visible) {
341: # Print the discusssion
342: $discussion.='<table bgcolor="#AAAAAA" cellpadding="2" cellspacing="2" border="0">';
343: my $colspan=$maxdepth+1;
344: $discussion .= '<tr bgcolor="#FFFFFF"><td colspan="'.$colspan.'" valign="top">'.
345: '<table border="0" bgcolor="#FFFFFF" width="100%" cellspacing="2" cellpadding="2">'.
346: '<tr><td align="left"><b>'.$lt{'cuse'}.'</b></td><td> </td><td align="right"><b>'.$lt{'chgt'}.'</b></td></tr>'.
347: '<tr><td>'.$lt{'disa'}.': <i>'.$currdisp.'</i></td><td> </td><td align="right"><a href="'.$displink.'">'.$dispchange.'</a></td></tr>'.
348: '<tr><td>'.$lt{'npce'}.': <i>'.$currmark.'</i></td><td> </td><td align="right"><a href="'.$marklink.'">'.$markchange.'</a></td></tr>'.
349: '</table></td></tr>'.
350: '<tr><td bgcolor="#DDDDBB" colspan="'.$colspan.'">'.
351: '<table border="0" width="100%" bgcolor="#DDDDBB"><tr>';
352: if ($visible>2) {
353: $discussion.='<td align="left">'.
354: '<a href="/adm/feedback?threadedon='.$ressymb;
355: if ($newpostsflag) {
356: $discussion .= '&previous='.$prevread;
357: }
358: $discussion .='">'.&mt('Threaded View').'</a> '.
359: '<a href="/adm/feedback?threadedoff='.$ressymb;
360: if ($newpostsflag) {
361: $discussion .= '&previous='.$prevread;
362: }
363: $discussion .='">'.&mt('Chronological View').'</a> </td>';
364: }
365: if ($newpostsflag) {
366: if (!$markondisp) {
367: $discussion .='<td align="right"><a href="/adm/feedback?markread='.$ressymb.'">'.&mt('Mark new posts as read').'</a> ';
368: } else {
369: $discussion .= '<td> </td>';
370: }
371: } else {
372: $discussion .= '<td> </td>';
373: }
374: $discussion .= '</tr></table></td></tr>';
375:
376: my $numhidden = keys %notshown;
377: if ($numhidden > 0) {
378: my $colspan = $maxdepth+1;
379: $discussion.="\n".'<tr><td bgcolor="#CCCCCC" colspan="'.$colspan.'">'.
380: '<a href="/adm/feedback?allposts='.$ressymb;
381: if ($newpostsflag) {
382: $discussion .= '&previous='.$prevread;
383: }
384: $discussion .= '">'.&mt('Show all posts').'</a> '.&mt('to display').' '.
385: $numhidden.' '.&mt('previously viewed posts').
386: '<br/></td></tr>';
387: }
388: foreach (sort { $a <=> $b } keys %alldiscussion) {
389: unless ($notshown{$alldiscussion{$_}} eq '1') {
390: $discussion.="\n<tr>";
391: my $thisdepth=$depth[$alldiscussion{$_}];
392: for (1..$thisdepth) {
393: $discussion.='<td> </td>';
394: }
395: my $colspan=$maxdepth-$thisdepth+1;
396: $discussion.='<td bgcolor="'.$bgcols[$newitem{$alldiscussion{$_}}].'" colspan="'.$colspan.'">'.
397: $discussionitems[$alldiscussion{$_}].
398: '</td></tr>';
399: }
400: }
401: $discussion.='</table><br /><br />';
402: }
403: if ($discussiononly) {
404: $discussion.=(<<ENDDISCUSS);
405: <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data">
406: <input type="submit" name="discuss" value="Post Discussion" />
407: <input type="submit" name="anondiscuss" value="Post Anonymous Discussion" />
408: <input type="hidden" name="symb" value="$ressymb" />
409: <input type="hidden" name="sendit" value="true" />
410: <br />
411: <font size="1">Note: in anonymous discussion, your name is visible only to
412: course faculty</font><br />
413: <b>Title:</b> <input type="text" name="subject" value="" size="30" /><br /><br />
414: <textarea name="comment" cols="60" rows="10" wrap="hard"></textarea>
415: <p>
416: Attachment (128 KB max size): <input type="file" name="attachment" />
417: </p>
418: </form>
419: ENDDISCUSS
420: $discussion.=&generate_preview_button();
421: } else {
422: if (&Apache::lonnet::allowed('pch',
423: $ENV{'request.course.id'}.
424: ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) {
425: $discussion.='<table bgcolor="#BBBBBB"><tr><td><a href="/adm/feedback?replydisc='.
426: $symb.':::" '.$target.'>'.
427: '<img src="/adm/lonMisc/chat.gif" border="0" />'.
428: &mt('Post Discussion').'</a></td></tr></table>';
429: }
430: }
431: return $discussion;
432: }
433:
434: sub mail_screen {
435: my ($r,$feedurl,$options) = @_;
436: my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion',
437: '','onLoad="window.focus();"');
438: my $title=&Apache::lonnet::gettitle($feedurl);
439: if (!$title) { $title = $feedurl; }
440: my $quote='';
441: my $subject = '';
442: my $prevtag = '';
443: if ($ENV{'form.replydisc'}) {
444: my ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'});
445: my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
446: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
447: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
448: unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {
449: my $message=$contrib{$idx.':message'};
450: $message=~s/\n/\<br \/\>/g;
451: $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message).'</blockquote>';
452: if ($idx > 0) {
453: $subject = 'Re: '.$contrib{$idx.':subject'};
454: }
455: }
456: if ($ENV{'form.previous'}) {
457: $prevtag = '<input type="hidden" name="previous" value="'.$ENV{'form.previous'}.'" />';
458: }
459: }
460: my $latexHelp = Apache::loncommon::helpLatexCheatsheet();
461: my $send=&mt('Send');
462: $r->print(<<ENDDOCUMENT);
463: <html>
464: <head>
465: <title>The LearningOnline Network with CAPA</title>
466: <meta http-equiv="pragma" content="no-cache"></meta>
467: <script type="text/javascript">
468: //<!--
469: function gosubmit() {
470: var rec=0;
471: if (typeof(document.mailform.elements.author)!="undefined") {
472: if (document.mailform.elements.author.checked) {
473: rec=1;
474: }
475: }
476: if (typeof(document.mailform.elements.question)!="undefined") {
477: if (document.mailform.elements.question.checked) {
478: rec=1;
479: }
480: }
481: if (typeof(document.mailform.elements.course)!="undefined") {
482: if (document.mailform.elements.course.checked) {
483: rec=1;
484: }
485: }
486: if (typeof(document.mailform.elements.policy)!="undefined") {
487: if (document.mailform.elements.policy.checked) {
488: rec=1;
489: }
490: }
491: if (typeof(document.mailform.elements.discuss)!="undefined") {
492: if (document.mailform.elements.discuss.checked) {
493: rec=1;
494: }
495: }
496: if (typeof(document.mailform.elements.anondiscuss)!="undefined") {
497: if (document.mailform.elements.anondiscuss.checked) {
498: rec=1;
499: }
500: }
501:
502: if (rec) {
503: document.mailform.submit();
504: } else {
505: alert('Please check a feedback type.');
506: }
507: }
508: //-->
509: </script>
510: </head>
511: $bodytag
512: <h2><tt>$title</tt></h2>
513: <form action="/adm/feedback" method="post" name="mailform"
514: enctype="multipart/form-data">
515: $prevtag
516: <input type="hidden" name="postdata" value="$feedurl" />
517: <input type="hidden" name="replydisc" value="$ENV{'form.replydisc'}" />
518: Please check at least one of the following feedback types:
519: $options<hr />
520: $quote
521: <p>My question/comment/feedback:</p>
522: <p>
523: $latexHelp
524: Title: <input type="text" name="subject" size="30" value="$subject" /></p>
525: <p>
526: <textarea name="comment" cols="60" rows="10" wrap="hard">
527: </textarea></p>
528: <p>
529: Attachment (128 KB max size): <input type="file" name="attachment" />
530: </p>
531: <p>
532: <input type="hidden" name="sendit" value="1" />
533: <input type="button" value="$send" onClick='gosubmit();' />
534: </p>
535: </form>
536: ENDDOCUMENT
537: $r->print(&generate_preview_button().'</body></html>');
538: }
539:
540: sub fail_redirect {
541: my ($r,$feedurl) = @_;
542: if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
543: $r->print (<<ENDFAILREDIR);
544: <html>
545: <head><title>Feedback not sent</title>
546: <meta http-equiv="pragma" content="no-cache" />
547: <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />
548: </head>
549: <body bgcolor="#FFFFFF">
550: <img align="right" src="/adm/lonIcons/lonlogos.gif" />
551: <b>Sorry, no recipients ...</b>
552: </body>
553: </html>
554: ENDFAILREDIR
555: }
556:
557: sub redirect_back {
558: my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$status,$previous) = @_;
559: my $prevtag = '';
560: my $qrystr = '';
561: if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
562: if ($previous > 0) {
563: $qrystr = 'previous='.$previous;
564: if ($feedurl =~ /\?register=1/) {
565: $feedurl .= '&'.$qrystr;
566: } else {
567: $feedurl .= '?'.$qrystr;
568: }
569: $prevtag = '<input type="hidden" name="previous" value="'.$previous.'" />';
570: }
571: $r->print (<<ENDREDIR);
572: <html>
573: <head>
574: <title>Feedback sent</title>
575: <meta http-equiv="pragma" content="no-cache" />
576: <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />
577: </head>
578: <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>
579: <img align="right" src="/adm/lonIcons/lonlogos.gif" />
580: $typestyle
581: <b>Sent $sendsomething message(s), and $sendposts post(s).</b>
582: <font color="red">$status</font>
583: <form name="reldt" action="$feedurl" target="loncapaclient">
584: $prevtag
585: </form>
586: </body>
587: </html>
588: ENDREDIR
589: }
590:
591: sub no_redirect_back {
592: my ($r,$feedurl) = @_;
593: $r->print (<<ENDNOREDIR);
594: <html>
595: <head><title>Feedback not sent</title>
596: <meta http-equiv="pragma" content="no-cache" />
597: ENDNOREDIR
598:
599: if ($feedurl!~/^\/adm\/feedback/) {
600: $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2; url='.$feedurl.'">');
601: }
602:
603: $r->print (<<ENDNOREDIRTWO);
604: </head>
605: <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { self.close(); }'>
606: <img align="right" src="/adm/lonIcons/lonlogos.gif" />
607: <b>Sorry, no feedback possible on this resource ...</b>
608: </body>
609: </html>
610: ENDNOREDIRTWO
611: }
612:
613: sub screen_header {
614: my ($feedurl) = @_;
615: my $msgoptions='';
616: my $discussoptions='';
617: unless ($ENV{'form.replydisc'}) {
618: if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/)) {
619: $msgoptions=
620: '<p><input type="checkbox" name="author" /> '.
621: &mt('Feedback to resource author').'</p>';
622: }
623: if (&feedback_available(1)) {
624: $msgoptions.=
625: '<br /><input type="checkbox" name="question" /> '.
626: &mt('Question about resource content');
627: }
628: if (&feedback_available(0,1)) {
629: $msgoptions.=
630: '<br /><input type="checkbox" name="course" /> '.
631: &mt('Question/Comment/Feedback about course content');
632: }
633: if (&feedback_available(0,0,1)) {
634: $msgoptions.=
635: '<br /><input type="checkbox" name="policy" /> '.
636: &mt('Question/Comment/Feedback about course policy');
637: }
638: }
639: if ($ENV{'request.course.id'}) {
640: if (&Apache::lonnet::allowed('pch',
641: $ENV{'request.course.id'}.
642: ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) {
643: $discussoptions='<input type="checkbox" name="discuss" onClick="this.form.anondiscuss.checked=false;" '.
644: ($ENV{'form.replydisc'}?' checked="1"':'').' /> '.
645: &mt('Contribution to course discussion of resource');
646: $discussoptions.='<br /><input type="checkbox" name="anondiscuss" onClick="this.form.discuss.checked=false;" /> '.
647: &mt('Anonymous contribution to course discussion of resource').
648: ' <i>('.&mt('name only visible to course faculty').')</i>';
649: }
650: }
651: if ($msgoptions) { $msgoptions='<h2><img src="/adm/lonMisc/feedback.gif" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }
652: if ($discussoptions) {
653: $discussoptions='<h2><img src="/adm/lonMisc/chat.gif" />'.&mt('Discussion Contributions').'</h2>'.$discussoptions; }
654: return $msgoptions.$discussoptions;
655: }
656:
657: sub resource_output {
658: my ($feedurl) = @_;
659: my $usersaw=&Apache::lonnet::ssi_body($feedurl);
660: $usersaw=~s/\<body[^\>]*\>//gi;
661: $usersaw=~s/\<\/body\>//gi;
662: $usersaw=~s/\<html\>//gi;
663: $usersaw=~s/\<\/html\>//gi;
664: $usersaw=~s/\<head\>//gi;
665: $usersaw=~s/\<\/head\>//gi;
666: $usersaw=~s/action\s*\=/would_be_action\=/gi;
667: return $usersaw;
668: }
669:
670: sub clear_out_html {
671: my ($message,$override)=@_;
672: my $cid=$ENV{'request.course.id'};
673: if (($ENV{"course.$cid.allow_limited_html_in_feedback"} =~ m/yes/i) ||
674: ($override)) {
675: # allows <B> <I> <P> <A> <LI> <OL> <UL> <EM> <BR> <TT> <STRONG>
676: # <BLOCKQUOTE> <DIV .*> <DIV> <IMG>
677: my %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1,
678: BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, DIV=>1, IMG=>1,
679: M=>1);
680:
681: $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/
682: {($html{uc($2)}&&(length($1)<1000))?"\<$1":"\<$1"}/ge;
683: $message =~ s/(\<?\s*(\w+)[^\<\>]*)\>/
684: {($html{uc($2)}&&(length($1)<1000))?"$1\>":"$1\>"}/ge;
685: } else {
686: $message=~s/\</\<\;/g;
687: $message=~s/\>/\>\;/g;
688: }
689: return $message;
690: }
691:
692: sub assemble_email {
693: my ($feedurl,$message,$prevattempts,$usersaw,$useranswer)=@_;
694: my $email=<<"ENDEMAIL";
695: Refers to <a href="$feedurl">$feedurl</a>
696:
697: $message
698: ENDEMAIL
699: my $citations=<<"ENDCITE";
700: <h2>Previous attempts of student (if applicable)</h2>
701: $prevattempts
702: <br /><hr />
703: <h2>Original screen output (if applicable)</h2>
704: $usersaw
705: <h2>Correct Answer(s) (if applicable)</h2>
706: $useranswer
707: ENDCITE
708: return ($email,$citations);
709: }
710:
711: sub secapply {
712: my $rec=shift;
713: my $defaultflag=shift;
714: $rec=~s/\s+//g;
715: $rec=~s/\@/\:/g;
716: my ($adr,$sections)=($rec=~/^([^\(]+)\(([^\)]+)\)/);
717: if ($sections) {
718: foreach (split(/\;/,$sections)) {
719: if (($_ eq $ENV{'request.course.sec'}) ||
720: ($defaultflag && ($_ eq '*'))) {
721: return $adr;
722: }
723: }
724: } else {
725: return $rec;
726: }
727: return '';
728: }
729:
730: sub decide_receiver {
731: my ($feedurl,$author,$question,$course,$policy,$defaultflag) = @_;
732: my $typestyle='';
733: my %to=();
734: if ($ENV{'form.author'}||$author) {
735: $typestyle.='Submitting as Author Feedback<br>';
736: $feedurl=~/^\/res\/(\w+)\/(\w+)\//;
737: $to{$2.':'.$1}=1;
738: }
739: if ($ENV{'form.question'}||$question) {
740: $typestyle.='Submitting as Question<br>';
741: foreach (split(/\,/,
742: $ENV{'course.'.$ENV{'request.course.id'}.'.question.email'})
743: ) {
744: my $rec=&secapply($_,$defaultflag);
745: if ($rec) { $to{$rec}=1; }
746: }
747: }
748: if ($ENV{'form.course'}||$course) {
749: $typestyle.='Submitting as Comment<br />';
750: foreach (split(/\,/,
751: $ENV{'course.'.$ENV{'request.course.id'}.'.comment.email'})
752: ) {
753: my $rec=&secapply($_,$defaultflag);
754: if ($rec) { $to{$rec}=1; }
755: }
756: }
757: if ($ENV{'form.policy'}||$policy) {
758: $typestyle.='Submitting as Policy Feedback<br />';
759: foreach (split(/\,/,
760: $ENV{'course.'.$ENV{'request.course.id'}.'.policy.email'})
761: ) {
762: my $rec=&secapply($_,$defaultflag);
763: if ($rec) { $to{$rec}=1; }
764: }
765: }
766: if ((scalar(%to) eq '0') && (!$defaultflag)) {
767: ($typestyle,%to)=
768: &decide_receiver($feedurl,$author,$question,$course,$policy,1);
769: }
770: return ($typestyle,%to);
771: }
772:
773: sub feedback_available {
774: my ($question,$course,$policy)=@_;
775: my ($typestyle,%to)=&decide_receiver('',0,$question,$course,$policy);
776: return scalar(%to);
777: }
778:
779: sub send_msg {
780: my ($feedurl,$email,$citations,$attachmenturl,%to)=@_;
781: my $status='';
782: my $sendsomething=0;
783: foreach (keys %to) {
784: if ($_) {
785: my $declutter=&Apache::lonnet::declutter($feedurl);
786: unless (&Apache::lonmsg::user_normal_msg(split(/\:/,$_),
787: 'Feedback ['.$declutter.']',$email,$citations,$feedurl,
788: $attachmenturl)=~/ok/) {
789: $status.='<br />'.&mt('Error sending message to').' '.$_.'<br />';
790: } else {
791: $sendsomething++;
792: }
793: }
794: }
795:
796: my %record=&Apache::lonnet::restore('_feedback');
797: my ($temp)=keys %record;
798: unless ($temp=~/^error\:/) {
799: my %newrecord=();
800: $newrecord{'resource'}=$feedurl;
801: $newrecord{'subnumber'}=$record{'subnumber'}+1;
802: unless (&Apache::lonnet::cstore(\%newrecord,'_feedback') eq 'ok') {
803: $status.='<br />'.&mt('Not registered').'<br />';
804: }
805: }
806:
807: return ($status,$sendsomething);
808: }
809:
810: sub adddiscuss {
811: my ($symb,$email,$anon,$attachmenturl,$subject)=@_;
812: my $status='';
813: if (&Apache::lonnet::allowed('pch',$ENV{'request.course.id'}.
814: ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) {
815:
816: my %contrib=('message' => $email,
817: 'sendername' => $ENV{'user.name'},
818: 'senderdomain' => $ENV{'user.domain'},
819: 'screenname' => $ENV{'environment.screenname'},
820: 'plainname' => $ENV{'environment.firstname'}.' '.
821: $ENV{'environment.middlename'}.' '.
822: $ENV{'environment.lastname'}.' '.
823: $ENV{'enrironment.generation'},
824: 'attachmenturl'=> $attachmenturl,
825: 'subject' => $subject);
826: if ($ENV{'form.replydisc'}) {
827: $contrib{'replyto'}=(split(/\:\:\:/,$ENV{'form.replydisc'}))[1];
828: }
829: if ($anon) {
830: $contrib{'anonymous'}='true';
831: }
832: if (($symb) && ($email)) {
833: $status='Adding to class discussion'.($anon?' (anonymous)':'').': '.
834: &Apache::lonnet::store(\%contrib,$symb,$ENV{'request.course.id'},
835: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
836: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
837: my %storenewentry=($symb => time);
838: $status.='<br />'.&mt('Updating discussion time').': '.
839: &Apache::lonnet::put('discussiontimes',\%storenewentry,
840: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
841: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
842: }
843: my %record=&Apache::lonnet::restore('_discussion');
844: my ($temp)=keys %record;
845: unless ($temp=~/^error\:/) {
846: my %newrecord=();
847: $newrecord{'resource'}=$symb;
848: $newrecord{'subnumber'}=$record{'subnumber'}+1;
849: $status.='<br />'.&mt('Registering').': '.
850: &Apache::lonnet::cstore(\%newrecord,'_discussion');
851: }
852: } else {
853: $status.='Failed.';
854: }
855: return $status.'<br />';
856: }
857:
858: # ----------------------------------------------------------- Preview function
859:
860: sub show_preview {
861: my $r=shift;
862: my $message=&clear_out_html($ENV{'form.comment'});
863: $message=~s/\n/\<br \/\>/g;
864: $message=&Apache::lontexconvert::msgtexconverted($message);
865: my $subject=&clear_out_html($ENV{'form.subject'});
866: $subject=~s/\n/\<br \/\>/g;
867: $subject=&Apache::lontexconvert::msgtexconverted($subject);
868: $r->print('<table border="2"><tr><td>'.
869: '<b>Subject:</b> '.$subject.'<br /><br />'.
870: $message.'</td></tr></table>');
871: }
872:
873: sub generate_preview_button {
874: my $pre=&mt("Show Preview");
875: return(<<ENDPREVIEW);
876: <form name="preview" action="/adm/feedback?preview=1" method="post" target="preview">
877: <input type="hidden" name="subject">
878: <input type="hidden" name="comment" />
879: <input type="button" value="$pre"
880: onClick="this.form.comment.value=document.mailform.comment.value;this.form.subject.value=document.mailform.subject.value;this.form.submit();" />
881: </form>
882: ENDPREVIEW
883: }
884:
885: sub handler {
886: my $r = shift;
887: if ($r->header_only) {
888: &Apache::loncommon::content_type($r,'text/html');
889: $r->send_http_header;
890: return OK;
891: }
892:
893: # --------------------------- Get query string for limited number of parameters
894:
895: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
896: ['hide','unhide','deldisc','postdata','preview','replydisc','threadedon','threadedoff','onlyunread','allposts','previous','markread','markonread','markondisp']);
897:
898: if (($ENV{'form.markondisp'}) || ($ENV{'form.markonread'})) {
899: # ---------------------- Modify setting for identification of 'NEW' posts in this discussion
900:
901: &Apache::loncommon::content_type($r,'text/html');
902: $r->send_http_header;
903: my $symb=$ENV{'form.markondisp'}?$ENV{'form.markondisp'}:$ENV{'form.markonread'};
904: my $ressymb = $symb;
905: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
906: unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
907: $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;
908: }
909:
910: my %discinfo = ();
911: my $lastkey = $ressymb.'_lastread';
912: my $ondispkey = $ressymb.'_markondisp';
913: if ($ENV{'form.markondisp'}) {
914: $discinfo{$lastkey} = time;
915: $discinfo{$ondispkey} = 1;
916: } elsif ($ENV{'form.markonread'}) {
917: if ( defined($ENV{'previous'}) ) {
918: $discinfo{$lastkey} = $ENV{'previous'};
919: }
920: $discinfo{$ondispkey} = 0;
921: }
922: &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
923: if ($ENV{'form.markondisp'}) {
924: &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0');
925: } else {
926: &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0','',$ENV{'form.previous'});
927: }
928: return OK;
929: } elsif (($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'})) {
930: # ----------------------------------------------------------------- Modify display setting for this discussion
931: &Apache::loncommon::content_type($r,'text/html');
932: $r->send_http_header;
933: my $symb=$ENV{'form.allposts'}?$ENV{'form.allposts'}:$ENV{'form.onlyunread'};
934: my $ressymb = $symb;
935: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
936: unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
937: $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;
938: }
939: my %discinfo = ();
940: if ($ENV{'form.allposts'}) {
941: $discinfo{$ressymb.'_showonlyunread'} = 0;
942: } elsif ($ENV{'form.onlyunread'}) {
943: $discinfo{$ressymb.'_showonlyunread'} = 1;
944: }
945: &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
946: &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'<br />','0','0','',$ENV{'form.previous'});
947: return OK;
948: } elsif ($ENV{'form.markread'}) {
949: # ----------------------------------------------------------------- Mark new posts as read
950: &Apache::loncommon::content_type($r,'text/html');
951: $r->send_http_header;
952: my $symb=$ENV{'form.markread'};
953: my $ressymb = $symb;
954: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
955: unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
956: $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;
957: }
958: my %discinfo = ();
959: my $lastkey = $ressymb.'_lastread';
960: $discinfo{$lastkey} = time;
961: &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
962: &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed reading status').'<br />','0','0');
963: return OK;
964: } elsif (($ENV{'form.hide'}) || ($ENV{'form.unhide'})) {
965: # ----------------------------------------------------------------- Hide/unhide
966: &Apache::loncommon::content_type($r,'text/html');
967: $r->send_http_header;
968:
969: my $entry=$ENV{'form.hide'}?$ENV{'form.hide'}:$ENV{'form.unhide'};
970:
971: my ($symb,$idx)=split(/\:\:\:/,$entry);
972: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
973:
974: my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
975: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
976: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
977:
978:
979: my $currenthidden=$contrib{'hidden'};
980:
981: if ($ENV{'form.hide'}) {
982: $currenthidden.='.'.$idx.'.';
983: } else {
984: $currenthidden=~s/\.$idx\.//g;
985: }
986: my %newhash=('hidden' => $currenthidden);
987:
988: &Apache::lonnet::store(\%newhash,$symb,$ENV{'request.course.id'},
989: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
990: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
991:
992: &redirect_back($r,&Apache::lonnet::clutter($url),
993: &mt('Changed discussion status').'<br />','0','0','',$ENV{'form.previous'});
994: } elsif (($ENV{'form.threadedon'}) || ($ENV{'form.threadedoff'})) {
995: &Apache::loncommon::content_type($r,'text/html');
996: $r->send_http_header;
997: if ($ENV{'form.threadedon'}) {
998: &Apache::lonnet::put('environment',{'threadeddiscussion' => 'on'});
999: &Apache::lonnet::appenv('environment.threadeddiscussion' => 'on');
1000: } else {
1001: &Apache::lonnet::del('environment',['threadeddiscussion']);
1002: &Apache::lonnet::delenv('environment\.threadeddiscussion');
1003: }
1004: my $symb=$ENV{'form.threadedon'}?$ENV{'form.threadedon'}:$ENV{'form.threadedoff'};
1005: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
1006: &redirect_back($r,&Apache::lonnet::clutter($url),
1007: &mt('Changed discussion view mode').'<br />','0','0','',$ENV{'form.previous'});
1008: } elsif ($ENV{'form.deldisc'}) {
1009: # --------------------------------------------------------------- Hide for good
1010: &Apache::loncommon::content_type($r,'text/html');
1011: $r->send_http_header;
1012:
1013: my $entry=$ENV{'form.deldisc'};
1014:
1015: my ($symb,$idx)=split(/\:\:\:/,$entry);
1016: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
1017:
1018: my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},
1019: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
1020: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
1021:
1022:
1023: my $currentdeleted=$contrib{'deleted'};
1024:
1025: $currentdeleted.='.'.$idx.'.';
1026:
1027: my %newhash=('deleted' => $currentdeleted);
1028:
1029: &Apache::lonnet::store(\%newhash,$symb,$ENV{'request.course.id'},
1030: $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
1031: $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
1032:
1033: &redirect_back($r,&Apache::lonnet::clutter($url),
1034: &mt('Changed discussion status').'<br />','0','0','',$ENV{'form.previous'});
1035: } elsif ($ENV{'form.preview'}) {
1036: # -------------------------------------------------------- User wants a preview
1037: $r->content_type('text/html');
1038: $r->send_http_header;
1039: &show_preview($r);
1040: } else {
1041: # ------------------------------------------------------------- Normal feedback
1042: my $feedurl=$ENV{'form.postdata'};
1043: $feedurl=~s/^http\:\/\///;
1044: $feedurl=~s/^$ENV{'SERVER_NAME'}//;
1045: $feedurl=~s/^$ENV{'HTTP_HOST'}//;
1046: $feedurl=~s/\?.+$//;
1047:
1048: my $symb;
1049: if ($ENV{'form.replydisc'}) {
1050: $symb=(split(/\:\:\:/,$ENV{'form.replydisc'}))[0];
1051: my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
1052: $feedurl=&Apache::lonnet::clutter($url);
1053: } else {
1054: $symb=&Apache::lonnet::symbread($feedurl);
1055: }
1056: unless ($symb) {
1057: $symb=$ENV{'form.symb'};
1058: if ($symb) {
1059: my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
1060: $feedurl=&Apache::lonnet::clutter($url);
1061: }
1062: }
1063: my $goahead=1;
1064: if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form)$/) {
1065: unless ($symb) { $goahead=0; }
1066: }
1067: # backward compatibility (bulltin boards used to be 'wrapped')
1068: if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
1069: $feedurl=~s|^/adm/wrapper||;
1070: }
1071: if ($goahead) {
1072: # Go ahead with feedback, no ambiguous reference
1073: &Apache::loncommon::content_type($r,'text/html');
1074: $r->send_http_header;
1075:
1076: if (
1077: (
1078: ($feedurl=~m:^/res:) && ($feedurl!~m:^/res/adm:)
1079: )
1080: ||
1081: ($ENV{'request.course.id'} && ($feedurl!~m:^/adm:))
1082: ||
1083: ($ENV{'request.course.id'} && ($symb=~/^bulletin\_\_\_/))
1084: ) {
1085: # --------------------------------------------------- Print login screen header
1086: unless ($ENV{'form.sendit'}) {
1087: my $options=&screen_header($feedurl);
1088: if ($options) {
1089: &mail_screen($r,$feedurl,$options);
1090: } else {
1091: &fail_redirect($r,$feedurl);
1092: }
1093: } else {
1094:
1095: # Get previous user input
1096: my $prevattempts=&Apache::loncommon::get_previous_attempt(
1097: $symb,$ENV{'user.name'},$ENV{'user.domain'},
1098: $ENV{'request.course.id'});
1099:
1100: # Get output from resource
1101: my $usersaw=&resource_output($feedurl);
1102:
1103: # Get resource answer (need to allow student to view grades for this to work)
1104: &Apache::lonnet::appenv(('allowed.vgr'=>'F'));
1105: my $useranswer=&Apache::loncommon::get_student_answers(
1106: $symb,$ENV{'user.name'},$ENV{'user.domain'},
1107: $ENV{'request.course.id'});
1108: &Apache::lonnet::delenv('allowed.vgr');
1109: # Get attachments, if any, and not too large
1110: my $attachmenturl='';
1111: if ($ENV{'form.attachment.filename'}) {
1112: unless (length($ENV{'form.attachment'})>131072) {
1113: $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');
1114: }
1115: }
1116: # Filter HTML out of message (could be nasty)
1117: my $message=&clear_out_html($ENV{'form.comment'});
1118:
1119: # Assemble email
1120: my ($email,$citations)=&assemble_email($feedurl,$message,$prevattempts,
1121: $usersaw,$useranswer);
1122:
1123: # Who gets this?
1124: my ($typestyle,%to) = &decide_receiver($feedurl);
1125:
1126: # Actually send mail
1127: my ($status,$numsent)=&send_msg($feedurl,$email,$citations,
1128: $attachmenturl,%to);
1129:
1130: # Discussion? Store that.
1131:
1132: my $numpost=0;
1133: if ($ENV{'form.discuss'}) {
1134: my $subject = &clear_out_html($ENV{'form.subject'});
1135: $typestyle.=&adddiscuss($symb,$message,0,$attachmenturl,$subject);
1136: $numpost++;
1137: }
1138:
1139: if ($ENV{'form.anondiscuss'}) {
1140: my $subject = &clear_out_html($ENV{'form.subject'});
1141: $typestyle.=&adddiscuss($symb,$message,1,$attachmenturl,$subject);
1142: $numpost++;
1143: }
1144:
1145:
1146: # Receipt screen and redirect back to where came from
1147: &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$status,$ENV{'form.previous'});
1148:
1149: }
1150: } else {
1151: # Unable to give feedback
1152: &no_redirect_back($r,$feedurl);
1153: }
1154: } else {
1155: # Ambiguous Problem Resource
1156: if ( &Apache::lonnet::mod_perl_version() == 2 ) {
1157: &Apache::lonnet::cleanenv();
1158: }
1159: $r->internal_redirect('/adm/ambiguous');
1160: }
1161: }
1162: return OK;
1163: }
1164:
1165: 1;
1166: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>