Annotation of loncom/interface/lonfeedback.pm, revision 1.163

1.1       www         1: # The LearningOnline Network
                      2: # Feedback
                      3: #
1.163   ! albertel    4: # $Id: lonfeedback.pm,v 1.162 2005/04/11 15:33:46 albertel Exp $
1.19      albertel    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: #
1.77      www        28: ###
1.7       albertel   29: 
1.1       www        30: package Apache::lonfeedback;
                     31: 
                     32: use strict;
                     33: use Apache::Constants qw(:common);
1.3       www        34: use Apache::lonmsg();
1.9       albertel   35: use Apache::loncommon();
1.33      www        36: use Apache::lontexconvert();
1.86      www        37: use Apache::lonlocal; # must not have ()
1.157     albertel   38: use Apache::lonnet;
1.86      www        39: use Apache::lonhtmlcommon();
1.128     raeburn    40: use Apache::lonnavmaps;
1.130     albertel   41: use Apache::lonenc();
1.112     raeburn    42: use HTML::LCParser();
1.106     www        43: use Apache::lonspeller();
1.116     raeburn    44: use Cwd;
1.54      www        45: 
1.92      albertel   46: sub discussion_open {
1.122     raeburn    47:     my ($status,$symb)=@_;
1.92      albertel   48:     if (defined($status) &&
                     49: 	!($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'
1.77      www        50: 	  || $status eq 'OPEN')) {
1.92      albertel   51: 	return 0;
1.75      albertel   52:     }
1.122     raeburn    53:     my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);
1.89      albertel   54:     if (defined($close) && $close ne '' && $close < time) {
1.92      albertel   55: 	return 0;
1.89      albertel   56:     }
1.92      albertel   57:     return 1;
                     58: }
                     59: 
                     60: sub discussion_visible {
                     61:     my ($status)=@_;
                     62:     if (not &discussion_open($status)) {
                     63: 	my $hidden=&Apache::lonnet::EXT('resource.0.discusshide');
                     64: 	if (lc($hidden) eq 'yes' or $hidden eq '' or !defined($hidden))  {
1.157     albertel   65: 	    if (!$env{'request.role.adv'}) { return 0; }
1.92      albertel   66: 	}
                     67:     }
                     68:     return 1;
1.90      albertel   69: }
1.84      raeburn    70: 
1.90      albertel   71: sub list_discussion {
1.147     raeburn    72:     my ($mode,$status,$ressymb,$imsextras)=@_;
1.157     albertel   73:     my $outputtarget=$env{'form.grade_target'};
                     74:     if (defined($env{'form.export'})) {
                     75: 	if($env{'form.export'}) {
1.116     raeburn    76:             $outputtarget = 'export';
                     77:         }
1.140     raeburn    78:     }
1.147     raeburn    79:     if (defined($imsextras)) {
                     80:         if ($$imsextras{'caller'} eq 'imsexport') {
                     81:             $outputtarget = 'export';
                     82:         }
                     83:     }
1.92      albertel   84:     if (not &discussion_visible($status)) { return ''; }
1.84      raeburn    85:     my @bgcols = ("#cccccc","#eeeeee");
1.57      www        86:     my $discussiononly=0;
                     87:     if ($mode eq 'board') { $discussiononly=1; }
1.157     albertel   88:     unless ($env{'request.course.id'}) { return ''; }
                     89:     my $crs='/'.$env{'request.course.id'};
                     90:     my $cid=$env{'request.course.id'};
                     91:     if ($env{'request.course.sec'}) {
                     92: 	$crs.='_'.$env{'request.course.sec'};
1.143     raeburn    93:     }
1.55      www        94:     $crs=~s/\_/\//g;
1.133     albertel   95:     unless ($ressymb) {	$ressymb=&Apache::lonnet::symbread(); }
                     96:     unless ($ressymb) { return ''; }
                     97:     $ressymb=&wrap_symb($ressymb);
                     98:     my $encsymb=&Apache::lonenc::check_encrypt($ressymb);
                     99:     my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
                    100: 		  && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form)$/));
                    101:     
1.100     raeburn   102:     my %usernamesort = ();
                    103:     my %namesort =();
                    104:     my %subjectsort = ();
1.133     albertel  105: 
1.80      raeburn   106: # Get discussion display settings for this discussion
                    107:     my $lastkey = $ressymb.'_lastread';
                    108:     my $showkey = $ressymb.'_showonlyunread';
1.111     raeburn   109:     my $markkey = $ressymb.'_showonlyunmark',
1.80      raeburn   110:     my $visitkey = $ressymb.'_visit';
1.84      raeburn   111:     my $ondispkey = $ressymb.'_markondisp';
1.101     raeburn   112:     my $userpickkey = $ressymb.'_userpick';
1.111     raeburn   113:     my $toggkey = $ressymb.'_readtoggle';
                    114:     my $readkey = $ressymb.'_read';
1.139     albertel  115:     $ressymb=$encsymb;
1.157     albertel  116:     my %dischash = &Apache::lonnet::get('nohist_'.$env{'request.course.id'}.'_discuss',[$lastkey,$showkey,$markkey,$visitkey,$ondispkey,$userpickkey,$toggkey,$readkey],$env{'user.domain'},$env{'user.name'});
1.84      raeburn   117:     my %discinfo = ();
1.80      raeburn   118:     my $showonlyunread = 0;
1.111     raeburn   119:     my $showunmark = 0; 
1.84      raeburn   120:     my $markondisp = 0;
1.79      raeburn   121:     my $prevread = 0;
1.81      raeburn   122:     my $previous = 0;
1.80      raeburn   123:     my $visit = 0;
                    124:     my $newpostsflag = 0;
1.101     raeburn   125:     my @posters = split/\&/,$dischash{$userpickkey};
1.80      raeburn   126: 
1.81      raeburn   127: # Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts.
1.101     raeburn   128:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','totposters']);
1.157     albertel  129:     my $sortposts = $env{'form.sortposts'};
                    130:     my $statusfilter = $env{'form.statusfilter'};
1.143     raeburn   131:     my @sectionpick = ();
1.157     albertel  132:     if ($env{'form.sectionpick'} =~ /,/) {
                    133:         @sectionpick = split/,/,$env{'form.sectionpick'};
1.143     raeburn   134:     } else {
1.157     albertel  135:         $sectionpick[0] = $env{'form.sectionpick'};
1.143     raeburn   136:     }
                    137:     my @rolefilter = ();
1.157     albertel  138:     if ($env{'form.rolefilter'} =~ /,/) {
                    139:         @rolefilter = split/,/,$env{'form.rolefilter'};
1.143     raeburn   140:     } else {
1.157     albertel  141:         $rolefilter[0] = $env{'form.rolefilter'};
1.143     raeburn   142:     }
1.157     albertel  143:     my $totposters = $env{'form.totposters'};
                    144:     $previous = $env{'form.previous'};
1.80      raeburn   145:     if ($previous > 0) {
                    146:         $prevread = $previous;
                    147:     } elsif (defined($dischash{$lastkey})) {
1.84      raeburn   148:         unless ($dischash{$lastkey} eq '') {
                    149:             $prevread = $dischash{$lastkey};
                    150:         }
1.80      raeburn   151:     }
1.79      raeburn   152: 
1.108     raeburn   153: # Get information about students and non-students in course for filtering display of posts
1.101     raeburn   154:     my %roleshash = ();
                    155:     my %roleinfo = ();
1.157     albertel  156:     if ($env{'form.rolefilter'}) {
                    157:         %roleshash = &Apache::lonnet::dump('nohist_userroles',$env{'course.'.$env{'request.course.id'}.'.domain'},$env{'course.'.$env{'request.course.id'}.'.num'});
1.101     raeburn   158:         foreach (keys %roleshash) {
                    159:             my ($role,$uname,$udom,$sec) = split/:/,$_;
1.144     raeburn   160:             if ($role =~ /^cr/) {
                    161:                 $role = 'cr';
                    162:             }
1.101     raeburn   163:             my ($end,$start) = split/:/,$roleshash{$_};
                    164:             my $now = time;
                    165:             my $status = 'Active';
                    166:             if (($now < $start) || ($end > 0 && $now > $end)) {
                    167:                 $status = 'Expired';
                    168:             }
1.144     raeburn   169:             if ($uname && $udom) { 
                    170:                 push @{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status;
                    171:             }
1.101     raeburn   172:         }
                    173:         my ($classlist) = &Apache::loncoursedata::get_classlist(
1.157     albertel  174:                               $env{'request.course.id'},
                    175:                               $env{'course.'.$env{'request.course.id'}.'.domain'},
                    176:                               $env{'course.'.$env{'request.course.id'}.'.num'});
1.101     raeburn   177:         my $sec_index = &Apache::loncoursedata::CL_SECTION();
                    178:         my $status_index = &Apache::loncoursedata::CL_STATUS();
                    179:         while (my ($student,$data) = each %$classlist) {
                    180:             my ($section,$status) = ($data->[$sec_index],
                    181:                                  $data->[$status_index]);
                    182:             push @{$roleinfo{$student}}, 'st:'.$section.':'.$status;
                    183:         }
                    184:     }
                    185: 
1.84      raeburn   186: # Get discussion display default settings for user
1.157     albertel  187:     if ($env{'environment.discdisplay'} eq 'unread') {
1.83      raeburn   188:         $showonlyunread = 1;
                    189:     }
1.157     albertel  190:     if ($env{'environment.discmarkread'} eq 'ondisp') {
1.84      raeburn   191:         $markondisp = 1;
                    192:     }
                    193: 
                    194: # Override user's default if user specified display setting for this discussion
                    195:     if (defined($dischash{$ondispkey})) {
1.123     raeburn   196:         unless ($dischash{$ondispkey} eq '') {
                    197:             $markondisp = $dischash{$ondispkey};
                    198:         }
1.84      raeburn   199:     }
                    200:     if ($markondisp) {
                    201:         $discinfo{$lastkey} = time;
                    202:     }
1.83      raeburn   203: 
1.80      raeburn   204:     if (defined($dischash{$showkey})) {
1.123     raeburn   205:         unless ($dischash{$showkey} eq '') {
                    206:             $showonlyunread = $dischash{$showkey};
                    207:         }
1.80      raeburn   208:     }
                    209: 
1.111     raeburn   210:     if (defined($dischash{$markkey})) {
1.123     raeburn   211:         unless ($dischash{$markkey} eq '') {
                    212:             $showunmark = $dischash{$markkey};
                    213:         }
1.111     raeburn   214:     }
                    215: 
1.80      raeburn   216:     if (defined($dischash{$visitkey})) {
1.123     raeburn   217:         unless ($dischash{$visitkey} eq '') {
                    218:             $visit = $dischash{$visitkey};
                    219:         }
1.78      raeburn   220:     }
1.80      raeburn   221:     $visit ++;
1.78      raeburn   222: 
1.54      www       223:     my $seeid=&Apache::lonnet::allowed('rin',$crs);
1.68      www       224:     my @discussionitems=();
1.101     raeburn   225:     my %shown = ();
                    226:     my @posteridentity=();
1.116     raeburn   227: 
                    228:     my $current=0;
1.67      www       229:     my $visible=0;
1.68      www       230:     my @depth=();
1.116     raeburn   231:     my @replies = ();
1.68      www       232:     my %alldiscussion=();
1.116     raeburn   233:     my %imsitems=();
                    234:     my %imsfiles=();
1.80      raeburn   235:     my %notshown = ();
1.84      raeburn   236:     my %newitem = ();
1.68      www       237:     my $maxdepth=0;
                    238: 
1.69      www       239:     my $target='';
1.157     albertel  240:     unless ($env{'browser.interface'} eq 'textual' ||
                    241: 	    $env{'environment.remote'} eq 'off' ) {
1.69      www       242: 	$target='target="LONcom"';
                    243:     }
1.111     raeburn   244: 
1.79      raeburn   245:     my $now = time;
1.80      raeburn   246:     $discinfo{$visitkey} = $visit;
                    247: 
1.157     albertel  248:     &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',\%discinfo,$env{'user.domain'},$env{'user.name'});
1.143     raeburn   249:     &build_posting_display(\%usernamesort,\%subjectsort,\%namesort,\%notshown,\%newitem,\%dischash,\%shown,\%alldiscussion,\%imsitems,\%imsfiles,\%roleinfo,\@discussionitems,\@replies,\@depth,\@posters,\$maxdepth,\$visible,\$newpostsflag,\$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$encsymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,$statusfilter,$toggkey,$outputtarget);
1.80      raeburn   250: 
1.67      www       251:     my $discussion='';
1.116     raeburn   252:     my $manifestfile;
                    253:     my $manifestok=0;
                    254:     my $tempexport;
                    255:     my $imsresources;
                    256:     my $copyresult;
1.84      raeburn   257: 
                    258:     my $function = &Apache::loncommon::get_users_function();
                    259:     my $color = &Apache::loncommon::designparm($function.'.tabbg',
1.157     albertel  260:                                                     $env{'user.domain'});
1.84      raeburn   261:     my %lt = &Apache::lonlocal::texthash(
1.97      raeburn   262:         'cuse' => 'Current discussion settings',
1.84      raeburn   263:         'allposts' => 'All posts',
                    264:         'unread' => 'New posts only',
1.111     raeburn   265:         'unmark' => 'Unread only',
1.84      raeburn   266:         'ondisp' => 'Once displayed',
1.111     raeburn   267:         'onmark' => 'Once marked not NEW',
                    268:         'toggoff' => 'Off',
                    269:         'toggon' => 'On',
1.84      raeburn   270:         'disa' => 'Posts to be displayed',
                    271:         'npce' => 'Posts cease to be marked "NEW"',
1.111     raeburn   272:         'epcb' => 'Each post can be toggled read/unread', 
1.97      raeburn   273:         'chgt' => 'Change',
                    274:         'disp' => 'Display',
                    275:         'nolo' => 'Not new',
1.111     raeburn   276:         'togg' => 'Toggle read/unread',
1.84      raeburn   277:     );
                    278: 
                    279:     my $currdisp = $lt{'allposts'};
                    280:     my $currmark = $lt{'onmark'};
1.111     raeburn   281:     my $currtogg = $lt{'toggoff'};
1.84      raeburn   282:     my $dispchange = $lt{'unread'};
                    283:     my $markchange = $lt{'ondisp'};
1.111     raeburn   284:     my $toggchange = $lt{'toggon'};
1.97      raeburn   285:     my $chglink = '/adm/feedback?modifydisp='.$ressymb;
1.111     raeburn   286:     my $displinkA = 'onlyunread';
                    287:     my $displinkB = 'onlyunmark';
1.97      raeburn   288:     my $marklink = 'markondisp';
1.111     raeburn   289:     my $togglink = 'toggon';
1.84      raeburn   290: 
                    291:     if ($markondisp) {
                    292:         $currmark = $lt{'ondisp'};
                    293:         $markchange = $lt{'onmark'};
1.97      raeburn   294:         $marklink = 'markonread';
1.84      raeburn   295:     }
                    296: 
                    297:     if ($showonlyunread) {
                    298:         $currdisp = $lt{'unread'};
                    299:         $dispchange = $lt{'allposts'};
1.111     raeburn   300:         $displinkA = 'allposts';
1.84      raeburn   301:     }
1.111     raeburn   302: 
                    303:     if ($showunmark) {
                    304:         $currdisp = $lt{'unmark'};
                    305:         $dispchange = $lt{'unmark'};
                    306:         $displinkA='allposts';
                    307:         $displinkB='onlyunread';
                    308:         $showonlyunread = 0;
                    309:     }
                    310: 
                    311:     if ($dischash{$toggkey}) {
                    312:         $currtogg = $lt{'toggon'};
                    313:         $toggchange = $lt{'toggoff'};
                    314:         $togglink = 'toggoff';
                    315:     } 
1.97      raeburn   316:    
1.111     raeburn   317:     $chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;
1.84      raeburn   318: 
                    319:     if ($newpostsflag) {
1.97      raeburn   320:         $chglink .= '&previous='.$prevread;
1.84      raeburn   321:     }
                    322: 
1.67      www       323:     if ($visible) {
1.80      raeburn   324: # Print the discusssion
1.116     raeburn   325:         if ($outputtarget eq 'tex') {
1.156     albertel  326:             $discussion.='<tex>{\tiny \vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.
1.116     raeburn   327:                          '\textbf{DISCUSSIONS}\makebox[2 cm][b]{\hrulefill}'.
                    328:                          '\vskip 0 mm\noindent\textbf{'.$lt{'cuse'}.'}:\vskip 0 mm'.
                    329:                          '\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.
1.156     albertel  330:                          '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}}</tex>';
1.116     raeburn   331:         } elsif ($outputtarget eq 'export') {
                    332: # Create temporary directory if this is an export
                    333:             my $now = time;
1.147     raeburn   334:             if ((defined($imsextras)) && ($$imsextras{'caller'} eq 'imsexport')) {
                    335:                 $tempexport = $$imsextras{'tempexport'};
                    336:                 if (!-e $tempexport) {
                    337:                     mkdir($tempexport,0700);
                    338:                 }
                    339:                 $tempexport .= '/'.$$imsextras{'count'};
                    340:                 if (!-e $tempexport) {
                    341:                     mkdir($tempexport,0700);
                    342:                 }
                    343:             } else {
                    344:                 $tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';
                    345:                 if (!-e $tempexport) {
                    346:                     mkdir($tempexport,0700);
                    347:                 }
                    348:                 $tempexport .= '/'.$now;
                    349:                 if (!-e $tempexport) {
                    350:                     mkdir($tempexport,0700);
                    351:                 }
1.157     albertel  352:                 $tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'};
1.116     raeburn   353:             }
                    354:             if (!-e $tempexport) {
                    355:                 mkdir($tempexport,0700);
                    356:             }
                    357: # open manifest file
                    358:             my $manifest = '/imsmanifest.xml';
                    359:             my $manifestfilename = $tempexport.$manifest;
                    360:             if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {
                    361:                 $manifestok=1;
                    362:                 print $manifestfile qq|
                    363: <?xml version="1.0" encoding="UTF-8"?>
                    364: <manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2" 
                    365: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    366: identifier="MANIFEST-$ressymb" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 
                    367: imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">
                    368:   <organizations default="$ressymb">
                    369:     <organization identifier="$ressymb">
                    370:       <title>Discussion for $ressymb</title>\n|;
                    371:             } else {
                    372:                 $discussion .= 'An error occurred opening the manifest file.<br />';
                    373:             }
                    374: 	} else {
1.97      raeburn   375:             my $colspan=$maxdepth+1;
1.102     raeburn   376:             $discussion.= qq|
                    377: <script>
                    378:    function studentdelete (symb,idx,newflag,previous) {
                    379:        var symbparm = symb+':::'+idx
                    380:        var prevparm = ""
                    381:        if (newflag == 1) {
                    382:            prevparm = "&previous="+previous
                    383:        }
                    384:        if (confirm("Are you sure you want to delete this post?\\nDeleted posts will no longer be visible to you and other students,\\nbut will continue to be visible to your instructor")) {
                    385:            document.location.href = "/adm/feedback?hide="+symbparm+prevparm
                    386:        }  
                    387:    }
                    388: </script>
                    389:             |;
1.134     albertel  390: 	    $discussion.='<form name="readchoices" method="post" action="/adm/feedback?chgreads='.$ressymb.'" ><table bgcolor="#AAAAAA" cellpadding="2" cellspacing="2" border="0">';
1.97      raeburn   391: 	    $discussion .='<tr><td bgcolor="#DDDDBB" colspan="'.$colspan.'">'.
1.95      sakharuk  392: 		'<table border="0" width="100%" bgcolor="#DDDDBB"><tr>';
                    393: 	    if ($visible>2) {
                    394: 		$discussion.='<td align="left">'.
1.137     albertel  395: 		    '<a href="/adm/feedback?cmd=threadedon&amp;symb='.$ressymb;
1.95      sakharuk  396: 		if ($newpostsflag) {
                    397: 		    $discussion .= '&previous='.$prevread;
                    398: 		}
                    399: 		$discussion .='">'.&mt('Threaded View').'</a>&nbsp;&nbsp;'.
1.137     albertel  400: 		    '<a href="/adm/feedback?cmd=threadedoff&amp;symb='.$ressymb;
1.95      sakharuk  401: 		if ($newpostsflag) {
                    402: 		    $discussion .= '&previous='.$prevread;
                    403: 		}
1.100     raeburn   404: 		$discussion .='">'.&mt('Chronological View').'</a>&nbsp;&nbsp;
1.137     albertel  405:                               <a href= "/adm/feedback?cmd=sortfilter&amp;symb='.$ressymb;
1.100     raeburn   406:                 if ($newpostsflag) {
                    407:                     $discussion .= '&previous='.$prevread;
                    408:                 }
                    409:                 $discussion .='">'.&mt('Sorting/Filtering options').'</a>&nbsp;&nbsp';
                    410:             } else {
                    411:                 $discussion .= '<td align="left">';
                    412:             }
                    413:             $discussion .='<a href= "/adm/feedback?export='.$ressymb;
                    414:             if ($newpostsflag) {
                    415:                 $discussion .= '&previous='.$prevread;
                    416:             }
                    417:             $discussion .= '">'.&mt('Export').'?</a>&nbsp;&nbsp;</td>';
1.95      sakharuk  418: 	    if ($newpostsflag) {
                    419: 		if (!$markondisp) {
1.137     albertel  420: 		    $discussion .='<td align="right"><a href="/adm/feedback?markread=1&amp;symb='.$ressymb.'">'.&mt('Mark NEW posts no longer new').'</a>&nbsp;&nbsp;';
1.95      sakharuk  421: 		} else {
                    422: 		    $discussion .= '<td>&nbsp;</td>';
                    423: 		}
                    424: 	    } else {
                    425: 		$discussion .= '<td>&nbsp;</td>';
                    426: 	    }
                    427: 	    $discussion .= '</tr></table></td></tr>';
1.116     raeburn   428: 
                    429:             my $numhidden = keys %notshown;
                    430:             if ($numhidden > 0) {
                    431:                 my $colspan = $maxdepth+1;
                    432:                 $discussion.="\n".'<tr><td bgcolor="#CCCCCC" colspan="'.$colspan.'">'.
1.145     raeburn   433:                          '<a href="/adm/feedback?allposts=1&amp;symb='.$ressymb;
1.116     raeburn   434:                 if ($newpostsflag) {
                    435:                     $discussion .= '&previous='.$prevread;
                    436:                 }
                    437:                 $discussion .= '">'.&mt('Show all posts').'</a> '.&mt('to display').' '.
1.111     raeburn   438:                          $numhidden.' ';
1.116     raeburn   439:                 if ($showunmark) {
                    440:                     $discussion .= &mt('posts previously marked read');
                    441:                 } else {
                    442:                     $discussion .= &mt('previously viewed posts');
                    443:                 }
                    444:                 $discussion .= '<br/></td></tr>';
1.111     raeburn   445:             }
1.80      raeburn   446:         }
1.100     raeburn   447: 
                    448: # Choose sort mechanism
                    449:         my @showposts = ();
                    450:         if ($sortposts eq 'descdate') {
                    451:             @showposts = (sort { $b <=> $a } keys %alldiscussion);
                    452:         } elsif ($sortposts eq 'thread') {
                    453:             @showposts = (sort { $a <=> $b } keys %alldiscussion);
                    454:         } elsif ($sortposts eq 'subject') {
                    455:             foreach (sort keys %subjectsort) {
                    456:                 push @showposts, @{$subjectsort{$_}};
                    457:             }
                    458:         } elsif ($sortposts eq 'username') {
                    459:             foreach my $domain (sort keys %usernamesort) {
                    460:                 foreach (sort keys %{$usernamesort{$domain}}) {
                    461:                     push @showposts, @{$usernamesort{$domain}{$_}};
                    462:                 }
                    463:             }
                    464:         } elsif ($sortposts eq 'lastfirst') {
                    465:             foreach my $last (sort keys %namesort) {
                    466:                  foreach (sort keys %{$namesort{$last}}) {
                    467:                      push @showposts, @{$namesort{$last}{$_}};
                    468:                  }
                    469:             }
                    470:         } else {
                    471:             @showposts =  (sort { $a <=> $b } keys %alldiscussion);
                    472:         }
1.116     raeburn   473:         my $currdepth = 0;
                    474:         my $firstidx = $alldiscussion{$showposts[0]};
1.100     raeburn   475:         foreach (@showposts) {
1.157     albertel  476:             unless (($sortposts eq 'thread') || (($sortposts eq '') && ($env{'environment.threadeddiscussion'})) || ($outputtarget eq 'export')) {
1.100     raeburn   477:                 $alldiscussion{$_} = $_;
                    478:             }
1.101     raeburn   479:             unless ( ($notshown{$alldiscussion{$_}} eq '1') || ($shown{$alldiscussion{$_}} == 0) ) {
1.117     albertel  480:                 if ($outputtarget ne 'tex' && $outputtarget ne 'export') {
1.95      sakharuk  481: 		    $discussion.="\n<tr>";
                    482: 		}
1.80      raeburn   483: 	        my $thisdepth=$depth[$alldiscussion{$_}];
1.117     albertel  484:                 if ($outputtarget ne 'tex' && $outputtarget ne 'export') {
1.95      sakharuk  485: 		    for (1..$thisdepth) {
                    486: 			$discussion.='<td>&nbsp;&nbsp;&nbsp;</td>';
                    487: 		    }
                    488: 		}
1.80      raeburn   489: 	        my $colspan=$maxdepth-$thisdepth+1;
1.116     raeburn   490:                 if ($outputtarget eq 'tex') {
1.95      sakharuk  491: 		    #cleanup block
                    492: 		    $discussionitems[$alldiscussion{$_}]=~s/<table([^>]*)>/<table TeXwidth="90 mm">/;
                    493: 		    $discussionitems[$alldiscussion{$_}]=~s/<tr([^>]*)><td([^>]*)>/<tr><td TeXwidth="20 mm" align="left">/;
                    494:                     my $threadinsert='';
                    495:                     if ($thisdepth > 0) {
                    496: 			$threadinsert='<br /><strong>Reply: '.$thisdepth.'</strong>';
                    497: 		    }
                    498: 		    $discussionitems[$alldiscussion{$_}]=~s/<\/td><td([^>]*)>/$threadinsert<\/td><td TeXwidth="65 mm" align="left">/;
1.102     raeburn   499: 		    $discussionitems[$alldiscussion{$_}]=~s/<a([^>]+)>(Edit|Hide|Delete|Reply|Submissions)<\/a>//g;
1.95      sakharuk  500:                     $discussionitems[$alldiscussion{$_}]=~s/(<b>|<\/b>|<\/a>|<a([^>]+)>)//g;
1.114     sakharuk  501: 
                    502: 		    $discussionitems[$alldiscussion{$_}]='<tex>\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}</tex>'.$discussionitems[$alldiscussion{$_}];
                    503: 		    $discussion.=$discussionitems[$alldiscussion{$_}];
1.116     raeburn   504: 		} elsif ($outputtarget eq 'export') {
                    505:                     my $postfilename = $alldiscussion{$_}.'-'.$imsitems{$alldiscussion{$_}}{'timestamp'}.'.html';
                    506:                     if ($manifestok) {
                    507:                         if (($depth[$alldiscussion{$_}] <= $currdepth) && ($alldiscussion{$_} != $firstidx)) {
                    508:                             print $manifestfile '  </item>'."\n";
                    509:                         }
                    510:                         $currdepth = $depth[$alldiscussion{$_}];
                    511:                         print $manifestfile "\n". 
                    512:       '<item identifier="ITEM-'.$ressymb.'-'.$alldiscussion{$_}.'" isvisible="'.
                    513:         $imsitems{$alldiscussion{$_}}{'isvisible'}.'" identifieref="RES-'.$ressymb.'-'.$alldiscussion{$_}.'">'.
                    514:         '<title>'.$imsitems{$alldiscussion{$_}}{'title'}.'</title>';
                    515:                         $imsresources .= "\n".
1.146     raeburn   516:     '<resource identifier="RES-'.$ressymb.'-'.$alldiscussion{$_}.'" type="webcontent" href="'.$postfilename.'">'."\n".
                    517:       '<file href="'.$postfilename.'">'."\n".
1.116     raeburn   518:       $imsfiles{$alldiscussion{$_}}{$imsitems{$alldiscussion{$_}}{'currversion'}}."\n".
                    519:     '</resource>';
                    520:                     }
                    521:                     my $postingfile;
                    522:                     my $postingfilename = $tempexport.'/'.$postfilename;
                    523:                     if ($postingfile = Apache::File->new('>'.$postingfilename)) {
                    524:                         print $postingfile '<html><head><title>Discussion Post</title></head><body>'.
                    525:                                            $imsitems{$alldiscussion{$_}}{'title'}.' '.
                    526:                                            $imsitems{$alldiscussion{$_}}{'sender'}.
                    527:                                            $imsitems{$alldiscussion{$_}}{'timestamp'}.'<br /><br />'.
                    528:                                            $imsitems{$alldiscussion{$_}}{'message'}.'<br />'.
                    529:                                            $imsitems{$alldiscussion{$_}}{'attach'}.'</body></html>'."\n"; 
                    530:                         close($postingfile);
                    531:                     } else {
                    532:                         $discussion .= 'An error occurred opening the export file for posting '.$alldiscussion{$_}.'<br />';
                    533:                     }
                    534:                     $copyresult.=&replicate_attachments($imsitems{$alldiscussion{$_}}{'allattachments'},$tempexport);
                    535:                 } else {
                    536:                     $discussion.='<td  bgcolor="'.$bgcols[$newitem{$alldiscussion{$_}}].
                    537:                        '" colspan="'.$colspan.'">'. $discussionitems[$alldiscussion{$_}].
                    538:                        '</td></tr>';
                    539:                 }
1.69      www       540: 	    }
1.80      raeburn   541:         }
1.116     raeburn   542: 	unless ($outputtarget eq 'tex' || $outputtarget eq 'export') {
1.97      raeburn   543:             my $colspan=$maxdepth+1;
1.111     raeburn   544:             $discussion .= <<END;
1.97      raeburn   545:             <tr bgcolor="#FFFFFF">
1.98      raeburn   546:              <td colspan="$colspan" valign="top">
1.97      raeburn   547:               <table border="0" bgcolor="#FFFFFF" width="100%" cellspacing="2" cellpadding="2">
                    548:                <tr>
                    549:                 <td align="left">
                    550:                  <table border="0" cellpadding="0" cellspacing="4">
                    551:                   <tr>
                    552:                    <td>
                    553:                     <font size="-1"><b>$lt{'cuse'}</b>:</td>
                    554:                    <td>&nbsp;</td>
1.111     raeburn   555:                    <td><font size="-1">
1.97      raeburn   556: END
                    557:             if ($newpostsflag) {
                    558:                 $discussion .= 
1.111     raeburn   559:                    '1.&nbsp;'.$lt{'disp'}.'&nbsp;-&nbsp;<i>'.$currdisp.'</i>&nbsp;&nbsp;2.&nbsp;'.$lt{'nolo'}.'&nbsp;-&nbsp;<i>'.$currmark.'</i>';
                    560:                 if ($dischash{$toggkey}) {
                    561:                    $discussion .= '&nbsp;&nbsp;3.&nbsp;'.$lt{'togg'}.'&nbsp;-&nbsp;<i>'.$currtogg.'</i>';
                    562:                 }
1.97      raeburn   563:             } else {
1.111     raeburn   564:                 if ($dischash{$toggkey}) {
                    565:                    $discussion .= '1.&nbsp;'.$lt{'disp'}.'&nbsp;-&nbsp;<i>'.$currdisp.'</i>&nbsp;2.&nbsp;'.$lt{'togg'}.'&nbsp;-&nbsp;<i>'.$currtogg.'</i>';
                    566:                 } else {
                    567:                     $discussion .=
                    568:                          $lt{'disp'}.'&nbsp;-&nbsp;<i>'.$currdisp.'</i>';
                    569:                 }
1.97      raeburn   570:             }
                    571:             $discussion .= <<END;
1.111     raeburn   572:                    </font></td>
1.97      raeburn   573:                    <td>&nbsp;</td>
1.144     raeburn   574:                    <td align="left">
1.111     raeburn   575:                     <font size="-1"><b><a href="$chglink">$lt{'chgt'}</a>?</font></b>
                    576:                    </td>
1.97      raeburn   577:                   </tr>
                    578:                  </table>
                    579:                 </td>
1.111     raeburn   580: END
1.143     raeburn   581:             if ($sortposts) {
                    582:                 my %sort_types = ();
                    583:                 my %role_types = ();
                    584:                 my %status_types = ();
                    585:                 &sort_filter_names(\%sort_types,\%role_types,\%status_types);
                    586: 
                    587:                 $discussion .= '<td><font size="-1"><b>'.&mt('Sorted by').'</b>: '.$sort_types{$sortposts}.'<br />';
1.157     albertel  588:                 if (defined($env{'form.totposters'})) {
1.144     raeburn   589:                     $discussion .= &mt('Posts by').':';
1.143     raeburn   590:                     if ($totposters > 0) {
                    591:                         foreach my $poster (@posters) {
                    592:                             $poster =~ s/:/\@/;
1.144     raeburn   593:                             $discussion .= ' '.$poster.',';
1.143     raeburn   594:                         }
1.144     raeburn   595:                         $discussion =~ s/,$//;
1.143     raeburn   596:                     } else {
                    597:                         $discussion .= &mt('None selected');
                    598:                     }
                    599:                 } else {
                    600:                     my $filterchoice ='';
                    601:                     if (@sectionpick > 0) {
1.157     albertel  602:                         $filterchoice = '<i>'.&mt('sections').'</i>-&nbsp;'.$env{'form.sectionpick'};
1.143     raeburn   603:                         $filterchoice .= '&nbsp;&nbsp;&nbsp; ';
                    604:                     }
                    605:                     if (@rolefilter > 0) {
1.144     raeburn   606:                         $filterchoice .= '<i>'.&mt('roles').'</i>-';
1.143     raeburn   607:                         foreach (@rolefilter) {
1.144     raeburn   608:                             $filterchoice .= '&nbsp;'.$role_types{$_}.',';
1.143     raeburn   609:                         }
1.144     raeburn   610:                         $filterchoice =~ s/,$//;
                    611:                         $filterchoice .= '<br />&nbsp;&nbsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp&nbsp;';
1.143     raeburn   612:                     }
                    613:                     if ($statusfilter) {
                    614:                         $filterchoice .= '<i>'.&mt('status').'</i>-&nbsp;'.$status_types{$statusfilter};
                    615:                     }
                    616:                     if ($filterchoice) {
                    617:                         $discussion .= '<b>'.&mt('Filters').'</b>:&nbsp;'.$filterchoice;
                    618:                     }
                    619:                     $discussion .= '</font></td>';
                    620:                 }
                    621:             }
1.111     raeburn   622:             if ($dischash{$toggkey}) {
                    623:                 my $storebutton = &mt('Store read/unread changes');
                    624:                 $discussion.='<td align="right">'.
                    625:               '<input type="hidden" name="discsymb" value="'.$ressymb.'">'."\n".
                    626:               '<input type="button" name="readoptions" value="'.$storebutton.'"'.
                    627:               ' onClick="this.form.submit();">'."\n".
                    628:               '</td>';
                    629:             }
                    630:             $discussion .= (<<END);
1.97      raeburn   631:                </tr>
                    632:               </table>
                    633:              </td>
                    634:             </tr>
                    635:            </table>
1.134     albertel  636:            <br /><br /></form>
1.97      raeburn   637: END
1.114     sakharuk  638:         } 
1.116     raeburn   639:         if ($outputtarget eq 'export') {
                    640:             if ($manifestok) {
                    641:                 while ($currdepth > 0) {
                    642:                     print $manifestfile "    </item>\n";
                    643:                     $currdepth --;
                    644:                 }
                    645:                 print $manifestfile qq|
                    646:     </organization>
                    647:   </organizations>
                    648:   <resources>
                    649:     $imsresources
                    650:   </resources>
                    651: </manifest>
                    652:                 |;
                    653:                 close($manifestfile);
1.147     raeburn   654:                 if ((defined($imsextras)) && ($$imsextras{'caller'} eq 'imsexport')) {
                    655:                     $discussion = $copyresult;
                    656:                 } else {
1.116     raeburn   657: 
                    658: #Create zip file in prtspool
                    659: 
1.147     raeburn   660:                     my $imszipfile = '/prtspool/'.
1.157     albertel  661:                     $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
1.147     raeburn   662:                          time.'_'.rand(1000000000).'.zip';
                    663:                     my $cwd = &getcwd(); 
                    664:                     my $imszip = '/home/httpd/'.$imszipfile;
                    665:                     chdir $tempexport;
                    666:                     open(OUTPUT, "zip -r $imszip *  2> /dev/null |");
                    667:                     close(OUTPUT);
                    668:                     chdir $cwd;
                    669:                     $discussion .= 'Download the zip file from <a href="'.$imszipfile.'">Discussion Posting Archive</a><br />';
                    670:                     if ($copyresult) {
                    671:                         $discussion .= 'The following errors occurred during export - <br />'.$copyresult;
                    672:                     }
1.116     raeburn   673:                 }
                    674:             } else {
                    675:                 $discussion .= '<br />Unfortunately you will not be able to retrieve an archive of the discussion posts at this time, because there was a problem creating a manifest file.<br />';
                    676:             }
                    677:             return $discussion;
                    678:         }
1.54      www       679:     }
                    680:     if ($discussiononly) {
1.108     raeburn   681:         my $now = time;
                    682:         my $attachnum = 0;
                    683:         my $newattachmsg = '';
                    684:         my @currnewattach = ();
                    685:         my @currdelold = ();
                    686:         my $comment = '';
                    687:         my $subject = '';
1.157     albertel  688:         if ($env{'form.origpage'}) {
1.108     raeburn   689:             &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['addnewattach','deloldattach','delnewattach','timestamp','idx','subject','comment']);
1.157     albertel  690:             $subject = &Apache::lonnet::unescape($env{'form.subject'});
                    691:             $comment = &Apache::lonnet::unescape($env{'form.comment'});
1.108     raeburn   692:             my @keepold = ();
                    693:             &process_attachments(\@currnewattach,\@currdelold,\@keepold);
                    694:             if (@currnewattach > 0) {
                    695:                 $attachnum += @currnewattach;
                    696:             }
                    697:         }
1.122     raeburn   698: 	if (&discussion_open($status)) {
                    699: 	    $discussion.=(<<ENDDISCUSS);
1.54      www       700: <form action="/adm/feedback" method="post" name="mailform" enctype="multipart/form-data">
                    701: <input type="submit" name="discuss" value="Post Discussion" />
                    702: <input type="submit" name="anondiscuss" value="Post Anonymous Discussion" />
1.73      albertel  703: <input type="hidden" name="symb" value="$ressymb" />
1.54      www       704: <input type="hidden" name="sendit" value="true" />
1.108     raeburn   705: <input type="hidden" name="timestamp" value="$now" />
                    706: <br /><a name="newpost"></a>
                    707: <font size="1">Note: in anonymous discussion, your name is visible only 
                    708: to course faculty</font><br />
                    709: <b>Title:</b>&nbsp;<input type="text" name="subject" value="$subject" size="30" /><br /><br />
                    710: <textarea name="comment" cols="80" rows="14" wrap="hard">$comment</textarea>
1.54      www       711: ENDDISCUSS
1.157     albertel  712:             if ($env{'form.origpage'}) {
                    713:                 $discussion.='<input type="hidden" name="origpage" value="'.$env{'form.origpage'}.'" />'."\n";
1.140     raeburn   714:                 foreach (@currnewattach) {
                    715:                     $discussion.='<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";
                    716:                 }
                    717:             }
                    718:             $discussion.="</form>\n";
                    719:             if ($outputtarget ne 'tex') {
                    720:                 $discussion.=&generate_attachments_button('',$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,'',$mode);
                    721:                 if (@currnewattach > 0) {
                    722:                     $newattachmsg .= '<b>New attachments</b><br />';
                    723:                     if (@currnewattach > 1) {
                    724:                         $newattachmsg .= '<ol>';
                    725:                         foreach my $item (@currnewattach) {
                    726:                             $item =~ m#.*/([^/]+)$#;
                    727:                             $newattachmsg .= '<li><a href="'.$item.'">'.$1.'</a></li>'."\n";
                    728:                         }
                    729:                         $newattachmsg .= '</ol>'."\n";
                    730:                     } else {
                    731:                         $currnewattach[0] =~ m#.*/([^/]+)$#;
                    732:                         $newattachmsg .= '<a href="'.$currnewattach[0].'">'.$1.'</a><br />'."\n";
1.108     raeburn   733:                     }
                    734:                 }
1.140     raeburn   735:                 $discussion.=$newattachmsg;
                    736: 	        $discussion.=&generate_preview_button();
                    737: 	    }
1.95      sakharuk  738: 	}
1.140     raeburn   739:     } else {
                    740:         if (&discussion_open($status) &&
                    741:             &Apache::lonnet::allowed('pch',
1.157     albertel  742:     	        $env{'request.course.id'}.
                    743: 	        ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
1.95      sakharuk  744: 	    if ($outputtarget ne 'tex') {
                    745: 		$discussion.='<table bgcolor="#BBBBBB"><tr><td><a href="/adm/feedback?replydisc='.
1.129     albertel  746: 		    $ressymb.':::" '.$target.'>'.
1.148     albertel  747: 		    '<img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" border="0" />'.
1.95      sakharuk  748: 		    &mt('Post Discussion').'</a></td></tr></table>';
                    749: 	    }
1.100     raeburn   750: 	}
1.74      www       751:     }
1.114     sakharuk  752:     return $discussion;
1.54      www       753: }
1.1       www       754: 
1.116     raeburn   755: sub build_posting_display {
                    756:     my ($usernamesort,$subjectsort,$namesort,$notshown,$newitem,$dischash,$shown,$alldiscussion,$imsitems,$imsfiles,$roleinfo,$discussionitems,$replies,$depth,$posters,$maxdepth,$visible,$newpostsflag,$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$ressymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$statusfilter,$toggkey,$outputtarget) = @_;
                    757:     my @original=();
                    758:     my @index=();
1.133     albertel  759:     my $symb=&Apache::lonenc::check_decrypt($ressymb);
1.157     albertel  760:     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                    761: 			  $env{'course.'.$env{'request.course.id'}.'.domain'},
                    762: 			  $env{'course.'.$env{'request.course.id'}.'.num'});
1.116     raeburn   763: 
                    764:     if ($contrib{'version'}) {
                    765:         my $oldest = $contrib{'1:timestamp'};
                    766:         if ($prevread eq '0') {
                    767:             $prevread = $oldest-1;
                    768:         }
1.143     raeburn   769:         my ($skiptest,$rolematch,$roleregexp,$secregexp,$statusregexp);
                    770:         if ($sortposts) {
                    771:             ($skiptest,$roleregexp,$secregexp,$statusregexp) = &filter_regexp($rolefilter,$sectionpick,$statusfilter);
                    772:             $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;
                    773:         } 
1.116     raeburn   774: 	for (my $id=1;$id<=$contrib{'version'};$id++) {
                    775: 	    my $idx=$id;
                    776:             my $posttime = $contrib{$idx.':timestamp'};
                    777:             if ($prevread <= $posttime) {
                    778:                 $$newpostsflag = 1;
                    779:             }
                    780: 	    my $hidden=($contrib{'hidden'}=~/\.$idx\./);
                    781:             my $studenthidden=($contrib{'studenthidden'}=~/\.$idx\./);
                    782: 	    my $deleted=($contrib{'deleted'}=~/\.$idx\./);
                    783: 	    my $origindex='0.';
                    784:             my $numoldver=0;
                    785: 	    if ($contrib{$idx.':replyto'}) {
1.157     albertel  786:                 if ( (($env{'environment.threadeddiscussion'}) && ($sortposts eq '')) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) {
1.116     raeburn   787: # this is a follow-up message
                    788: 		    $original[$idx]=$original[$contrib{$idx.':replyto'}];
                    789: 		    $$depth[$idx]=$$depth[$contrib{$idx.':replyto'}]+1;
                    790: 		    $origindex=$index[$contrib{$idx.':replyto'}];
                    791: 		    if ($$depth[$idx]>$$maxdepth) { $$maxdepth=$$depth[$idx]; }
                    792:                 } else {
                    793:                     $original[$idx]=0;
                    794:                     $$depth[$idx]=0;
                    795:                 }
                    796: 	    } else {
                    797: # this is an original message
                    798: 		$original[$idx]=0;
                    799: 		$$depth[$idx]=0;
                    800: 	    }
                    801: 	    if ($$replies[$$depth[$idx]]) {
                    802: 		$$replies[$$depth[$idx]]++;
                    803: 	    } else {
                    804: 		$$replies[$$depth[$idx]]=1;
                    805: 	    }
                    806: 	    unless ((($hidden) && (!$seeid)) || ($deleted)) {
                    807: 		$$visible++;
                    808:                 if ($contrib{$idx.':history'}) {
                    809:                     if ($contrib{$idx.':history'} =~ /:/) {
                    810:                         my @oldversions = split/:/,$contrib{$idx.':history'};
                    811:                         $numoldver = @oldversions;
                    812:                     } else {
                    813:                         $numoldver = 1;
                    814:                     } 
                    815:                 }
                    816:                 $$current = $numoldver;
                    817: 		my %messages = ();
                    818:                 my %subjects = ();
                    819:                 my %attachtxt = ();
                    820:                 my %allattachments = ();
                    821:                 my ($screenname,$plainname);
                    822:                 my $sender = &mt('Anonymous');
                    823:                 my ($message,$subject,$vgrlink,$ctlink);
                    824:                 &get_post_contents(\%contrib,$idx,$seeid,$outputtarget,\%messages,\%subjects,\%allattachments,\%attachtxt,$imsfiles,\$screenname,\$plainname,$numoldver);
                    825: 
                    826: 
                    827: # Set up for sorting by subject
                    828:                 unless ($outputtarget eq 'export') {
                    829:                     $message=$messages{$numoldver};
                    830:                     $message.=$attachtxt{$numoldver};
                    831:                     $subject=$subjects{$numoldver};
                    832:                     if ($message) {
                    833: 	  	        if ($hidden) {
                    834: 			    $message='<font color="#888888">'.$message.'</font>';
                    835:                             if ($studenthidden) {
                    836:                                 $message .='<br /><br />Deleted by poster (student).';
                    837:                             }
                    838: 		        }
                    839: 
                    840:                         if ($subject eq '') {
                    841:                            if (defined($$subjectsort{'__No subject'})) {
                    842:                                push @{$$subjectsort{'__No subject'}}, $idx;
                    843:                            } else {
                    844:                                @{$$subjectsort{'__No subject'}} = ("$idx");
                    845:                            }
                    846:                         } else {
                    847:                             if (defined($$subjectsort{$subject})) {
                    848:                                push @{$$subjectsort{$subject}}, $idx;
                    849:                             } else {
                    850:                                @{$$subjectsort{$subject}} = ("$idx");
                    851:                             }
                    852:                         }
                    853: 		        if ((!$contrib{$idx.':anonymous'}) || ($seeid)) {
                    854: 			    $sender=&Apache::loncommon::aboutmewrapper(
                    855: 					 $plainname,
                    856: 					 $contrib{$idx.':sendername'},
                    857: 					 $contrib{$idx.':senderdomain'}).' ('.
                    858: 					 $contrib{$idx.':sendername'}.' at '.
                    859: 					 $contrib{$idx.':senderdomain'}.')';
                    860: 			    if ($contrib{$idx.':anonymous'}) {
                    861: 			        $sender.=' ['.&mt('anonymous').'] '.
                    862: 				    $screenname;
                    863: 			    }
                    864: 
                    865: # Set up for sorting by domain, then username
                    866:                             unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) {
                    867:                                 %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = ();
                    868:                             }
                    869:                             if (defined($$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}})) {
                    870:                                 push @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx;
                    871:                             } else {
                    872:                                 @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}} = ("$idx");
                    873:                             }
                    874: # Set up for sorting by last name, then first name
                    875:                             my %names = &Apache::lonnet::get('environment',
                    876:                                  ['firstname','lastname'],$contrib{$idx.':senderdomain'},
                    877:                                   ,$contrib{$idx.':sendername'});
                    878:                             my $lastname = $names{'lastname'};
                    879:                             my $firstname = $names{'firstname'};
                    880:                             if ($lastname eq '') {
                    881:                                 $lastname = '_';
                    882:                             }
                    883:                             if ($firstname eq '') {
                    884:                                 $firstname = '_';
                    885:                             }
                    886:                             unless (defined($$namesort{$lastname})) {
                    887:                                 %{$$namesort{$lastname}} = ();
                    888:                             }
                    889:                             if (defined($$namesort{$lastname}{$firstname})) {
                    890:                                 push @{$$namesort{$lastname}{$firstname}}, $idx;
                    891:                             } else {
                    892:                                 @{$$namesort{$lastname}{$firstname}} = ("$idx");
                    893:                             }
1.157     albertel  894:                             if ($env{'course.'.$env{'request.course.id'}.'.allow_discussion_post_editing'} =~ m/yes/i) {
                    895:                                 if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) {
1.116     raeburn   896:                                     $sender.=' <a href="/adm/feedback?editdisc='.
                    897:                                          $ressymb.':::'.$idx;
                    898:                                     if ($newpostsflag) {
                    899:                                         $sender .= '&previous='.$prevread;
                    900:                                     }
                    901:                                     $sender .= '" '.$target.'>'.&mt('Edit').'</a>';                                             
                    902:                                     unless ($seeid) {
                    903:                                         $sender.=" <a href=\"javascript:studentdelete('$ressymb','$idx','$newpostsflag','$prevread')";
                    904:                                         $sender .= '">'.&mt('Delete').'</a>';
                    905:                                     }
                    906:                                 }
                    907:                             } 
                    908: 			    if ($seeid) {
                    909: 			        if ($hidden) {
                    910:                                     unless ($studenthidden) {
                    911: 			                $sender.=' <a href="/adm/feedback?unhide='.
                    912: 				                $ressymb.':::'.$idx;
                    913:                                         if ($newpostsflag) {
                    914:                                              $sender .= '&previous='.$prevread;
                    915:                                         }
                    916:                                         $sender .= '">'.&mt('Make Visible').'</a>';
                    917:                                     }
                    918: 			        } else {
                    919: 				    $sender.=' <a href="/adm/feedback?hide='.
                    920: 				        $ressymb.':::'.$idx;
                    921:                                     if ($newpostsflag) {
                    922:                                         $sender .= '&previous='.$prevread;
                    923:                                     }
                    924:                                     $sender .= '">'.&mt('Hide').'</a>';
                    925: 			        }                     
                    926: 			        $sender.=' <a href="/adm/feedback?deldisc='.
                    927: 				        $ressymb.':::'.$idx;
                    928:                                 if ($newpostsflag) {
                    929:                                     $sender .= '&previous='.$prevread;
                    930:                                 }
                    931:                                 $sender .= '">'.&mt('Delete').'</a>';
                    932:                             }
                    933: 		        } else {
                    934: 			    if ($screenname) {
                    935: 			        $sender='<i>'.$screenname.'</i>';
                    936: 			    }
                    937: # Set up for sorting by domain, then username for anonymous
                    938:                             unless (defined($$usernamesort{'__anon'})) {
                    939:                                 %{$$usernamesort{'__anon'}} = ();
                    940:                             }
                    941:                             if (defined($$usernamesort{'__anon'}{'__anon'})) {
                    942:                                 push @{$$usernamesort{'__anon'}{'__anon'}}, $idx;
                    943:                             } else {
                    944:                                 @{$$usernamesort{'__anon'}{'__anon'}} = ("$idx");
                    945:                             }
                    946: # Set up for sorting by last name, then first name for anonymous
                    947:                             unless (defined($$namesort{'__anon'})) {
                    948:                                 %{$$namesort{'__anon'}} = ();
                    949:                             }
                    950:                             if (defined($$namesort{'__anon'}{'__anon'})) {
                    951:                                 push @{$$namesort{'__anon'}{'__anon'}}, $idx;
                    952:                             } else {
                    953:                                 @{$$namesort{'__anon'}{'__anon'}} = ("$idx");
                    954:                             }
                    955: 		        }
                    956: 		        if (&discussion_open($status) &&
                    957: 			        &Apache::lonnet::allowed('pch',
1.157     albertel  958: 						 $env{'request.course.id'}.
                    959: 						 ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
1.116     raeburn   960: 			    $sender.=' <a href="/adm/feedback?replydisc='.
                    961: 			            $ressymb.':::'.$idx;
                    962:                             if ($newpostsflag) {
                    963:                                     $sender .= '&previous='.$prevread;
                    964:                             }
                    965:                             $sender .= '" '.$target.'>'.&mt('Reply').'</a>';
                    966:                         }
                    967: 		        if ($viewgrades) {
                    968: 			        $vgrlink=&Apache::loncommon::submlink('Submissions',
                    969:                             $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb);
                    970: 		        }
                    971:                         if ($$dischash{$readkey}=~/\.$idx\./) { 
1.151     albertel  972:                             $ctlink = '<label><b>'.&mt('Mark unread').'?</b>&nbsp;<input type="checkbox" name="postunread_'.$idx.'" /></label>';
1.116     raeburn   973:                         } else {
1.151     albertel  974:                             $ctlink = '<label><b>'.&mt('Mark read').'?</b>&nbsp;<input type="checkbox" name="postread_'.$idx.'" /></label>';
1.116     raeburn   975:                         }
                    976:                     }
                    977: #figure out at what position this needs to print
                    978:                 }
                    979:                 if ($outputtarget eq 'export' || $message) {
                    980: 		    my $thisindex=$idx;
1.157     albertel  981: 		    if ( (($env{'environment.threadeddiscussion'}) && ($sortposts eq '')) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) {
1.116     raeburn   982: 			$thisindex=$origindex.substr('00'.$$replies[$$depth[$idx]],-2,2);
                    983: 		    }
                    984: 		    $$alldiscussion{$thisindex}=$idx;
                    985:                     $$shown{$idx} = 0;
                    986:                     $index[$idx]=$thisindex;
                    987:                 }
                    988:                 if ($outputtarget eq 'export') {
                    989:                     %{$$imsitems{$idx}} = ();
                    990:                     $$imsitems{$idx}{'isvisible'}='true';
                    991:                     if ($hidden) {
                    992:                         $$imsitems{$idx}{'isvisible'}='false';
                    993:                     }
                    994:                     $$imsitems{$idx}{'title'}=$subjects{$numoldver};
                    995:                     $$imsitems{$idx}{'message'}=$messages{$numoldver};
                    996:                     $$imsitems{$idx}{'attach'}=$attachtxt{$numoldver};
                    997:                     $$imsitems{$idx}{'timestamp'}=$contrib{$idx.':timestamp'};
                    998:                     $$imsitems{$idx}{'sender'}=$plainname.' ('.
                    999:                                          $contrib{$idx.':sendername'}.' at '.
                   1000:                                          $contrib{$idx.':senderdomain'}.')';
                   1001:                     $$imsitems{$idx}{'isanonymous'}='false';
                   1002:                     if ($contrib{$idx.':anonymous'}) {
                   1003:                         $$imsitems{$idx}{'isanonymous'}='true';
                   1004:                     }
                   1005:                     $$imsitems{$idx}{'currversion'}=$numoldver;
                   1006:                     %{$$imsitems{$idx}{'allattachments'}}=%allattachments;
                   1007:                     unless ($messages{$numoldver} eq '' && $attachtxt{$numoldver} eq '') {
                   1008:                         $$shown{$idx} = 1;
                   1009:                     }
                   1010:                 } else {
                   1011:                     if ($message) {
                   1012:                         my $spansize = 2;
                   1013:                         if ($showonlyunread && $prevread > $posttime) {
                   1014:                             $$notshown{$idx} = 1;
                   1015:                         } elsif ($showunmark && $$dischash{$readkey}=~/\.$idx\./) {
                   1016:                             $$notshown{$idx} = 1;
                   1017:                         } else {
                   1018: # apply filters
                   1019:                             my $uname = $contrib{$idx.':sendername'};
                   1020:                             my $udom = $contrib{$idx.':senderdomain'};
                   1021:                             my $poster = $uname.':'.$udom;
1.157     albertel 1022:                             if (defined($env{'form.totposters'})) {
1.143     raeburn  1023:                                 if ($totposters == 0) {
                   1024:                                     $$shown{$idx} = 0;
                   1025:                                 } elsif ($totposters > 0) {
                   1026:                                     if (grep/^$poster$/,@{$posters}) {
                   1027:                                         $$shown{$idx} = 1;
1.116     raeburn  1028:                                     }
                   1029:                                 }
1.143     raeburn  1030:                             } elsif ($sortposts) {
1.116     raeburn  1031:                                 if ($skiptest) {
                   1032:                                     $$shown{$idx} = 1;
                   1033:                                 } else {
                   1034:                                     foreach my $role (@{$$roleinfo{$poster}}) {
1.143     raeburn  1035:                                         if ($role =~ /^cc:/) {
                   1036:                                             my $cc_regexp = $roleregexp.':[^:]*:'.$statusregexp;
                   1037:                                             if ($role =~ /$cc_regexp/) {
                   1038:                                                 $$shown{$idx} = 1;
1.144     raeburn  1039:                                                 last;
1.143     raeburn  1040:                                             }
                   1041:                                         } elsif ($role =~ /^$rolematch$/) {
1.116     raeburn  1042:                                             $$shown{$idx} = 1;
                   1043:                                             last;
                   1044:                                         }
                   1045:                                     }
                   1046:                                 }
1.143     raeburn  1047:                             } else {
                   1048:                                 $$shown{$idx} = 1;
1.116     raeburn  1049:                             }
                   1050:                         }
                   1051:                         unless ($$notshown{$idx} == 1) {
                   1052:                             if ($prevread > 0 && $prevread <= $posttime) {
                   1053:                                 $$newitem{$idx} = 1;
                   1054:                                 $$discussionitems[$idx] .= '
                   1055:                                  <p><table border="0" width="100%">
                   1056:                                   <tr><td align="left"><font color="#FF0000"><b>NEW</b></font></td>';
                   1057:                             } else {
                   1058:                                 $$newitem{$idx} = 0;
                   1059:                                 $$discussionitems[$idx] .= '
                   1060:                                  <p><table border="0" width="100%">
                   1061:                                   <tr><td align="left">&nbsp;</td>';
                   1062:                             }
                   1063:                             $$discussionitems[$idx] .= '<td align ="left">&nbsp;&nbsp;'.
                   1064:                                 '<b>'.$subject.'</b>&nbsp;&nbsp;'.
                   1065:                                 $sender.'</b> '.$vgrlink.' ('.
                   1066:                                 &Apache::lonlocal::locallocaltime($posttime).')</td>';
                   1067:                             if ($$dischash{$toggkey}) {
                   1068:                                 $$discussionitems[$idx].='<td align="right">&nbsp;&nbsp;'.
                   1069:                                   $ctlink.'</td>';
                   1070:                             }
                   1071:                             $$discussionitems[$idx].= '</tr></table><blockquote>'.
                   1072:                                     $message.'</blockquote></p>';
                   1073:                             if ($contrib{$idx.':history'}) {
                   1074:                                 my @postversions = ();
                   1075:                                 $$discussionitems[$idx] .= &mt('This post has been edited by the author.');
                   1076:                                 if ($seeid) {
                   1077:                                     $$discussionitems[$idx] .= '&nbsp;&nbsp;<a href="/adm/feedback?allversions='.$ressymb.':::'.$idx.'">'.&mt('Display all versions').'</a>';
                   1078:                                 }
                   1079:                                 $$discussionitems[$idx].='<br/>'.&mt('Earlier version(s) were posted on: ');
                   1080:                                 if ($contrib{$idx.':history'} =~ m/:/) {
                   1081:                                     @postversions = split/:/,$contrib{$idx.':history'};
                   1082:                                 } else {
                   1083:                                     @postversions = ("$contrib{$idx.':history'}");
                   1084:                                 }
                   1085:                                 for (my $i=0; $i<@postversions; $i++) {
                   1086:                                     my $version = $i+1;
                   1087:                                     $$discussionitems[$idx] .= '<b>'.$version.'.</b> - '.&Apache::lonlocal::locallocaltime($postversions[$i]).'  ';
                   1088:                                 }
                   1089:                             }
                   1090:                         }
                   1091:                     }
                   1092:                 }
                   1093:             }
                   1094: 	}
                   1095:     }
                   1096: }
                   1097: 
1.143     raeburn  1098: sub filter_regexp {
                   1099:     my ($rolefilter,$sectionpick,$statusfilter) = @_;
                   1100:     my ($roleregexp,$secregexp,$statusregexp);
                   1101:     my $skiptest = 1;
                   1102:     if (@{$rolefilter} > 0) {
                   1103:         my @okrolefilter = ();
                   1104:         foreach (@{$rolefilter}) {
                   1105:             unless ($_ eq '') {
                   1106:                 push @okrolefilter, $_;
                   1107:             }
                   1108:         }
                   1109:         if (@okrolefilter > 0) {
                   1110:             if (grep/^all$/,@okrolefilter) {
                   1111:                 $roleregexp='[^:]+';
                   1112:             } else {
                   1113:                 if (@okrolefilter == 1) {
                   1114:                     $roleregexp=$okrolefilter[0];
                   1115:                 } else {
                   1116:                     $roleregexp='('.join('|',@okrolefilter).')';
                   1117:                 }
                   1118:                 $skiptest = 0;
                   1119:             }
                   1120:         }
                   1121:     }
                   1122:     if (@{$sectionpick} > 0) {
                   1123:         my @oksectionpick = ();
                   1124:         foreach (@{$sectionpick}) {
                   1125:             unless ($_ eq '') {
                   1126:                  push @oksectionpick, $_;
                   1127:             }
                   1128:         }
                   1129:         if ((@oksectionpick > 0) && (!grep/^all$/,@oksectionpick)) {
                   1130:             if (@oksectionpick == 1) {
                   1131:                 $secregexp = $oksectionpick[0];
                   1132:             } else {
                   1133:                 $secregexp .= '('.join('|',@oksectionpick).')';
                   1134:             }
                   1135:             $skiptest = 0;
                   1136:         } else {
                   1137:             $secregexp .= '[^:]*';
                   1138:         }
                   1139:     }
                   1140:     if (defined($statusfilter) && $statusfilter ne '') {
                   1141:         if ($statusfilter eq 'all') {
                   1142:             $statusregexp = '[^:]+';
                   1143:         } else {
                   1144:             $statusregexp = $statusfilter;
                   1145:             $skiptest = 0;
                   1146:         }
                   1147:     }
                   1148:     return ($skiptest,$roleregexp,$secregexp,$statusregexp);
                   1149: }
                   1150: 
                   1151: 
1.116     raeburn  1152: sub get_post_contents {
                   1153:     my ($contrib,$idx,$seeid,$type,$messages,$subjects,$allattachments,$attachtxt,$imsfiles,$screenname,$plainname,$numver) = @_;
                   1154:     my $discussion = '';
                   1155:     my $start=$numver;
                   1156:     my $end=$numver + 1;
                   1157:     %{$$imsfiles{$idx}}=();
                   1158:     if ($type eq 'allversions') {
                   1159:        unless($seeid) {
                   1160:            $discussion=&mt('You do not have privileges to view all versions of posts.').&mt('Please select a different role');
                   1161:            return $discussion;
                   1162:        } 
                   1163:     }
1.126     albertel 1164: #    $$screenname=&Apache::loncommon::screenname(
                   1165: #                                        $$contrib{$idx.':sendername'},
                   1166: #                                        $$contrib{$idx.':senderdomain'});
                   1167: #    $$plainname=&Apache::loncommon::nickname(
                   1168: #                                        $$contrib{$idx.':sendername'},
                   1169: #                                        $$contrib{$idx.':senderdomain'});
                   1170:     ($$screenname,$$plainname)=($$contrib{$idx.':screenname'},
                   1171: 				$$contrib{$idx.':plainname'});
1.116     raeburn  1172:     my $sender=&Apache::loncommon::aboutmewrapper(
                   1173:                                  $$plainname,
                   1174:                                  $$contrib{$idx.':sendername'},
                   1175:                                  $$contrib{$idx.':senderdomain'}).' ('.
                   1176:                                  $$contrib{$idx.':sendername'}.' at '.
                   1177:                                  $$contrib{$idx.':senderdomain'}.')';
                   1178:     my $attachmenturls = $$contrib{$idx.':attachmenturl'};
                   1179:     my @postversions = ();
                   1180:     if ($type eq 'allversions' || $type eq 'export') {
                   1181:         $start = 0;
                   1182:         if ($$contrib{$idx.':history'}) {
                   1183:             if ($$contrib{$idx.':history'} =~ m/:/) {
                   1184:                 @postversions = split/:/,$$contrib{$idx.':history'};
                   1185:             } else {
                   1186:                 @postversions = ("$$contrib{$idx.':history'}");
                   1187:             }
                   1188:         }
                   1189:         &get_post_versions($messages,$$contrib{$idx.':message'},1);
                   1190:         &get_post_versions($subjects,$$contrib{$idx.':subject'},1);
                   1191:         push @postversions,$$contrib{$idx.':timestamp'};
                   1192:         $end = @postversions;
                   1193:     } else {
                   1194:         &get_post_versions($messages,$$contrib{$idx.':message'},1,$numver);
                   1195:         &get_post_versions($subjects,$$contrib{$idx.':subject'},1,$numver);
                   1196:     }
                   1197: 
                   1198:     if ($$contrib{$idx.':anonymous'}) {
                   1199:         $sender.=' ['.&mt('anonymous').'] '.$$screenname;
                   1200:     }
                   1201:     if ($type eq 'allversions') {
                   1202:         $discussion=('<b>'.$sender.'</b><br /><ul>');
                   1203:     }
                   1204:     for (my $i=$start; $i<$end; $i++) {
                   1205:         my ($timesent,$attachmsg);
                   1206:         my %currattach = ();
                   1207:         $timesent = &Apache::lonlocal::locallocaltime($postversions[$i]);
                   1208:         $$messages{$i}=~s/\n/\<br \/\>/g;
                   1209:         $$messages{$i}=&Apache::lontexconvert::msgtexconverted($$messages{$i});
                   1210:         $$subjects{$i}=~s/\n/\<br \/\>/g;
                   1211:         $$subjects{$i}=&Apache::lontexconvert::msgtexconverted($$subjects{$i});
                   1212:         if ($attachmenturls) {
                   1213:             &extract_attachments($attachmenturls,$idx,$i,\$attachmsg,$allattachments,\%currattach);
                   1214:         }
                   1215:         if ($type eq 'export') {
                   1216:             $$imsfiles{$idx}{$i} = '';
                   1217:             if ($attachmsg) {
                   1218:                 $$attachtxt{$i} = '<br />Attachments:<br />';
                   1219:                 foreach (sort keys %currattach) {
                   1220:                     if ($$allattachments{$_}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {
                   1221:                         my $fname = $1.$3.'/'.$4;
                   1222:                         $$imsfiles{$idx}{$i} .= '<file href="'.$fname.'">'."\n";
                   1223:                         $$attachtxt{$i}.= '<a href="'.$fname.'">'.$4.'</a><br />';
                   1224:                     }
                   1225:                 }
                   1226:             }
                   1227:         } else {
                   1228:             if ($attachmsg) {
                   1229:                 $$attachtxt{$i} = '<br />Attachments:'.$attachmsg.'<br />';
                   1230:             } else {
                   1231:                 $$attachtxt{$i} = '';
                   1232:             }
                   1233:         }
                   1234:         if ($type eq 'allversions') {
                   1235:             $discussion.= <<"END";
                   1236: <li><b>$$subjects{$i}</b>, $timesent<br />
                   1237: $$messages{$i}<br />
                   1238: $$attachtxt{$i}</li>
                   1239: END
                   1240:         }
                   1241:     }
                   1242:     if ($type eq 'allversions') {
                   1243:         $discussion.=('</ul></body></html>');
                   1244:         return $discussion;
                   1245:     } else {
                   1246:         return;
                   1247:     }
                   1248: }
                   1249: 
                   1250: sub replicate_attachments {
                   1251:     my ($attachrefs,$tempexport) = @_;
                   1252:     my $response;
                   1253:     foreach my $id (keys %{$attachrefs}) {
                   1254:         if ($$attachrefs{$id}{'filename'} =~ m-^/uploaded/([^/]+)/([^/]+)(/feedback)?(/?\d*)/([^/]+)$-) {
                   1255:             my $path = $tempexport;
                   1256:             my $tail = $1.'/'.$2.$4;
                   1257:             my @extras = split/\//,$tail;
                   1258:             my $destination = $tempexport.'/'.$1.'/'.$2.$4.'/'.$5;
                   1259:             if (!-e $destination) {
                   1260:                 my $i= 0;
                   1261:                 while ($i<@extras) {
                   1262:                     $path .= '/'.$extras[$i];
                   1263:                     if (!-e $path) {
                   1264:                         mkdir($path,0700);
                   1265:                     }
                   1266:                     $i ++;
                   1267:                 }
                   1268:                 my ($content,$rtncode);
                   1269:                 my $uploadreply = &Apache::lonnet::getuploaded('GET',$$attachrefs{$id}{'filename'},$1,$2,$content,$rtncode);
                   1270:                 if ($uploadreply eq 'ok') {
1.125     raeburn  1271:                     my $attachcopy;
                   1272:                     if ($attachcopy = Apache::File->new('>'.$destination)) {
                   1273:                         print $attachcopy $content;
                   1274:                         close($attachcopy);
                   1275:                     } else {
                   1276:                         $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$!.'<br />'."\n";
                   1277:                     }
1.116     raeburn  1278:                 } else {
1.125     raeburn  1279:                     &Apache::lonnet::logthis("Replication of attachment failed when building IMS export of discussion posts - domain: $1, course: $2, file: $$attachrefs{$id}{'filename'} -error: $rtncode");
                   1280:                     $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$rtncode.'<br />'."\n";
1.116     raeburn  1281:                 }
                   1282:             }
                   1283:         }
                   1284:     }
1.125     raeburn  1285:     return $response;
1.116     raeburn  1286: }
                   1287: 
1.6       albertel 1288: sub mail_screen {
                   1289:   my ($r,$feedurl,$options) = @_;
1.157     albertel 1290:   if (exists($env{'form.origpage'})) {
1.108     raeburn  1291:       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss']);
                   1292:   }
1.45      www      1293:   my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion',
1.102     raeburn  1294:                                           '','onLoad="window.focus();setposttype();"');
1.51      albertel 1295:   my $title=&Apache::lonnet::gettitle($feedurl);
                   1296:   if (!$title) { $title = $feedurl; }
1.69      www      1297:   my $quote='';
1.78      raeburn  1298:   my $subject = '';
1.108     raeburn  1299:   my $comment = '';
1.80      raeburn  1300:   my $prevtag = '';
1.102     raeburn  1301:   my $parentmsg = '';
1.108     raeburn  1302:   my ($symb,$idx,$attachmenturls);
                   1303:   my $numoldver = 0;
                   1304:   my $attachmsg = '';
                   1305:   my $newattachmsg = '';
                   1306:   my @currnewattach = ();
                   1307:   my @currdelold = ();
                   1308:   my @keepold = ();
1.113     raeburn  1309:   my %attachments = ();
1.108     raeburn  1310:   my %currattach = ();
                   1311:   my $attachnum = 0;
                   1312:   my $anonchk = (<<END);
                   1313:   function anonchk() {
                   1314:      if (document.mailform.anondiscuss.checked == true) {
                   1315:           document.attachment.anondiscuss.value = '1'
                   1316:      }
                   1317:      if (document.mailform.discuss.checked == true) {
                   1318:           document.attachment.discuss.value = '1'
                   1319:      }
                   1320:      return
                   1321:    }
                   1322: END
                   1323:   my $anonscript;
1.157     albertel 1324:   if (exists($env{'form.origpage'})) {
1.108     raeburn  1325:       $anonscript = (<<END);
1.102     raeburn  1326:   function setposttype() {
1.157     albertel 1327:       var anondisc = $env{'form.anondiscuss'};
                   1328:       var disc = $env{'form.discuss'};
1.108     raeburn  1329:       if (anondisc == 1) {
                   1330:           document.mailform.anondiscuss.checked = true
                   1331:       }
                   1332:       if (disc == 1) {
                   1333:           document.mailform.discuss.checked = true
                   1334:       }
1.102     raeburn  1335:       return
                   1336:   }
                   1337: END
1.108     raeburn  1338:   } else {
                   1339:       $anonscript = (<<END);
                   1340:   function setposttype() {
                   1341:       return
                   1342:   }
                   1343: END
                   1344:   }
1.157     albertel 1345:   if (($env{'form.replydisc'}) || ($env{'form.editdisc'})) {
                   1346:       if ($env{'form.replydisc'}) {
                   1347:           ($symb,$idx)=split(/\:\:\:/,$env{'form.replydisc'});
1.102     raeburn  1348:       } else {
1.157     albertel 1349:           ($symb,$idx)=split(/\:\:\:/,$env{'form.editdisc'});
1.102     raeburn  1350:       }
1.157     albertel 1351:       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   1352: 					   $env{'course.'.$env{'request.course.id'}.'.domain'},
                   1353: 					   $env{'course.'.$env{'request.course.id'}.'.num'});
1.80      raeburn  1354:       unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) {
1.112     raeburn  1355:           if ($contrib{$idx.':history'}) {
                   1356:               if ($contrib{$idx.':history'} =~ /:/) {
                   1357:                   my @oldversions = split/:/,$contrib{$idx.':history'};
                   1358:                   $numoldver = @oldversions;
                   1359:               } else {
                   1360:                   $numoldver = 1;
                   1361:               }
                   1362:           }
1.157     albertel 1363:           if ($env{'form.replydisc'}) {
1.102     raeburn  1364:               if ($contrib{$idx.':history'}) {
                   1365:                   if ($contrib{$idx.':history'} =~ /:/) {
                   1366:                       my @oldversions = split/:/,$contrib{$idx.':history'};
                   1367:                       $numoldver = @oldversions;
                   1368:                   } else {
                   1369:                       $numoldver = 1;
                   1370:                   }
                   1371:               }
1.108     raeburn  1372:               my $message;
                   1373:               if ($idx > 0) {
1.116     raeburn  1374:                   my %msgversions = ();
                   1375:                   &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);
                   1376:                   $message = $msgversions{$numoldver};
1.108     raeburn  1377:               }
1.102     raeburn  1378: 	      $message=~s/\n/\<br \/\>/g;
1.108     raeburn  1379: 	      $quote='<blockquote>'.&Apache::lontexconvert::msgtexconverted($message).'</blockquote>';
1.102     raeburn  1380:               if ($idx > 0) {
1.116     raeburn  1381:                   my %subversions = ();
                   1382:                   &get_post_versions(\%subversions,$contrib{$idx.':subject'},1,$numoldver);
                   1383:                   $subject = 'Re: '.$subversions{$numoldver};
1.102     raeburn  1384:               }
1.108     raeburn  1385:               $subject = &HTML::Entities::encode($subject,'<>&"');
1.102     raeburn  1386:           } else {
1.108     raeburn  1387:               $attachmenturls = $contrib{$idx.':attachmenturl'};
1.116     raeburn  1388:               if ($idx > 0) {
                   1389:                   my %msgversions = ();
                   1390:                   &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver);
                   1391:                   $comment = $msgversions{$numoldver};
                   1392:                   my %subversions = ();
                   1393:                   &get_post_versions(\%subversions,$contrib{$idx.':subject'},0,$numoldver);
                   1394:                   $subject = $subversions{$numoldver}; 
1.102     raeburn  1395:               }
                   1396:               if (defined($contrib{$idx.':replyto'})) {
                   1397:                   $parentmsg = $contrib{$idx.':replyto'};
                   1398:               }
1.157     albertel 1399:               unless (exists($env{'form.origpage'})) {
1.108     raeburn  1400:                   my $anonflag = 0;
                   1401:                   if ($contrib{$idx.':anonymous'}) {
                   1402:                       $anonflag = 1;
                   1403:                   }
                   1404:                   $anonscript = (<<END);
1.102     raeburn  1405:   function setposttype () {
                   1406:       var currtype = $anonflag
                   1407:       if (currtype == 1) {
                   1408:           document.mailform.elements.discuss.checked = false
                   1409:           document.mailform.elements.anondiscuss.checked = true
                   1410:       }
                   1411:       if (currtype == 0) {
                   1412:           document.mailform.elements.anondiscuss.checked = false
                   1413:           document.mailform.elements.discuss.checked = true
                   1414:       }
                   1415:       return
                   1416:   }
                   1417: END
1.108     raeburn  1418:               }
1.79      raeburn  1419:           }
1.69      www      1420:       }
1.157     albertel 1421:       if ($env{'form.previous'}) {
                   1422:           $prevtag = '<input type="hidden" name="previous" value="'.$env{'form.previous'}.'" />';
1.80      raeburn  1423:       }
1.69      www      1424:   }
1.108     raeburn  1425: 
1.157     albertel 1426:   if ($env{'form.origpage'}) {
                   1427:       $subject = &Apache::lonnet::unescape($env{'form.subject'});
                   1428:       $comment = &Apache::lonnet::unescape($env{'form.comment'});
1.108     raeburn  1429:       &process_attachments(\@currnewattach,\@currdelold,\@keepold);
                   1430:   }
1.85      www      1431:   my $latexHelp=&Apache::loncommon::helpLatexCheatsheet();
1.86      www      1432:   my $htmlheader=&Apache::lonhtmlcommon::htmlareaheaders();
1.74      www      1433:   my $send=&mt('Send');
1.152     albertel 1434:   my $html=&Apache::lonxml::xmlbegin();
1.102     raeburn  1435:   $r->print(<<END);
1.152     albertel 1436: $html
1.1       www      1437: <head>
                   1438: <title>The LearningOnline Network with CAPA</title>
1.7       albertel 1439: <meta http-equiv="pragma" content="no-cache"></meta>
1.85      www      1440: $htmlheader
1.63      albertel 1441: <script type="text/javascript">
                   1442: //<!--
1.5       www      1443:     function gosubmit() {
                   1444:         var rec=0;
1.12      albertel 1445:         if (typeof(document.mailform.elements.author)!="undefined") {
1.5       www      1446:           if (document.mailform.elements.author.checked) {
                   1447:              rec=1;
                   1448:           } 
                   1449:         }
1.12      albertel 1450:         if (typeof(document.mailform.elements.question)!="undefined") {
1.5       www      1451:           if (document.mailform.elements.question.checked) {
                   1452:              rec=1;
                   1453:           } 
                   1454:         }
1.12      albertel 1455:         if (typeof(document.mailform.elements.course)!="undefined") {
1.5       www      1456:           if (document.mailform.elements.course.checked) {
                   1457:              rec=1;
                   1458:           } 
                   1459:         }
1.12      albertel 1460:         if (typeof(document.mailform.elements.policy)!="undefined") {
1.5       www      1461:           if (document.mailform.elements.policy.checked) {
                   1462:              rec=1;
                   1463:           } 
                   1464:         }
1.12      albertel 1465:         if (typeof(document.mailform.elements.discuss)!="undefined") {
1.10      www      1466:           if (document.mailform.elements.discuss.checked) {
                   1467:              rec=1;
                   1468:           } 
                   1469:         }
1.14      www      1470:         if (typeof(document.mailform.elements.anondiscuss)!="undefined") {
                   1471:           if (document.mailform.elements.anondiscuss.checked) {
                   1472:              rec=1;
                   1473:           } 
                   1474:         }
1.5       www      1475: 
                   1476:         if (rec) {
1.118     albertel 1477:             if (typeof(document.mailform.onsubmit)=='function') {
1.105     www      1478: 		document.mailform.onsubmit();
                   1479: 	    }
1.5       www      1480: 	    document.mailform.submit();
                   1481:         } else {
                   1482:             alert('Please check a feedback type.');
                   1483: 	}
                   1484:     }
1.108     raeburn  1485:     $anonchk
1.102     raeburn  1486:     $anonscript
1.63      albertel 1487: //-->
1.5       www      1488: </script>
1.1       www      1489: </head>
1.29      www      1490: $bodytag
1.51      albertel 1491: <h2><tt>$title</tt></h2>
1.43      www      1492: <form action="/adm/feedback" method="post" name="mailform"
                   1493: enctype="multipart/form-data">
1.80      raeburn  1494: $prevtag
1.63      albertel 1495: <input type="hidden" name="postdata" value="$feedurl" />
1.102     raeburn  1496: END
1.157     albertel 1497:   if ($env{'form.replydisc'}) {
1.102     raeburn  1498:       $r->print(<<END);
1.157     albertel 1499: <input type="hidden" name="replydisc" value="$env{'form.replydisc'}" />
1.102     raeburn  1500: END
1.157     albertel 1501:   } elsif ($env{'form.editdisc'}) {
1.102     raeburn  1502:      $r->print(<<END);
1.157     albertel 1503: <input type="hidden" name="editdisc" value ="$env{'form.editdisc'}" />
1.102     raeburn  1504: <input type="hidden" name="parentmsg" value ="$parentmsg" />
                   1505: END
                   1506:   }
1.108     raeburn  1507:   $r->print(<<END);
1.5       www      1508: Please check at least one of the following feedback types:
1.63      albertel 1509: $options<hr />
1.69      www      1510: $quote
1.63      albertel 1511: <p>My question/comment/feedback:</p>
                   1512: <p>
1.47      bowersj2 1513: $latexHelp
1.78      raeburn  1514: Title: <input type="text" name="subject" size="30" value="$subject" /></p>
                   1515: <p>
1.108     raeburn  1516: <textarea name="comment" id="comment" cols="60" rows="10" wrap="hard">$comment
1.63      albertel 1517: </textarea></p>
                   1518: <p>
1.108     raeburn  1519: END
1.157     albertel 1520:     if ( ($env{'form.editdisc'}) || ($env{'form.replydisc'}) ) {
                   1521:         if ($env{'form.origpage'}) {
1.108     raeburn  1522:             foreach (@currnewattach) {
                   1523:                 $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");
                   1524:             }
                   1525:             foreach (@currdelold) {
                   1526:                 $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");
                   1527:             }
                   1528:         }
1.157     albertel 1529:         if ($env{'form.editdisc'}) {
1.108     raeburn  1530:             if ($attachmenturls) {
1.113     raeburn  1531:                 &extract_attachments($attachmenturls,$idx,$numoldver,\$attachmsg,\%attachments,\%currattach,\@currdelold);
1.108     raeburn  1532:                 $attachnum = scalar(keys %currattach);
                   1533:                 foreach (keys %currattach) {
                   1534:                     $r->print('<input type="hidden" name="keepold" value="'.$_.'" />'."\n");
                   1535:                 }
                   1536:             }
                   1537:         }
                   1538:     } else {
                   1539:         $r->print(<<END);
1.42      www      1540: Attachment (128 KB max size): <input type="file" name="attachment" />
                   1541: </p>
1.108     raeburn  1542: END
                   1543:     }
                   1544:     $r->print(<<END);
1.42      www      1545: <p>
                   1546: <input type="hidden" name="sendit" value="1" />
1.74      www      1547: <input type="button" value="$send" onClick='gosubmit();' />
1.42      www      1548: </p>
1.2       www      1549: </form>
1.108     raeburn  1550: END
1.157     albertel 1551:     if ($env{'form.editdisc'} || $env{'form.replydisc'}) {
1.108     raeburn  1552:         my $now = time;
                   1553:         my $ressymb = $symb;
                   1554:         my $postidx = '';
1.157     albertel 1555:         if ($env{'form.editdisc'}) {
1.108     raeburn  1556:             $postidx = $idx;
                   1557:         }
                   1558:         if (@currnewattach > 0) {
                   1559:             $attachnum += @currnewattach;
                   1560:         }
                   1561:         $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver));
                   1562:         if ($attachnum > 0) {
                   1563:             if (@currnewattach > 0) {
                   1564:                 $newattachmsg .= '<b>New attachments</b><br />';
                   1565:                 if (@currnewattach > 1) {
                   1566:                     $newattachmsg .= '<ol>';
                   1567:                     foreach my $item (@currnewattach) {
                   1568:                         $item =~ m#.*/([^/]+)$#;
                   1569:                         $newattachmsg .= '<li><a href="'.$item.'">'.$1.'</a></li>'."\n";
                   1570:                     }
                   1571:                     $newattachmsg .= '</ol>'."\n";
                   1572:                 } else {
                   1573:                     $currnewattach[0] =~ m#.*/([^/]+)$#;
                   1574:                     $newattachmsg .= '<a href="'.$currnewattach[0].'">'.$1.'</a><br />'."\n";
                   1575:                 }
                   1576:             }
                   1577:             if ($attachmsg) {
                   1578:                 $r->print("<b>Retained attachments</b>:$attachmsg<br />\n");
                   1579:             }
                   1580:             if ($newattachmsg) {
                   1581:                 $r->print("$newattachmsg<br />");
                   1582:             }
                   1583:         }
                   1584:     }
                   1585:     $r->print(&generate_preview_button().
                   1586:               &Apache::lonhtmlcommon::htmlareaselectactive('comment').
                   1587:               '</body></html>');
1.6       albertel 1588: }
                   1589: 
1.97      raeburn  1590: sub print_display_options {
1.111     raeburn  1591:     my ($r,$symb,$previous,$dispchgA,$dispchgB,$markchg,$toggchg,$feedurl) = @_;
1.135     albertel 1592:     &Apache::loncommon::content_type($r,'text/html');
                   1593:     $r->send_http_header;
1.98      raeburn  1594: 
1.97      raeburn  1595:     my $function = &Apache::loncommon::get_users_function();
                   1596:     my $tabcolor = &Apache::loncommon::designparm($function.'.tabbg',
1.157     albertel 1597:                                                     $env{'user.domain'});
1.97      raeburn  1598:     my $bodytag=&Apache::loncommon::bodytag('Discussion options',
                   1599:                                           '','');
                   1600: 
                   1601:     my %lt = &Apache::lonlocal::texthash(
                   1602:         'dido' => 'Discussion display options',
                   1603:         'pref' => 'Display Preference',
                   1604:         'curr' => 'Current setting ',
                   1605:         'actn' => 'Action',
                   1606:         'deff' => 'Default for all discussions',
                   1607:         'prca' => 'Preferences can be set for this discussion that determine ....',
                   1608:         'whpo' => 'Which posts are displayed when you display this bulletin board or resource, and',
1.111     raeburn  1609:         'unwh' => 'Under what circumstances posts are identified as "NEW", and',
                   1610:         'wipa' => 'Whether individual posts can be marked as read/unread',
1.97      raeburn  1611:         'allposts' => 'All posts',
                   1612:         'unread' => 'New posts only',
1.111     raeburn  1613:         'unmark' => 'Posts not marked read',
1.97      raeburn  1614:         'ondisp' => 'Once displayed',
1.111     raeburn  1615:         'onmark' => 'Once marked not NEW ',
                   1616:         'toggon' => 'Shown',
                   1617:         'toggoff' => 'Not shown',
1.97      raeburn  1618:         'disa' => 'Posts displayed?',
1.111     raeburn  1619:         'npmr' => 'New posts cease to be identified as "NEW"?',
                   1620:         'dotm' => 'Option to mark each post as read/unread?',  
1.97      raeburn  1621:         'chgt' => 'Change to ',
                   1622:         'mkdf' => 'Set to ',
1.111     raeburn  1623:         'yhni' => 'You have not indicated that you wish to change any of the discussion settings',
1.97      raeburn  1624:         'ywbr' => 'You will be returned to the previous page if you click OK.'
                   1625:     );
                   1626: 
1.111     raeburn  1627:     my $dispchangeA = $lt{'unread'};
                   1628:     my $dispchangeB = $lt{'unmark'};
1.97      raeburn  1629:     my $markchange = $lt{'ondisp'};
1.111     raeburn  1630:     my $toggchange = $lt{'toggon'};
1.97      raeburn  1631:     my $currdisp = $lt{'allposts'};
                   1632:     my $currmark = $lt{'onmark'};
                   1633:     my $discdisp = 'allposts';
                   1634:     my $discmark = 'onmark';
1.111     raeburn  1635:     my $currtogg = $lt{'toggoff'};
                   1636:     my $disctogg = 'toggoff';
1.97      raeburn  1637:                                                                                       
1.111     raeburn  1638:     if ($dispchgA eq 'allposts') {
                   1639:         $dispchangeA = $lt{'allposts'};
1.97      raeburn  1640:         $currdisp = $lt{'unread'};
                   1641:         $discdisp = 'unread';
                   1642:     }
1.111     raeburn  1643: 
1.97      raeburn  1644:     if ($markchg eq 'markonread') {
                   1645:         $markchange = $lt{'onmark'};
                   1646:         $currmark = $lt{'ondisp'};
                   1647:         $discmark = 'ondisp';
                   1648:     }
1.111     raeburn  1649: 
                   1650:     if ($dispchgB eq 'onlyunread') {
                   1651:         $dispchangeB = $lt{'unread'};
                   1652:         $currdisp = $lt{'unmark'};
                   1653:         $discdisp = 'unmark';
                   1654:     }
                   1655:     if ($toggchg eq 'toggoff') {
                   1656:         $toggchange = $lt{'toggoff'};
                   1657:         $currtogg = $lt{'toggon'};
                   1658:         $disctogg = 'toggon';
                   1659:     }
1.152     albertel 1660:     my $html=&Apache::lonxml::xmlbegin();
1.97      raeburn  1661:     $r->print(<<END);
1.152     albertel 1662: $html
1.97      raeburn  1663: <head>
                   1664: <title>$lt{'dido'}</title>
                   1665: <meta http-equiv="pragma" content="no-cache" />
                   1666: <script>
1.111     raeburn  1667: function discdispChk(caller) {
                   1668:     var disctogg = '$toggchg'
                   1669:     if (caller == 0) {
                   1670:         if (document.modifydisp.discdisp[0].checked == true) {
                   1671:             if (document.modifydisp.discdisp[1].checked == true) {
                   1672:                 document.modifydisp.discdisp[1].checked = false
                   1673:             }
                   1674:         }
                   1675:     }
                   1676:     if (caller == 1) {
                   1677:         if (document.modifydisp.discdisp[1].checked == true) {
                   1678:             if (document.modifydisp.discdisp[0].checked == true) {
                   1679:                 document.modifydisp.discdisp[0].checked = false
                   1680:             }
                   1681:             if (disctogg == 'toggon') {
                   1682:                 document.modifydisp.disctogg.checked = true
                   1683:             }
                   1684:             if (disctogg == 'toggoff') {
                   1685:                 document.modifydisp.disctogg.checked = false
                   1686:             }
                   1687:         }
                   1688:     }
                   1689:     if (caller == 2) {
                   1690:         var dispchgB = '$dispchgB'
                   1691:         if (disctogg == 'toggoff') {
                   1692:             if (document.modifydisp.disctogg.checked == true) {
                   1693:                 if (dispchgB == 'onlyunmark') {
                   1694:                     document.modifydisp.discdisp[1].checked = false
                   1695:                 }
                   1696:             }
                   1697:         }
                   1698:     }  
                   1699: }
                   1700: 
1.97      raeburn  1701: function setDisp() {
                   1702:     var prev = "$previous"
                   1703:     var chktotal = 0
1.111     raeburn  1704:     if (document.modifydisp.discdisp[0].checked == true) {
                   1705:         document.modifydisp.$dispchgA.value = "$symb"
                   1706:         chktotal ++
                   1707:     }
                   1708:     if (document.modifydisp.discdisp[1].checked == true) {
                   1709:         document.modifydisp.$dispchgB.value = "$symb"
1.97      raeburn  1710:         chktotal ++
                   1711:     }
                   1712:     if (document.modifydisp.discmark.checked == true) {
                   1713:         document.modifydisp.$markchg.value = "$symb"
                   1714:         chktotal ++
                   1715:     }
1.111     raeburn  1716:     if (document.modifydisp.disctogg.checked == true) {
                   1717:         document.modifydisp.$toggchg.value = "$symb"
                   1718:         chktotal ++
                   1719:     }
1.97      raeburn  1720:     if (chktotal > 0) { 
                   1721:         document.modifydisp.submit()
                   1722:     } else {
                   1723:         if(confirm("$lt{'yhni'}. \\n$lt{'ywbr'}"))      {
                   1724:             if (prev > 0) {
                   1725:                 location.href = "$feedurl?previous=$previous"
                   1726:             } else {
                   1727:                 location.href = "$feedurl"
                   1728:             }
                   1729:         }
                   1730:     }
                   1731: }
                   1732: </script>
                   1733: </head>
                   1734: $bodytag
                   1735: <form name="modifydisp" method="post" action="/adm/feedback">
1.111     raeburn  1736: $lt{'sdpf'}<br/> $lt{'prca'}  <ol><li>$lt{'whpo'}</li><li>$lt{'unwh'}</li><li>$lt{'wipa'}</li></ol>
1.97      raeburn  1737: <br />
                   1738: <table border="0" cellpadding="0" cellspacing="0">
                   1739:  <tr>
                   1740:   <td width="100%" bgcolor="#000000">
                   1741:    <table width="100%" border="0" cellpadding="1" cellspacing="0">
                   1742:     <tr>
                   1743:      <td width="100%" bgcolor="#000000">
                   1744:       <table border="0" cellpadding="3" cellspacing="1" bgcolor="#FFFFFF">
                   1745:        <tr bgcolor="$tabcolor">
                   1746:         <td><b>$lt{'pref'}</b></td>
                   1747:         <td><b>$lt{'curr'}</b></td>
                   1748:         <td><b>$lt{'actn'}?</b></td>
                   1749:        </tr>
                   1750:        <tr bgcolor="#dddddd">
                   1751:        <td>$lt{'disa'}</td>
                   1752:        <td>$lt{$discdisp}</td>
1.151     albertel 1753:        <td><label><input type="checkbox" name="discdisp" onClick="discdispChk('0')" />&nbsp;$lt{'chgt'} "$dispchangeA"</label>
1.111     raeburn  1754:            <br />
1.151     albertel 1755:            <label><input type="checkbox" name="discdisp" onClick="discdispChk('1')" />&nbsp;$lt{'chgt'} "$dispchangeB"</label>
1.111     raeburn  1756:        </td>
1.97      raeburn  1757:       </tr><tr bgcolor="#eeeeee">
                   1758:        <td>$lt{'npmr'}</td>
                   1759:        <td>$lt{$discmark}</td>
1.151     albertel 1760:        <td><label><input type="checkbox" name="discmark" />$lt{'chgt'} "$markchange"</label></td>
1.111     raeburn  1761:       </tr><tr bgcolor="#dddddd">
                   1762:        <td>$lt{'dotm'}</td>
                   1763:        <td>$lt{$disctogg}</td>
1.151     albertel 1764:        <td><label><input type="checkbox" name="disctogg" onClick="discdispChk('2')" />$lt{'chgt'} "$toggchange"</label></td>
1.97      raeburn  1765:       </tr>
                   1766:      </table>
                   1767:     </td>
                   1768:    </tr>
                   1769:   </table>
                   1770:  </td>
                   1771: </tr>
                   1772: </table>
                   1773: <br />
                   1774: <br />
1.137     albertel 1775: <input type="hidden" name="symb" value="$symb" />
1.97      raeburn  1776: <input type="hidden" name="previous" value="$previous" />
1.111     raeburn  1777: <input type="hidden" name="$dispchgA" value=""/>
                   1778: <input type="hidden" name="$dispchgB" value=""/>
1.97      raeburn  1779: <input type="hidden" name="$markchg" value=""/>
1.111     raeburn  1780: <input type="hidden" name="$toggchg" value="" />
1.97      raeburn  1781: <input type="button" name="sub" value="Store Changes" onClick="javascript:setDisp()" />
                   1782: <br />
                   1783: <br />
                   1784: </form>
                   1785: </body>
                   1786: </html>
                   1787: END
                   1788:     return;
                   1789: }
                   1790: 
1.100     raeburn  1791: sub print_sortfilter_options {
                   1792:     my ($r,$symb,$previous,$feedurl) = @_;
1.133     albertel 1793: 
1.135     albertel 1794:     &Apache::loncommon::content_type($r,'text/html');
                   1795:     $r->send_http_header;
                   1796: 
1.139     albertel 1797:     &Apache::lonenc::check_encrypt(\$symb);
1.100     raeburn  1798:     my @sections = ();
                   1799:     my $section_sel = '';
                   1800:     my $numsections = 0;
                   1801:     my $numvisible = 5;
                   1802:     my %sectioncount = ();
1.144     raeburn  1803: 
1.157     albertel 1804:     $numsections = &Apache::loncommon::get_sections($env{'course.'.$env{'request.course.id'}.'.domain'},$env{'course.'.$env{'request.course.id'}.'.num'},\%sectioncount);
1.144     raeburn  1805: 
1.157     albertel 1806:     if ($env{'request.course.sec'} !~ /^\s*$/) {  #Restrict section choice to current section 
                   1807:         @sections = ('all',$env{'request.course.sec'});
1.144     raeburn  1808:         $numvisible = 2;
1.100     raeburn  1809:     } else {
                   1810:         @sections = sort {$a cmp $b} keys(%sectioncount);
                   1811:         unshift(@sections,'all'); # Put 'all' at the front of the list
                   1812:         if ($numsections < 4) {
                   1813:             $numvisible = $numsections + 1;
                   1814:         }
                   1815:     }
                   1816:     foreach (@sections) {
                   1817:         $section_sel .= "  <option value=\"$_\" />$_\n";
                   1818:     }
                   1819:                                                                                    
                   1820:     my $function = &Apache::loncommon::get_users_function();
                   1821:     my $tabcolor = &Apache::loncommon::designparm($function.'.tabbg',
1.157     albertel 1822:                                                     $env{'user.domain'});
1.100     raeburn  1823:     my $bodytag=&Apache::loncommon::bodytag('Discussion options',
                   1824:                                           '','');
                   1825:     my %lt = &Apache::lonlocal::texthash(
                   1826:         'diso' => 'Discussion sorting and filtering options',
                   1827:         'diop' => 'Display Options',
                   1828:         'curr' => 'Current setting ',
                   1829:         'actn' => 'Action',
1.143     raeburn  1830:         'prca' => 'Set options that control the sort order of posts, and/or which posts are displayed.',
1.100     raeburn  1831:         'soor' => 'Sort order',
1.143     raeburn  1832:         'spur' => 'Specific user roles',
                   1833:         'sprs' => 'Specific role status',
1.100     raeburn  1834:         'spse' => 'Specific sections',
                   1835:         'psub' => 'Pick specific users (by name)',
1.101     raeburn  1836:         'shal' => 'Show a list of current posters'
1.100     raeburn  1837:     );
1.143     raeburn  1838: 
                   1839:     my %sort_types = ();
                   1840:     my %role_types = ();
                   1841:     my %status_types = ();
                   1842:     &sort_filter_names(\%sort_types,\%role_types,\%status_types);
1.152     albertel 1843:     my $html=&Apache::lonxml::xmlbegin();
1.100     raeburn  1844:     $r->print(<<END);
1.152     albertel 1845: $html
1.100     raeburn  1846: <head>
                   1847: <title>$lt{'diso'}</title>
                   1848: <meta http-equiv="pragma" content="no-cache" />
1.144     raeburn  1849: <script type="text/javascript">
                   1850: function verifyFilter() {
                   1851:     var rolenum = 0
                   1852:     for (var i=0; i<document.modifyshown.rolefilter.length; i++) {
                   1853:         if (document.modifyshown.rolefilter.options[i].selected == true) {
                   1854:             rolenum ++
                   1855:         }
                   1856:     }
                   1857:     if (rolenum == 0) {
                   1858:         document.modifyshown.rolefilter.options[0].selected = true
                   1859:     }
                   1860: 
                   1861:     var secnum = 0
                   1862:     for (var i=0; i<document.modifyshown.sectionpick.length; i++) {
                   1863:         if (document.modifyshown.sectionpick.options[i].selected == true) {
                   1864:             secnum ++
                   1865:         }
                   1866:     }
                   1867:     if (secnum == 0) {
                   1868:         document.modifyshown.sectionpick.options[0].selected = true
                   1869:     }
                   1870:     document.modifyshown.submit();
                   1871: }
                   1872: </script>
1.100     raeburn  1873: </head>
                   1874: $bodytag
                   1875: <form name="modifyshown" method="post" action="/adm/feedback">
                   1876: <b>$lt{'diso'}</b><br/> $lt{'prca'}
                   1877: <br /><br />
                   1878: <table border="0">
                   1879:  <tr>
                   1880:   <td><b>$lt{'soor'}</b></td>
                   1881:   <td>&nbsp;</td>
1.143     raeburn  1882:   <td><b>$lt{'sprs'}</b></td>
1.100     raeburn  1883:   <td>&nbsp;</td>
1.143     raeburn  1884:   <td><b>$lt{'spur'}</b></td>
1.100     raeburn  1885:   <td>&nbsp;</td>
                   1886:   <td><b>$lt{'spse'}</b></td>
                   1887:   <td>&nbsp;</td>
                   1888:   <td><b>$lt{'psub'}</b></td>
                   1889:  </tr>
                   1890:  <tr>
1.143     raeburn  1891:   <td align="center">
1.100     raeburn  1892:    <select name="sortposts">
1.144     raeburn  1893:     <option value="ascdate" selected="selected" />$sort_types{'ascdate'}
1.143     raeburn  1894:     <option value="descdate" />$sort_types{'descdate'}
                   1895:     <option value="thread" />$sort_types{'thread'}
                   1896:     <option value="subject" />$sort_types{'subject'}
                   1897:     <option value="username" />$sort_types{'username'}
                   1898:     <option value="lastfirst" />$sort_types{'lastfirst'}
1.100     raeburn  1899:    </select>
                   1900:   </td>
                   1901:   <td>&nbsp;</td>
1.143     raeburn  1902:   <td align="center">
                   1903:    <select name="statusfilter">
1.144     raeburn  1904:     <option value="all" selected="selected" />$status_types{'all'}
1.143     raeburn  1905:     <option value="Active" />$status_types{'Active'}
                   1906:     <option value="Expired" />$status_types{'Expired'}
1.100     raeburn  1907:    </select>
                   1908:   </td>
                   1909:   <td>&nbsp;</td>
1.143     raeburn  1910:   <td align="center">
                   1911:    <select name="rolefilter" multiple="true" size="5">
                   1912:     <option value="all" />$role_types{'all'}
                   1913:     <option value="st" />$role_types{'st'}
                   1914:     <option value="cc" />$role_types{'cc'}
                   1915:     <option value="in" />$role_types{'in'}
                   1916:     <option value="ta" />$role_types{'ta'}
                   1917:     <option value="ep" />$role_types{'ep'}
                   1918:     <option value="ad" />$role_types{'ad'}
                   1919:     <option value="cr" />$role_types{'cr'}
1.100     raeburn  1920:    </select>
                   1921:   </td>
                   1922:   <td>&nbsp;</td>
1.143     raeburn  1923:   <td align="center">
1.100     raeburn  1924:    <select name="sectionpick" multiple="true" size="$numvisible">
                   1925:     $section_sel
                   1926:    </select>
                   1927:   </td>
                   1928:   <td>&nbsp;</td>
1.151     albertel 1929:   <td><label><input type="checkbox" name="posterlist" value="$symb" />$lt{'shal'}</label></td>
1.100     raeburn  1930:  </tr>
                   1931: </table>
                   1932: <br />
                   1933: <br />
                   1934: <input type="hidden" name="previous" value="$previous" />
                   1935: <input type="hidden" name="applysort" value="$symb" />
1.144     raeburn  1936: <input type="button" name="sub" value="Store Changes" onClick="verifyFilter()" />
1.100     raeburn  1937: <br />
                   1938: <br />
                   1939: </form>
                   1940: </body>
                   1941: </html>
                   1942: END
                   1943: }
                   1944: 
1.101     raeburn  1945: sub print_showposters {
                   1946:     my ($r,$symb,$previous,$feedurl,$sortposts) = @_;
1.133     albertel 1947: 
1.154     albertel 1948:     &Apache::loncommon::content_type($r,'text/html');
                   1949:     $r->send_http_header;
                   1950: 
1.139     albertel 1951:     &Apache::lonenc::check_encrypt(\$symb);
1.157     albertel 1952:     my $crs='/'.$env{'request.course.id'};
                   1953:     if ($env{'request.course.sec'}) {
                   1954:         $crs.='_'.$env{'request.course.sec'};
1.102     raeburn  1955:     }
1.101     raeburn  1956:     $crs=~s/\_/\//g;
                   1957:     my $seeid=&Apache::lonnet::allowed('rin',$crs);
1.157     albertel 1958:     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   1959:                           $env{'course.'.$env{'request.course.id'}.'.domain'},
                   1960:                           $env{'course.'.$env{'request.course.id'}.'.num'});
1.101     raeburn  1961:     my %namesort = ();
                   1962:     my %postcounts = ();
                   1963:     my %lt=&Apache::lonlocal::texthash(
                   1964:                      'diso' => 'Discussion filtering options',
                   1965:     );
                   1966:     my $bodytag=&Apache::loncommon::bodytag('Discussion options',
                   1967:                                           '','');
                   1968:     if ($contrib{'version'}) {
                   1969:         for (my $idx=1;$idx<=$contrib{'version'};$idx++) {
                   1970:             my $hidden=($contrib{'hidden'}=~/\.$idx\./);
                   1971:             my $deleted=($contrib{'deleted'}=~/\.$idx\./);
                   1972:             unless ((($hidden) && (!$seeid)) || ($deleted)) {
                   1973:                 if ((!$contrib{$idx.':anonymous'}) || ($seeid)) {
                   1974:                     my %names = &Apache::lonnet::get('environment',['firstname','lastname'],$contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
                   1975:                     my $lastname = $names{'lastname'};
                   1976:                     my $firstname = $names{'firstname'};
                   1977:                     if ($lastname eq '') {
                   1978:                         $lastname = '_';
                   1979:                     }
                   1980:                     if ($firstname eq '') {
                   1981:                         $firstname = '_';
                   1982:                     }
                   1983:                     unless (defined($namesort{$lastname})) {
                   1984:                         %{$namesort{$lastname}} = ();
                   1985:                     }
                   1986:                     my $poster =  $contrib{$idx.':sendername'}.':'.$contrib{$idx.':senderdomain'};
                   1987:                     $postcounts{$poster} ++;
                   1988:                     if (defined($namesort{$lastname}{$firstname})) {
                   1989:                         if (!grep/^$poster$/,@{$namesort{$lastname}{$firstname}}) {
                   1990:                             push @{$namesort{$lastname}{$firstname}}, $poster;
                   1991:                         }
                   1992:                     } else {
                   1993:                         @{$namesort{$lastname}{$firstname}} = ("$poster");
                   1994:                     }
                   1995:                 }
                   1996:             }
                   1997:         }
                   1998:     }
1.152     albertel 1999:     my $html=&Apache::lonxml::xmlbegin();
1.101     raeburn  2000:     $r->print(<<END);
1.152     albertel 2001: $html
1.101     raeburn  2002: <head>
                   2003: <title>$lt{'diso'}</title>
                   2004: <meta http-equiv="pragma" content="no-cache" />
                   2005: </head>
                   2006: $bodytag
                   2007:  <form name="pickpostersform" method="post">
                   2008:   <table border="0">
                   2009:    <tr>
                   2010:     <td bgcolor="#777777">
                   2011:      <table border="0" cellpadding="3">
                   2012:       <tr bgcolor="#e6ffff">
                   2013:        <td><b>No.</b></td>
                   2014:        <td><b>Select</b></td>
                   2015:        <td><b>Fullname</b><font color="#999999">(Username/domain)</font></td>
                   2016:        <td><b>Posts</td>
                   2017:       </tr>
                   2018: END
                   2019:     my $count = 0;
                   2020:     foreach my $last (sort keys %namesort) {
                   2021:         foreach my $first (sort keys %{$namesort{$last}}) {
                   2022:             foreach (sort @{$namesort{$last}{$first}}) {
                   2023:                 my ($uname,$udom) = split/:/,$_;
                   2024:                 if (!$uname || !$udom) { 
                   2025:                     next;
                   2026:                 } else {
                   2027:                     $count ++;
1.151     albertel 2028:                     $r->print('<tr bgcolor="#ffffe6"><td align="right">'.$count.'</td><td align="center"><label><input name="stuinfo" type="checkbox" value="'.$_.'" /></td><td>'.$last.', '.$first.' ('.$uname.','.$udom.')</label></td><td>'.$postcounts{$_}.'</td></tr>');
1.101     raeburn  2029:                 }
                   2030:             }
                   2031:         }
                   2032:     }
                   2033:     $r->print(<<END);
                   2034:      </table>
                   2035:     </td>
                   2036:    </tr>
                   2037:   </table>
                   2038: <br />
                   2039: <input type="hidden" name="sortposts" value="$sortposts" />
                   2040: <input type="hidden" name="userpick" value="$symb" />
                   2041: <input type="button" name="store" value="Display posts" onClick="javascript:document.pickpostersform.submit()" />
                   2042: </form>
                   2043: </body>
                   2044: </html>
                   2045: END
                   2046: }
                   2047: 
1.112     raeburn  2048: sub get_post_versions {
1.116     raeburn  2049:     my ($versions,$incoming,$htmldecode,$numver) = @_;
                   2050:     if ($incoming =~ /^<version num="0">/) {
                   2051:         my $p = HTML::LCParser->new(\$incoming);
                   2052:         my $done = 0;                                                                       
                   2053:         while ( (my $token = $p->get_tag("version")) && (!$done)) {
                   2054:             my $num = $token->[1]{num};
                   2055:             my $text = $p->get_text("/version");
                   2056:             if (defined($numver)) {
                   2057:                 if ($num == $numver) {
                   2058:                     if ($htmldecode) {
                   2059:                         $text = &HTML::Entities::decode($text);
                   2060:                     }
                   2061:                     $$versions{$numver}=$text;
                   2062:                     $done = 1;
                   2063:                 }
                   2064:             } else {
                   2065:                 if ($htmldecode) {
                   2066:                     $text = &HTML::Entities::decode($text);
                   2067:                 }
                   2068:                 $$versions{$num}=$text;
1.112     raeburn  2069:             }
1.116     raeburn  2070:         }
                   2071:     } else {
                   2072:         if (!defined($numver)) {
                   2073:             $numver = 0;
                   2074:         }
                   2075:         if ($htmldecode) {
                   2076:             $$versions{$numver} = $incoming;
1.112     raeburn  2077:         } else {
1.116     raeburn  2078:             $$versions{$numver} = &HTML::Entities::encode($incoming,'<>&"');
1.112     raeburn  2079:         }
                   2080:     }
                   2081:     return;
                   2082: }
                   2083: 
1.113     raeburn  2084: sub get_post_attachments {
                   2085:     my ($attachments,$attachmenturls) = @_;
                   2086:     my $num;
1.116     raeburn  2087:     if ($attachmenturls =~ m/^<attachment id="0">/) {
                   2088:         my $p = HTML::LCParser->new(\$attachmenturls);
                   2089:         while (my $token = $p->get_tag("attachment","filename","post"))  {
                   2090:             if ($token->[0] eq "attachment") {
                   2091:                 $num = $token->[1]{id};
                   2092:                 %{$$attachments{$num}} =();
                   2093:             } elsif ($token->[0] eq "filename") {
                   2094:                 $$attachments{$num}{'filename'} = $p->get_text("/filename");
                   2095:             } elsif ($token->[0] eq "post") {
                   2096:                 my $id = $token->[1]{id};
                   2097:                 $$attachments{$num}{$id} = $p->get_text("/post");
                   2098:             }
1.113     raeburn  2099:         }
1.116     raeburn  2100:     } else {
                   2101:         %{$$attachments{'0'}} = ();
                   2102:         $$attachments{'0'}{'filename'} = $attachmenturls;
                   2103:         $$attachments{'0'}{'0'} = 'n';
1.113     raeburn  2104:     }
1.116     raeburn  2105: 
1.113     raeburn  2106:     return;
                   2107: }
                   2108: 
1.150     albertel 2109: sub fail_redirect {
1.6       albertel 2110:   my ($r,$feedurl) = @_;
1.70      www      2111:   if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
1.150     albertel 2112:   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
1.152     albertel 2113:   my $html=&Apache::lonxml::xmlbegin();
1.6       albertel 2114:   $r->print (<<ENDFAILREDIR);
1.152     albertel 2115: $html
                   2116: <head>
                   2117: <title>Feedback not sent</title>
1.63      albertel 2118: <meta http-equiv="pragma" content="no-cache" />
                   2119: <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />
1.5       www      2120: </head>
                   2121: <body bgcolor="#FFFFFF">
1.150     albertel 2122: <img align="right" src="$logo" />
1.8       www      2123: <b>Sorry, no recipients  ...</b>
1.121     albertel 2124: <br /><a href="$feedurl">Continue</a>
1.5       www      2125: </body>
                   2126: </html>
                   2127: ENDFAILREDIR
                   2128: }
1.4       www      2129: 
1.6       albertel 2130: sub redirect_back {
1.143     raeburn  2131:   my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$status,$previous,$sort,$rolefilter,$statusfilter,$sectionpick,$numpicks) = @_;
1.100     raeburn  2132:   my $sorttag = '';
1.101     raeburn  2133:   my $roletag = '';
                   2134:   my $statustag = '';
                   2135:   my $sectag = '';
                   2136:   my $userpicktag = '';
                   2137:   my $qrystr = '';
1.80      raeburn  2138:   my $prevtag = '';
1.133     albertel 2139: 
1.135     albertel 2140:   &Apache::loncommon::content_type($r,'text/html');
                   2141:   $r->send_http_header;
                   2142: 
1.133     albertel 2143:   &dewrapper(\$feedurl);
1.70      www      2144:   if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
1.80      raeburn  2145:   if ($previous > 0) {
                   2146:       $qrystr = 'previous='.$previous;
                   2147:       if ($feedurl =~ /\?register=1/) {
                   2148:           $feedurl .= '&'.$qrystr;
                   2149:       } else {
                   2150:           $feedurl .= '?'.$qrystr;
                   2151:       }
                   2152:       $prevtag = '<input type="hidden" name="previous" value="'.$previous.'" />';
                   2153:   }
1.100     raeburn  2154:   if (defined($sort)) {
                   2155:       my $sortqry = 'sortposts='.$sort;
                   2156:       if (($feedurl =~ /\?register=1/) || ($feedurl =~ /\?previous=/)) {
                   2157:           $feedurl .= '&'.$sortqry;
                   2158:       } else {
                   2159:           $feedurl .= '?'.$sortqry;
                   2160:       }
                   2161:       $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';
1.143     raeburn  2162:       if (defined($numpicks)) {
1.101     raeburn  2163:           my $userpickqry = 'totposters='.$numpicks;
                   2164:           $feedurl .= '&'.$userpickqry;
                   2165:           $userpicktag = '<input type="hidden" name="totposters" value="'.$numpicks.'" />';
                   2166:       } else {
1.143     raeburn  2167:           if (ref($sectionpick) eq 'ARRAY') {
                   2168:               $feedurl .= '&sectionpick=';
                   2169:               $sectag .=  '<input type="hidden" name="sectionpick" value="';
                   2170:               foreach (@{$sectionpick}) {
                   2171:                   $feedurl .= $_.',';
                   2172:                   $sectag .= $_.',';
                   2173:               }
                   2174:               $feedurl =~ s/,$//;
                   2175:               $sectag =~ s/,$//;
                   2176:               $sectag .= '" />';
                   2177:           } else {
                   2178:               $feedurl .= '&sectionpick='.$sectionpick;
                   2179:               $sectag = '<input type="hidden" name="sectionpick" value="'.$sectionpick.'" />';
                   2180:           }
                   2181:           if (ref($rolefilter) eq 'ARRAY') {
                   2182:               $feedurl .= '&rolefilter=';
                   2183:               $roletag .=  '<input type="hidden" name="rolefilter" value="';
                   2184:               foreach (@{$rolefilter}) {
                   2185:                   $feedurl .= $_.',';
                   2186:                   $roletag .= $_.',';
                   2187:               }
                   2188:               $feedurl =~ s/,$//;
                   2189:               $roletag =~ s/,$//;
                   2190:               $roletag .= '" />';
                   2191:           } else {
                   2192:               $feedurl .= '&rolefilter='.$rolefilter;
                   2193:               $roletag = '<input type="hidden" name="rolefilter" value="'.$rolefilter.'" />';
                   2194:           }
1.101     raeburn  2195:           $feedurl .= '&statusfilter='.$statusfilter;
                   2196:           $statustag ='<input type="hidden" name="statusfilter" value="'.$statusfilter.'" />';
                   2197:       }
1.100     raeburn  2198:   }
1.129     albertel 2199:   $feedurl=&Apache::lonenc::check_encrypt($feedurl);
1.150     albertel 2200:   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
1.152     albertel 2201:   my $html=&Apache::lonxml::xmlbegin();
1.6       albertel 2202:   $r->print (<<ENDREDIR);
1.152     albertel 2203: $html
1.3       www      2204: <head>
                   2205: <title>Feedback sent</title>
1.63      albertel 2206: <meta http-equiv="pragma" content="no-cache" />
1.80      raeburn  2207: <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />
1.2       www      2208: </head>
1.49      www      2209: <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>
1.150     albertel 2210: <img align="right" src="$logo" />
1.5       www      2211: $typestyle
1.32      albertel 2212: <b>Sent $sendsomething message(s), and $sendposts post(s).</b>
1.63      albertel 2213: <font color="red">$status</font>
1.49      www      2214: <form name="reldt" action="$feedurl" target="loncapaclient">
1.80      raeburn  2215: $prevtag
1.100     raeburn  2216: $sorttag
1.101     raeburn  2217: $statustag
                   2218: $roletag
                   2219: $sectag
                   2220: $userpicktag
1.49      www      2221: </form>
1.121     albertel 2222: <br /><a href="$feedurl">Continue</a>
1.2       www      2223: </body>
                   2224: </html>
                   2225: ENDREDIR
                   2226: }
1.6       albertel 2227: 
                   2228: sub no_redirect_back {
                   2229:   my ($r,$feedurl) = @_;
1.107     www      2230:   my $nofeed=&mt('Sorry, no feedback possible on this resource  ...');
1.120     albertel 2231:   my $continue=&mt('Continue');
1.152     albertel 2232:   my $html=&Apache::lonxml::xmlbegin();
1.6       albertel 2233:   $r->print (<<ENDNOREDIR);
1.152     albertel 2234: $html
                   2235: <head>
                   2236: <title>Feedback not sent</title>
1.63      albertel 2237: <meta http-equiv="pragma" content="no-cache" />
1.7       albertel 2238: ENDNOREDIR
                   2239: 
1.8       www      2240:   if ($feedurl!~/^\/adm\/feedback/) { 
1.129     albertel 2241:       $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2; url='.
                   2242: 		&Apache::lonenc::check_encrypt($feedurl).'">');
1.7       albertel 2243:   }
1.129     albertel 2244:   $feedurl=&Apache::lonenc::check_encrypt($feedurl);
1.150     albertel 2245:   my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
1.8       www      2246:   $r->print (<<ENDNOREDIRTWO);
1.2       www      2247: </head>
1.49      www      2248: <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { self.close(); }'>
1.150     albertel 2249: <img align="right" src="$logo" />
1.107     www      2250: <b>$nofeed</b>
1.121     albertel 2251: <br /><a href="$feedurl">$continue</a>
1.2       www      2252: </body>
                   2253: </html>
1.8       www      2254: ENDNOREDIRTWO
1.2       www      2255: }
1.6       albertel 2256: 
                   2257: sub screen_header {
1.141     raeburn  2258:     my ($feedurl,$symb) = @_;
1.65      www      2259:     my $msgoptions='';
                   2260:     my $discussoptions='';
1.157     albertel 2261:     unless (($env{'form.replydisc'}) || ($env{'form.editdisc'})) {
1.65      www      2262: 	if (($feedurl=~/^\/res\//) && ($feedurl!~/^\/res\/adm/)) {
                   2263: 	    $msgoptions= 
1.151     albertel 2264: 		'<p><label><input type="checkbox" name="author" /> '.
                   2265: 		&mt('Feedback to resource author').'</label></p>';
1.65      www      2266: 	}
                   2267: 	if (&feedback_available(1)) {
                   2268: 	    $msgoptions.=
1.151     albertel 2269: 		'<p><label><input type="checkbox" name="question" /> '.
                   2270: 		&mt('Question about resource content').'</label></p>';
1.65      www      2271: 	}
                   2272: 	if (&feedback_available(0,1)) {
                   2273: 	    $msgoptions.=
1.151     albertel 2274: 		'<p><label><input type="checkbox" name="course" /> '.
                   2275: 		&mt('Question/Comment/Feedback about course content').
                   2276: 		'</label></p>';
1.65      www      2277: 	}
                   2278: 	if (&feedback_available(0,0,1)) {
                   2279: 	    $msgoptions.=
1.151     albertel 2280: 		'<p><label><input type="checkbox" name="policy" /> '.
                   2281: 		&mt('Question/Comment/Feedback about course policy').
                   2282: 		'</label></p>';
1.65      www      2283: 	}
                   2284:     }
1.157     albertel 2285:     if ($env{'request.course.id'}) {
1.141     raeburn  2286: 	if (&discussion_open(undef,$symb) &&
1.90      albertel 2287: 	    &Apache::lonnet::allowed('pch',
1.157     albertel 2288: 				     $env{'request.course.id'}.
                   2289: 				     ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
1.151     albertel 2290: 	    $discussoptions='<label><input type="checkbox" name="discuss" onClick="this.form.anondiscuss.checked=false;" '.
1.157     albertel 2291: 		($env{'form.replydisc'}?' checked="1"':'').' /> '.
1.65      www      2292: 		&mt('Contribution to course discussion of resource');
1.151     albertel 2293: 	    $discussoptions.='</label><br /><label><input type="checkbox" name="anondiscuss" onClick="this.form.discuss.checked=false;" /> '.
1.65      www      2294: 		&mt('Anonymous contribution to course discussion of resource').
1.151     albertel 2295: 		' <i>('.&mt('name only visible to course faculty').')</i></label>';
1.141     raeburn  2296:         }
1.65      www      2297:     }
1.149     albertel 2298:     if ($msgoptions) { $msgoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/feedback.gif').'" />'.&mt('Sending Messages').'</h2>'.$msgoptions; }
1.65      www      2299:     if ($discussoptions) { 
1.149     albertel 2300: 	$discussoptions='<h2><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/chat.gif').'" />'.&mt('Discussion Contributions').'</h2>'.$discussoptions; }
1.65      www      2301:     return $msgoptions.$discussoptions;
1.6       albertel 2302: }
                   2303: 
                   2304: sub resource_output {
                   2305:   my ($feedurl) = @_;
1.46      albertel 2306:   my $usersaw=&Apache::lonnet::ssi_body($feedurl);
1.6       albertel 2307:   $usersaw=~s/\<body[^\>]*\>//gi;
                   2308:   $usersaw=~s/\<\/body\>//gi;
                   2309:   $usersaw=~s/\<html\>//gi;
                   2310:   $usersaw=~s/\<\/html\>//gi;
                   2311:   $usersaw=~s/\<head\>//gi;
                   2312:   $usersaw=~s/\<\/head\>//gi;
                   2313:   $usersaw=~s/action\s*\=/would_be_action\=/gi;
                   2314:   return $usersaw;
                   2315: }
                   2316: 
                   2317: sub clear_out_html {
1.39      www      2318:   my ($message,$override)=@_;
1.88      www      2319:   unless (&Apache::lonhtmlcommon::htmlareablocked()) { return $message; }
1.107     www      2320: # Always allow the <m>-tag
                   2321:   my %html=(M=>1);
                   2322: # Check if more is allowed
1.157     albertel 2323:   my $cid=$env{'request.course.id'};
                   2324:   if (($env{"course.$cid.allow_limited_html_in_feedback"} =~ m/yes/i) ||
1.39      www      2325:       ($override)) {
1.37      albertel 2326:       # allows <B> <I> <P> <A> <LI> <OL> <UL> <EM> <BR> <TT> <STRONG> 
1.88      www      2327:       # <BLOCKQUOTE> <DIV .*> <DIV> <IMG> <M> <SPAN> <H1> <H2> <H3> <H4> <SUB>
                   2328:       # <SUP>
1.107     www      2329:       %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1,
                   2330: 	     BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, DIV=>1, IMG=>1,
1.155     albertel 2331: 	     M=>1, ALGEBRA=>1, SUB=>1, SUP=>1, SPAN=>1, 
1.107     www      2332: 	     H1=>1, H2=>1, H3=>1, H4=>1, H5=>1);
                   2333:   }
                   2334: # Do the substitution of everything that is not explicitly allowed
                   2335:   $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/
1.48      albertel 2336: 	  {($html{uc($2)}&&(length($1)<1000))?"\<$1":"\&lt;$1"}/ge;
1.107     www      2337:   $message =~ s/(\<?\s*(\w+)[^\<\>]*)\>/
1.48      albertel 2338: 	  {($html{uc($2)}&&(length($1)<1000))?"$1\>":"$1\&gt;"}/ge;
1.6       albertel 2339:   return $message;
                   2340: }
                   2341: 
                   2342: sub assemble_email {
1.40      albertel 2343:   my ($feedurl,$message,$prevattempts,$usersaw,$useranswer)=@_;
1.6       albertel 2344:   my $email=<<"ENDEMAIL";
                   2345: $message
                   2346: ENDEMAIL
                   2347:     my $citations=<<"ENDCITE";
                   2348: <h2>Previous attempts of student (if applicable)</h2>
                   2349: $prevattempts
1.63      albertel 2350: <br /><hr />
1.6       albertel 2351: <h2>Original screen output (if applicable)</h2>
                   2352: $usersaw
1.40      albertel 2353: <h2>Correct Answer(s) (if applicable)</h2>
                   2354: $useranswer
1.6       albertel 2355: ENDCITE
                   2356:   return ($email,$citations);
                   2357: }
                   2358: 
1.35      www      2359: sub secapply {
                   2360:     my $rec=shift;
1.36      www      2361:     my $defaultflag=shift;
                   2362:     $rec=~s/\s+//g;
                   2363:     $rec=~s/\@/\:/g;
                   2364:     my ($adr,$sections)=($rec=~/^([^\(]+)\(([^\)]+)\)/);
                   2365:     if ($sections) {
                   2366: 	foreach (split(/\;/,$sections)) {
1.157     albertel 2367:             if (($_ eq $env{'request.course.sec'}) ||
1.36      www      2368:                 ($defaultflag && ($_ eq '*'))) {
                   2369:                 return $adr; 
                   2370:             }
                   2371:         }
                   2372:     } else {
                   2373:        return $rec;
                   2374:     }
                   2375:     return '';
1.35      www      2376: }
                   2377: 
1.163   ! albertel 2378: =pod 
        !          2379: 
        !          2380: =over 4
        !          2381: 
        !          2382: =item *
        !          2383: 
        !          2384: decide_receiver($feedurl,$author,$question,$course,$policy,$defaultflag);
        !          2385: 
        !          2386: Arguments
        !          2387:   $feedurl - /res/ url of resource (only need if $author is true)
        !          2388:   $author,$question,$course,$policy - all true/false parameters
        !          2389:     if true will attempt to find the addresses of user that should receive
        !          2390:     this type of feedback (author - feedback to author of resource $feedurl,
        !          2391:     $question 'Resource Content Questions', $course 'Course Content Question',
        !          2392:     $policy 'Course Policy')
        !          2393:     (Additionally it also checks $env for whether the corresponding form.<name>
        !          2394:     element exists, for ease of use in a html response context)
        !          2395:    
        !          2396:   $defaultflag - (internal should be left blank) if true gather addresses 
        !          2397:                  that aren't for a section even if I have a section
        !          2398:                  (used for reccursion internally, first we look for
        !          2399:                  addresses for our specific section then we recurse
        !          2400:                  and look for non section addresses)
        !          2401: 
        !          2402: Returns
        !          2403:   $typestyle - string of html text, describing what addresses were found
        !          2404:   %to - a hash, which keys are addresses of users to send messages to
        !          2405:         the keys will look like   name:domain
        !          2406: 
        !          2407: =cut
        !          2408: 
1.6       albertel 2409: sub decide_receiver {
1.36      www      2410:   my ($feedurl,$author,$question,$course,$policy,$defaultflag) = @_;
1.6       albertel 2411:   my $typestyle='';
                   2412:   my %to=();
1.157     albertel 2413:   if ($env{'form.author'}||$author) {
1.163   ! albertel 2414:     $typestyle.='Submitting as Author Feedback<br />';
1.6       albertel 2415:     $feedurl=~/^\/res\/(\w+)\/(\w+)\//;
                   2416:     $to{$2.':'.$1}=1;
                   2417:   }
1.157     albertel 2418:   if ($env{'form.question'}||$question) {
1.163   ! albertel 2419:     $typestyle.='Submitting as Question<br />';
1.24      harris41 2420:     foreach (split(/\,/,
1.157     albertel 2421: 		   $env{'course.'.$env{'request.course.id'}.'.question.email'})
1.24      harris41 2422: 	     ) {
1.36      www      2423: 	my $rec=&secapply($_,$defaultflag);
                   2424:         if ($rec) { $to{$rec}=1; }
1.24      harris41 2425:     } 
1.6       albertel 2426:   }
1.157     albertel 2427:   if ($env{'form.course'}||$course) {
1.63      albertel 2428:     $typestyle.='Submitting as Comment<br />';
1.24      harris41 2429:     foreach (split(/\,/,
1.157     albertel 2430: 		   $env{'course.'.$env{'request.course.id'}.'.comment.email'})
1.24      harris41 2431: 	     ) {
1.36      www      2432: 	my $rec=&secapply($_,$defaultflag);
                   2433:         if ($rec) { $to{$rec}=1; }
1.24      harris41 2434:     } 
1.6       albertel 2435:   }
1.157     albertel 2436:   if ($env{'form.policy'}||$policy) {
1.63      albertel 2437:     $typestyle.='Submitting as Policy Feedback<br />';
1.24      harris41 2438:     foreach (split(/\,/,
1.157     albertel 2439: 		   $env{'course.'.$env{'request.course.id'}.'.policy.email'})
1.24      harris41 2440: 	     ) {
1.36      www      2441: 	my $rec=&secapply($_,$defaultflag);
                   2442:         if ($rec) { $to{$rec}=1; }
1.24      harris41 2443:     } 
1.6       albertel 2444:   }
1.36      www      2445:   if ((scalar(%to) eq '0') && (!$defaultflag)) {
                   2446:      ($typestyle,%to)=
                   2447: 	 &decide_receiver($feedurl,$author,$question,$course,$policy,1);
                   2448:   }
1.6       albertel 2449:   return ($typestyle,%to);
1.36      www      2450: }
                   2451: 
                   2452: sub feedback_available {
                   2453:     my ($question,$course,$policy)=@_;
                   2454:     my ($typestyle,%to)=&decide_receiver('',0,$question,$course,$policy);
                   2455:     return scalar(%to);
1.6       albertel 2456: }
                   2457: 
                   2458: sub send_msg {
1.43      www      2459:   my ($feedurl,$email,$citations,$attachmenturl,%to)=@_;
1.6       albertel 2460:   my $status='';
                   2461:   my $sendsomething=0;
1.24      harris41 2462:   foreach (keys %to) {
1.6       albertel 2463:     if ($_) {
1.22      www      2464:       my $declutter=&Apache::lonnet::declutter($feedurl);
1.8       www      2465:       unless (&Apache::lonmsg::user_normal_msg(split(/\:/,$_),
1.43      www      2466:                'Feedback ['.$declutter.']',$email,$citations,$feedurl,
                   2467:                 $attachmenturl)=~/ok/) {
1.63      albertel 2468: 	$status.='<br />'.&mt('Error sending message to').' '.$_.'<br />';
1.6       albertel 2469:       } else {
                   2470: 	$sendsomething++;
                   2471:       }
                   2472:     }
1.24      harris41 2473:   }
1.18      www      2474: 
                   2475:     my %record=&Apache::lonnet::restore('_feedback');
                   2476:     my ($temp)=keys %record;
                   2477:     unless ($temp=~/^error\:/) {
                   2478:        my %newrecord=();
                   2479:        $newrecord{'resource'}=$feedurl;
                   2480:        $newrecord{'subnumber'}=$record{'subnumber'}+1;
                   2481:        unless (&Apache::lonnet::cstore(\%newrecord,'_feedback') eq 'ok') {
1.63      albertel 2482: 	   $status.='<br />'.&mt('Not registered').'<br />';
1.18      www      2483:        }
                   2484:     }
                   2485:        
1.6       albertel 2486:   return ($status,$sendsomething);
                   2487: }
                   2488: 
1.13      www      2489: sub adddiscuss {
1.78      raeburn  2490:     my ($symb,$email,$anon,$attachmenturl,$subject)=@_;
1.13      www      2491:     my $status='';
1.122     raeburn  2492:     my $realsymb;
                   2493:     if ($symb=~/^bulletin___/) {
                   2494: 	my $filename=(&Apache::lonnet::decode_symb($symb))[2];
                   2495: 	$filename=~s|^adm/wrapper/||;
                   2496: 	$realsymb=&Apache::lonnet::symbread($filename);
                   2497:     }
                   2498:     if (&discussion_open(undef,$realsymb) &&
1.157     albertel 2499: 	&Apache::lonnet::allowed('pch',$env{'request.course.id'}.
                   2500:         ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))) {
1.20      www      2501: 
1.13      www      2502:     my %contrib=('message'      => $email,
1.157     albertel 2503:                  'sendername'   => $env{'user.name'},
                   2504:                  'senderdomain' => $env{'user.domain'},
                   2505:                  'screenname'   => $env{'environment.screenname'},
                   2506:                  'plainname'    => $env{'environment.firstname'}.' '.
                   2507: 		                   $env{'environment.middlename'}.' '.
                   2508:                                    $env{'environment.lastname'}.' '.
                   2509:                                    $env{'enrironment.generation'},
1.78      raeburn  2510:                  'attachmenturl'=> $attachmenturl,
                   2511:                  'subject'      => $subject);
1.157     albertel 2512:     if ($env{'form.replydisc'}) {
                   2513: 	$contrib{'replyto'}=(split(/\:\:\:/,$env{'form.replydisc'}))[1];
1.65      www      2514:     }
1.14      www      2515:     if ($anon) {
                   2516: 	$contrib{'anonymous'}='true';
                   2517:     }
1.13      www      2518:     if (($symb) && ($email)) {
1.157     albertel 2519:         if ($env{'form.editdisc'}) {
1.102     raeburn  2520:             my %newcontrib = ();
                   2521:             $contrib{'ip'}=$ENV{'REMOTE_ADDR'};
                   2522:             $contrib{'host'}=$Apache::lonnet::perlvar{'lonHostID'};
                   2523:             $contrib{'timestamp'} = time;
                   2524:             $contrib{'history'} = '';
                   2525:             my $numoldver = 0;
1.157     albertel 2526:             my ($oldsymb,$oldidx)=split(/\:\:\:/,$env{'form.editdisc'});
1.132     albertel 2527: 	    &Apache::lonenc::check_decrypt(\$oldsymb);
1.110     raeburn  2528:             $oldsymb=~s|(bulletin___\d+___)adm/wrapper/|$1|;
1.102     raeburn  2529: # get timestamp for last post and history
1.157     albertel 2530:             my %oldcontrib=&Apache::lonnet::restore($oldsymb,$env{'request.course.id'},
                   2531:                      $env{'course.'.$env{'request.course.id'}.'.domain'},
                   2532:                      $env{'course.'.$env{'request.course.id'}.'.num'});
1.102     raeburn  2533:             if (defined($oldcontrib{$oldidx.':replyto'})) {
                   2534:                 $contrib{'replyto'} = $oldcontrib{$oldidx.':replyto'};
                   2535:             }
                   2536:             if (defined($oldcontrib{$oldidx.':history'})) {
                   2537:                 if ($oldcontrib{$oldidx.':history'} =~ /:/) {
                   2538:                     my @oldversions = split/:/,$oldcontrib{$oldidx.':history'};
                   2539:                     $numoldver = @oldversions;
                   2540:                 } else {
                   2541:                     $numoldver = 1;
                   2542:                 }
                   2543:                 $contrib{'history'} = $oldcontrib{$oldidx.':history'}.':';
                   2544:             }
1.108     raeburn  2545:             my $numnewver = $numoldver + 1;
1.102     raeburn  2546:             if (defined($oldcontrib{$oldidx.':subject'})) {
1.112     raeburn  2547:                 if ($oldcontrib{$oldidx.':subject'} =~ /^<version num="0">/) {
                   2548:                     $contrib{'subject'} = '<version num="'.$numnewver.'">'.&HTML::Entities::encode($contrib{'subject'},'<>&"').'</version>';
                   2549:                     $contrib{'subject'} = $oldcontrib{$oldidx.':subject'}.$contrib{'subject'};
1.108     raeburn  2550:                 } else {
1.112     raeburn  2551:                     $contrib{'subject'} = '<version num="0">'.&HTML::Entities::encode($oldcontrib{$oldidx.':subject'},'<>&"').'</version><version num="1">'.&HTML::Entities::encode($contrib{'subject'},'<>&"').'</version>';
1.108     raeburn  2552:                 }
1.102     raeburn  2553:             } 
                   2554:             if (defined($oldcontrib{$oldidx.':message'})) {
1.112     raeburn  2555:                 if ($oldcontrib{$oldidx.':message'} =~ /^<version num="0">/) {
                   2556:                     $contrib{'message'} = '<version num="'.$numnewver.'">'.&HTML::Entities::encode($contrib{'message'},'<>&"').'</version>';
                   2557:                     $contrib{'message'} = $oldcontrib{$oldidx.':message'}.$contrib{'message'};
1.108     raeburn  2558:                 } else {
1.112     raeburn  2559:                     $contrib{'message'} = '<version num="0">'.&HTML::Entities::encode($oldcontrib{$oldidx.':message'},'<>&"').'</version><version num="1">'.&HTML::Entities::encode($contrib{'message'},'<>&"').'</version>';
1.108     raeburn  2560:                 }
1.102     raeburn  2561:             }
                   2562:             $contrib{'history'} .= $oldcontrib{$oldidx.':timestamp'};
                   2563:             foreach (keys %contrib) {
                   2564:                 my $key = $oldidx.':'.&Apache::lonnet::escape($oldsymb).':'.$_;                                                                               
                   2565:                 $newcontrib{$key} = $contrib{$_};
                   2566:             }
1.157     albertel 2567:             my $put_reply = &Apache::lonnet::putstore($env{'request.course.id'},
1.102     raeburn  2568:                   \%newcontrib,
1.157     albertel 2569:                   $env{'course.'.$env{'request.course.id'}.'.domain'},
                   2570:                   $env{'course.'.$env{'request.course.id'}.'.num'});
1.102     raeburn  2571:             $status='Editing class discussion'.($anon?' (anonymous)':'');
                   2572:         } else {
                   2573:            $status='Adding to class discussion'.($anon?' (anonymous)':'').': '.
1.157     albertel 2574:            &Apache::lonnet::store(\%contrib,$symb,$env{'request.course.id'},
                   2575:                      $env{'course.'.$env{'request.course.id'}.'.domain'},
                   2576: 		     $env{'course.'.$env{'request.course.id'}.'.num'});
1.102     raeburn  2577:         }
1.21      www      2578:         my %storenewentry=($symb => time);
1.63      albertel 2579:         $status.='<br />'.&mt('Updating discussion time').': '.
1.21      www      2580:         &Apache::lonnet::put('discussiontimes',\%storenewentry,
1.157     albertel 2581:                      $env{'course.'.$env{'request.course.id'}.'.domain'},
                   2582: 		     $env{'course.'.$env{'request.course.id'}.'.num'});
1.13      www      2583:     }
1.17      www      2584:     my %record=&Apache::lonnet::restore('_discussion');
                   2585:     my ($temp)=keys %record;
                   2586:     unless ($temp=~/^error\:/) {
                   2587:        my %newrecord=();
                   2588:        $newrecord{'resource'}=$symb;
                   2589:        $newrecord{'subnumber'}=$record{'subnumber'}+1;
1.63      albertel 2590:        $status.='<br />'.&mt('Registering').': '.
1.21      www      2591:                &Apache::lonnet::cstore(\%newrecord,'_discussion');
1.20      www      2592:     }
                   2593:     } else {
                   2594: 	$status.='Failed.';
1.17      www      2595:     }
1.63      albertel 2596:     return $status.'<br />';   
1.13      www      2597: }
                   2598: 
1.33      www      2599: # ----------------------------------------------------------- Preview function
                   2600: 
                   2601: sub show_preview {
                   2602:     my $r=shift;
1.135     albertel 2603:     &Apache::loncommon::content_type($r,'text/html');
                   2604:     $r->send_http_header;
1.157     albertel 2605:     my $message=&clear_out_html($env{'form.comment'});
1.33      www      2606:     $message=~s/\n/\<br \/\>/g;
1.106     www      2607:     $message=&Apache::lonspeller::markeduptext($message);
1.33      www      2608:     $message=&Apache::lontexconvert::msgtexconverted($message);
1.157     albertel 2609:     my $subject=&clear_out_html($env{'form.subject'});
1.78      raeburn  2610:     $subject=~s/\n/\<br \/\>/g;
                   2611:     $subject=&Apache::lontexconvert::msgtexconverted($subject);
1.153     albertel 2612:     my $html=&Apache::lonxml::xmlbegin();
                   2613:     $r->print($html.'<head>'.
                   2614: 	      '</head><body><table border="2"><tr><td>'.
                   2615: 	      '<b>Subject:</b> '.$subject.'<br /><br />'.
                   2616: 	      $message.'</td></tr></table></body></html>');
1.33      www      2617: }
                   2618: 
                   2619: sub generate_preview_button {
1.107     www      2620:     my $pre=&mt("Show Preview and Check Spelling");
1.33      www      2621:     return(<<ENDPREVIEW);
                   2622: <form name="preview" action="/adm/feedback?preview=1" method="post" target="preview">
1.78      raeburn  2623: <input type="hidden" name="subject">
1.33      www      2624: <input type="hidden" name="comment" />
1.65      www      2625: <input type="button" value="$pre"
1.119     albertel 2626: onClick="if (typeof(document.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=document.mailform.comment.value;this.form.subject.value=document.mailform.subject.value;this.form.submit();" />
1.33      www      2627: </form>
                   2628: ENDPREVIEW
                   2629: }
1.71      www      2630: 
1.108     raeburn  2631: sub modify_attachments {
                   2632:     my ($r,$currnewattach,$currdelold,$symb,$idx,$attachmenturls)=@_;
1.157     albertel 2633:     my $orig_subject = &Apache::lonnet::unescape($env{'form.subject'});
1.124     raeburn  2634:     my $subject=&clear_out_html($orig_subject);
1.108     raeburn  2635:     $subject=~s/\n/\<br \/\>/g;
                   2636:     $subject=&Apache::lontexconvert::msgtexconverted($subject);
1.157     albertel 2637:     my $timestamp=$env{'form.timestamp'};
                   2638:     my $numoldver=$env{'form.numoldver'};
1.108     raeburn  2639:     my $bodytag=&Apache::loncommon::bodytag('Discussion Post Attachments',
                   2640:                                           '','');
                   2641:     my $msg = '';
1.113     raeburn  2642:     my %attachments = ();
1.108     raeburn  2643:     my %currattach = ();
                   2644:     if ($idx) {
1.113     raeburn  2645:         &extract_attachments($attachmenturls,$idx,$numoldver,\$msg,\%attachments,\%currattach,$currdelold);
1.108     raeburn  2646:     }
1.139     albertel 2647:     &Apache::lonenc::check_encrypt(\$symb);
1.152     albertel 2648:     my $html=&Apache::lonxml::xmlbegin();
1.108     raeburn  2649:     $r->print(<<END);
1.152     albertel 2650: $html
1.108     raeburn  2651: <head>
                   2652: <title>Managing Attachments</title>
                   2653: <script>
                   2654:  function setAction () {
                   2655:    document.modattachments.action = document.modattachments.origpage.value;
                   2656:    document.modattachments.submit();
                   2657:  }
                   2658: </script> 
                   2659: </head>
                   2660: $bodytag
                   2661: <form name="modattachments" method="post" enctype="multipart/form-data" action="/adm/feedback?attach=$symb">
                   2662:  <table border="2">
                   2663:   <tr>
                   2664:    <td>
1.124     raeburn  2665:     <b>Subject:</b> $subject</b><br /><br />
1.108     raeburn  2666: END
                   2667:     if ($idx) {
                   2668:         if ($attachmenturls) {
                   2669:             my @currold = keys %currattach;
                   2670:             if (@currold > 0) {
                   2671:                 $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");  
1.113     raeburn  2672:                 foreach my $id (@currold) {
                   2673:                     my $attachurl = &HTML::Entities::decode($attachments{$id}{'filename'}); 
                   2674:                     $attachurl =~ m#/([^/]+)$#;
1.151     albertel 2675:                     $r->print('<label><input type="checkbox" name="deloldattach" value="'.$id.'" />&nbsp;'.$1.'</label><br />'."\n");
1.108     raeburn  2676:                 }
                   2677:                 $r->print("<br />");
                   2678:             }
                   2679:         }
                   2680:     }
                   2681:     if (@{$currnewattach} > 0) {
                   2682:         $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");
                   2683:         foreach (@{$currnewattach}) {
                   2684:             $_ =~ m#/([^/]+)$#;
1.151     albertel 2685:             $r->print('<label><input type="checkbox" name="delnewattach" value="'.$_.'" />&nbsp;'.$1.'</label><br />'."\n");
1.108     raeburn  2686:         }
                   2687:         $r->print("<br />"); 
                   2688:     }
                   2689:     $r->print(<<END);
                   2690:    Add a new attachment to this post.&nbsp;<input type="file" name="addnewattach" /><input type="button" name="upload" value="Upload" onClick="this.form.submit()" />    
                   2691:    </td>
                   2692:   </tr>
                   2693:  </table>
1.157     albertel 2694: <input type="hidden" name="subject" value="$env{'form.subject'}" />
                   2695: <input type="hidden" name="comment" value="$env{'form.comment'}" />
                   2696: <input type="hidden" name="timestamp" value="$env{'form.timestamp'}" />
                   2697: <input type="hidden" name="idx" value="$env{'form.idx'}" />
                   2698: <input type="hidden" name="numoldver" value="$env{'form.numoldver'}" />
                   2699: <input type="hidden" name="origpage" value="$env{'form.origpage'}" />
                   2700: <input type="hidden" name="anondiscuss" value="$env{'form.anondiscuss'}" />
                   2701: <input type="hidden" name="discuss" value="$env{'form.discuss'}" />
1.108     raeburn  2702: END
                   2703:     foreach (@{$currnewattach}) {
                   2704:         $r->print('<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n");
                   2705:     }
                   2706:     foreach (@{$currdelold}) {
                   2707:         $r->print('<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n");
                   2708:     }
                   2709:     $r->print(<<END);
                   2710:  <input type="button" name="rtntoedit" value="Store Changes" onClick="setAction()"/>
                   2711: </form>
                   2712: </body>
                   2713: </html>
                   2714: END
                   2715:     return;
                   2716: }
                   2717: 
                   2718: sub process_attachments {
                   2719:     my ($currnewattach,$currdelold,$keepold) = @_;
1.158     albertel 2720: 
                   2721:     @{$currnewattach}=
                   2722: 	&Apache::loncommon::get_env_multiple('form.currnewattach');
                   2723:     @{$currdelold}=
                   2724: 	&Apache::loncommon::get_env_multiple('form.deloldattach');
1.157     albertel 2725:     if (exists($env{'form.delnewattach'})) {
1.158     albertel 2726:         my @currdelnew =
                   2727: 	    &Apache::loncommon::get_env_multiple('form.delnewattach');
1.108     raeburn  2728:         my @currnew = ();
                   2729:         foreach my $newone (@{$currnewattach}) {
                   2730:             my $delflag = 0;
                   2731:             foreach (@currdelnew) {
                   2732:                 if ($newone eq $_) {
                   2733:                     $delflag = 1;
                   2734:                     last;
                   2735:                 }
                   2736:             }
                   2737:             unless ($delflag) {
                   2738:                 push @currnew, $newone;
                   2739:             }
                   2740:         }
                   2741:         @{$currnewattach} = @currnew;
                   2742:     }
1.158     albertel 2743:     @{$keepold} = &Apache::loncommon::get_env_multiple('form.keepold');
1.108     raeburn  2744: }
                   2745: 
                   2746: sub generate_attachments_button {
                   2747:     my ($idx,$attachnum,$ressymb,$now,$currnewattach,$deloldattach,$numoldver,$mode) = @_;
                   2748:     my $origpage = $ENV{'REQUEST_URI'};
                   2749:     my $att=$attachnum.' '.&mt("attachments");
                   2750:     my $response = (<<END);
                   2751: <form name="attachment" action="/adm/feedback?attach=$ressymb" method="post">
                   2752: Click to add/remove attachments:&nbsp;<input type="button" value="$att"
1.124     raeburn  2753: onClick="if (typeof(document.mailform.onsubmit)=='function') {document.mailform.onsubmit();};this.form.comment.value=escape(document.mailform.comment.value);this.form.subject.value=escape(document.mailform.subject.value);
1.108     raeburn  2754: END
                   2755:     unless ($mode eq 'board') {
                   2756:         $response .= 'javascript:anonchk();';
                   2757:     }
                   2758:     $response .= (<<ENDATTACH);
                   2759: this.form.submit();" />
                   2760: <input type="hidden" name="origpage" value="$origpage" />
                   2761: <input type="hidden" name="idx" value="$idx" />
                   2762: <input type="hidden" name="timestamp" value="$now" />
                   2763: <input type="hidden" name="subject" />
                   2764: <input type="hidden" name="comment" />
                   2765: <input type="hidden" name="anondiscuss" value = "0";
                   2766: <input type="hidden" name="discuss" value = "0";
                   2767: <input type="hidden" name="numoldver" value="$numoldver" />
                   2768: ENDATTACH
                   2769:     if (defined($deloldattach)) {
                   2770:         if (@{$deloldattach} > 0) {
                   2771:             foreach (@{$deloldattach}) {
                   2772:                 $response .= '<input type="hidden" name="deloldattach" value="'.$_.'" />'."\n";
                   2773:             }
                   2774:         }
                   2775:     }
                   2776:     if (defined($currnewattach)) {
                   2777:         if (@{$currnewattach} > 0) {
                   2778:             foreach (@{$currnewattach}) {
                   2779:                 $response .= '<input type="hidden" name="currnewattach" value="'.$_.'" />'."\n";
                   2780:             }
                   2781:         }
                   2782:     }
                   2783:     $response .= '</form>';
                   2784:     return $response;
                   2785: }
                   2786: 
                   2787: sub extract_attachments {
                   2788:     my ($attachmenturls,$idx,$numoldver,$message,$attachments,$currattach,$currdelold) = @_;
1.116     raeburn  2789:     %{$attachments}=();
                   2790:     &get_post_attachments($attachments,$attachmenturls);
                   2791:     foreach my $id (sort keys %{$attachments}) {
                   2792:         if (exists($$attachments{$id}{$numoldver})) {
                   2793:             if (defined($currdelold)) {
                   2794:                 if (@{$currdelold} > 0) {
                   2795:                     unless (grep/^$id$/,@{$currdelold}) {
                   2796:                         $$currattach{$id} = $$attachments{$id}{$numoldver}; 
1.108     raeburn  2797:                     }
1.113     raeburn  2798:                 } else {
                   2799:                     $$currattach{$id} = $$attachments{$id}{$numoldver};
1.108     raeburn  2800:                 }
1.116     raeburn  2801:             } else {
                   2802:                 $$currattach{$id} = $$attachments{$id}{$numoldver};
1.108     raeburn  2803:             }
                   2804:         }
1.116     raeburn  2805:     }
                   2806:     my @attached = (sort { $a <=> $b } keys %{$currattach});
                   2807:     if (@attached == 1) {
                   2808:         my $id = $attached[0];
                   2809:         my $attachurl;
                   2810:         if ($attachmenturls =~ m/^<attachment id="0">/) {
                   2811:             $attachurl = &HTML::Entities::decode($$attachments{$id}{'filename'});
                   2812:         } else {
                   2813:             $attachurl = $$attachments{$id}{'filename'};
                   2814:         }
                   2815:         $attachurl=~m|/([^/]+)$|;
                   2816:         $$message.='<br /><a href="'.$attachurl.'"><tt>'.
                   2817:         $1.'</tt></a><br />';
                   2818:         &Apache::lonnet::allowuploaded('/adm/feedback',
                   2819:                                $attachurl);
                   2820:     } elsif (@attached > 1) {
                   2821:         $$message.='<ol>';
                   2822:         foreach (@attached) {
                   2823:             my $id = $_;
1.113     raeburn  2824:             my $attachurl = &HTML::Entities::decode($$attachments{$id}{'filename'});
1.116     raeburn  2825:             my ($fname)
                   2826:               =($attachurl=~m|/([^/]+)$|);
                   2827:             $$message .= '<li><a href="'.$attachurl.
                   2828:               '"><tt>'.
                   2829:               $fname.'</tt></a></li>';
1.108     raeburn  2830:             &Apache::lonnet::allowuploaded('/adm/feedback',
1.116     raeburn  2831:                              $attachurl);
1.108     raeburn  2832:         }
1.116     raeburn  2833:         $$message .= '</ol>';
1.108     raeburn  2834:     }
                   2835: }
                   2836: 
                   2837: sub construct_attachmenturl {
                   2838:     my ($currnewattach,$keepold,$symb,$idx)=@_;
                   2839:     my $oldattachmenturl;
                   2840:     my $newattachmenturl;
1.113     raeburn  2841:     my $startnum = 0;
1.108     raeburn  2842:     my $currver = 0;
1.157     albertel 2843:     if (($env{'form.editdisc'}) && ($idx)) {
                   2844:         my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   2845:                        $env{'course.'.$env{'request.course.id'}.'.domain'},
                   2846:                        $env{'course.'.$env{'request.course.id'}.'.num'});
1.108     raeburn  2847:         $oldattachmenturl = $contrib{$idx.':attachmenturl'};
                   2848:         if ($contrib{$idx.':history'}) {
                   2849:             if ($contrib{$idx.':history'} =~ /:/) {
                   2850:                 my @oldversions = split/:/,$contrib{$idx.':history'};
                   2851:                 $currver = 1 + scalar(@oldversions);
                   2852:             } else {
                   2853:                 $currver = 2;
                   2854:             }
                   2855:         } else {
                   2856:             $currver = 1;
                   2857:         }
                   2858:         if ($oldattachmenturl) {
1.113     raeburn  2859:             if ($oldattachmenturl =~ m/^<attachment id="0">/) {
                   2860:                 my %attachments = ();
                   2861:                 my $prevver = $currver-1;
                   2862:                 &get_post_attachments(\%attachments,$oldattachmenturl);
1.116     raeburn  2863:                 my $numattach = scalar(keys %attachments);
1.113     raeburn  2864:                 $startnum += $numattach;
                   2865:                 foreach my $num (sort {$a <=> $b} keys %attachments) {
                   2866:                     $newattachmenturl .= '<attachment id="'.$num.'"><filename>'.$attachments{$num}{'filename'}.'</filename>';
1.116     raeburn  2867:                     foreach $_ (sort {$a <=> $b} keys %{$attachments{$num}}) {
                   2868:                         unless ($_ eq 'filename') {
                   2869:                             $newattachmenturl .= '<post id="'.$_.'">'.$attachments{$num}{$_}.'</post>';
                   2870:                         }
1.113     raeburn  2871:                     }
                   2872:                     if (grep/^$num$/,@{$keepold}) {
                   2873:                         $newattachmenturl .= '<post id="'.$currver.'">'.$attachments{$num}{$prevver}.'</post>';
1.108     raeburn  2874:                     }
1.113     raeburn  2875:                     $newattachmenturl .= '</attachment>';
1.108     raeburn  2876:                 }
                   2877:             } else {
1.116     raeburn  2878:                 $newattachmenturl = '<attachment id="0"><filename>'.&HTML::Entities::encode($oldattachmenturl).'</filename><post id="0">n</post>';
1.108     raeburn  2879:                 unless (grep/^0$/,@{$keepold}) {
1.113     raeburn  2880:                     $newattachmenturl .= '<post id="1">n</post>';
1.108     raeburn  2881:                 }
1.113     raeburn  2882:                 $newattachmenturl .= '</attachment>';
1.108     raeburn  2883:                 $startnum ++;
                   2884:             }
                   2885:         }
                   2886:     }
                   2887:     for (my $i=0; $i<@{$currnewattach}; $i++) {
                   2888:         my $attachnum = $startnum + $i;
1.113     raeburn  2889:         $newattachmenturl .= '<attachment id="'.$attachnum.'"><filename>'.&HTML::Entities::encode($$currnewattach[$i]).'</filename><post id="'.$currver.'">n</post></attachment>';
1.108     raeburn  2890:     }
                   2891:     return $newattachmenturl; 
                   2892: }
1.128     raeburn  2893: 
                   2894: sub has_discussion {
                   2895:     my $resourcesref = shift;
                   2896:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2897:     my @allres=$navmap->retrieveResources();
                   2898:     foreach my $resource (@allres) {
                   2899:         if ($resource->hasDiscussion()) {
1.162     albertel 2900:             my $ressymb = $resource->wrap_symb();
1.128     raeburn  2901:             push @{$resourcesref}, $ressymb;
                   2902:         }
                   2903:     }
                   2904:     return;
1.143     raeburn  2905: }
                   2906: 
                   2907: sub sort_filter_names {
                   2908:     my ($sort_types,$role_types,$status_types) = @_;
                   2909:     %{$sort_types} = (
                   2910:                      ascdate => 'Date order - oldest first',
                   2911:                      descdate => 'Date order - newest first',
                   2912:                      thread => 'Threaded',
                   2913:                      subject => 'By subject',
                   2914:                      username => 'By domain and username',
                   2915:                      lastfirst => 'By last name, first name'
                   2916:                    );
                   2917:     %{$role_types} = (
                   2918:                      all => 'All roles',
                   2919:                      st  => 'Students',
                   2920:                      cc  => 'Course Coordinators',
                   2921:                      in  => 'Instructors',
                   2922:                      ta  => 'TAs',
                   2923:                      ep  => 'Exam proctors',
                   2924:                      ad  => 'Administrators',
                   2925:                      cr  => 'Custom roles'
                   2926:                    );
                   2927:     %{$status_types} = (
                   2928:                      all     => 'Roles of any status',
                   2929:                      Active => 'Only active roles',
                   2930:                      Expired => 'Only inactive roles'
                   2931:                    );
                   2932: }
1.108     raeburn  2933:   
1.6       albertel 2934: sub handler {
                   2935:   my $r = shift;
1.8       www      2936:   if ($r->header_only) {
1.71      www      2937:      &Apache::loncommon::content_type($r,'text/html');
1.8       www      2938:      $r->send_http_header;
                   2939:      return OK;
                   2940:   }
1.15      www      2941: 
                   2942: # --------------------------- Get query string for limited number of parameters
                   2943: 
1.97      raeburn  2944:   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.137     albertel 2945:          ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export']);
1.143     raeburn  2946: 
1.157     albertel 2947:   if ($env{'form.discsymb'}) {
                   2948:       my ($symb,$feedurl) = &get_feedurl_and_clean_symb($env{'form.discsymb'});
1.111     raeburn  2949:       my $readkey = $symb.'_read';
                   2950:       my $chgcount = 0;
1.157     albertel 2951:       my %readinghash = &Apache::lonnet::get('nohist_'.$env{'request.course.id'}.'_discuss',[$readkey],$env{'user.domain'},$env{'user.name'});
                   2952:       foreach my $key (keys %env) {
1.111     raeburn  2953:           if ($key =~ m/^form\.postunread_(\d+)/) {
                   2954:               if ($readinghash{$readkey} =~ /\.$1\./) {
                   2955:                   $readinghash{$readkey} =~ s/\.$1\.//;
                   2956:                   $chgcount ++;
                   2957:               }
                   2958:           } elsif ($key =~ m/^form\.postread_(\d+)/) {
                   2959:               unless ($readinghash{$readkey} =~ /\.$1\./) {
                   2960:                   $readinghash{$readkey} .= '.'.$1.'.';
                   2961:                   $chgcount ++;
                   2962:               }
                   2963:           }
                   2964:       }
                   2965:       if ($chgcount > 0) {
1.157     albertel 2966:           &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',
                   2967: 			  \%readinghash,$env{'user.domain'},$env{'user.name'});
1.111     raeburn  2968:       }
1.133     albertel 2969:       &redirect_back($r,$feedurl,&mt('Marked postings read/unread').'<br />',
1.157     albertel 2970: 		     '0','0','',$env{'form.previous'},'','','',);
1.111     raeburn  2971:       return OK;
                   2972:   }
1.157     albertel 2973:   if ($env{'form.allversions'}) {
1.109     raeburn  2974:       &Apache::loncommon::content_type($r,'text/html');
                   2975:       $r->send_http_header;
1.152     albertel 2976:       my $html=&Apache::lonxml::xmlbegin();
1.133     albertel 2977:       my $bodytag=&Apache::loncommon::bodytag('Discussion Post Versions');
1.143     raeburn  2978:       $r->print(<<END);
1.152     albertel 2979: $html
1.109     raeburn  2980: <head>
                   2981: <title>Post Versions</title>
                   2982: <meta http-equiv="pragma" content="no-cache" />
                   2983: </head>
                   2984: $bodytag
                   2985: END
1.157     albertel 2986:       my $crs='/'.$env{'request.course.id'};
                   2987:       if ($env{'request.course.sec'}) {
                   2988:           $crs.='_'.$env{'request.course.sec'};
1.109     raeburn  2989:       }
1.133     albertel 2990:       $crs=~s|_|/|g;
1.109     raeburn  2991:       my $seeid=&Apache::lonnet::allowed('rin',$crs);
1.157     albertel 2992:       my ($symb,$idx)=split(/\:\:\:/,$env{'form.allversions'});
1.133     albertel 2993:       ($symb)=&get_feedurl_and_clean_symb($symb);
1.109     raeburn  2994:       if ($idx > 0) {
1.116     raeburn  2995:           my %messages = ();
                   2996:           my %subjects = ();
                   2997:           my %attachmsgs = ();
                   2998:           my %allattachments = ();
                   2999:           my %imsfiles = ();
                   3000:           my ($screenname,$plainname);
1.157     albertel 3001:           my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   3002:                            $env{'course.'.$env{'request.course.id'}.'.domain'},
                   3003:                            $env{'course.'.$env{'request.course.id'}.'.num'});
1.133     albertel 3004:           $r->print(&get_post_contents(\%contrib,$idx,$seeid,'allversions',\%messages,\%subjects,\%allattachments,\%attachmsgs,\%imsfiles,\$screenname,\$plainname));
1.109     raeburn  3005:       }
                   3006:       return OK;
                   3007:   }
1.157     albertel 3008:   if ($env{'form.posterlist'}) {
                   3009:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.applysort'});
                   3010:       &print_showposters($r,$symb,$env{'form.previous'},$feedurl,
                   3011: 			 $env{'form.sortposts'});
1.101     raeburn  3012:       return OK;
                   3013:   }
1.157     albertel 3014:   if ($env{'form.userpick'}) {
1.133     albertel 3015:       my @posters = &Apache::loncommon::get_env_multiple('form.stuinfo');
1.157     albertel 3016:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.userpick'});
1.101     raeburn  3017:       my $numpicks = @posters;
1.133     albertel 3018:       my %discinfo;
                   3019:       $discinfo{$symb.'_userpick'} = join('&',@posters);
1.157     albertel 3020:       &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',
                   3021: 			   \%discinfo,$env{'user.domain'},$env{'user.name'});
1.133     albertel 3022:       &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0',
1.157     albertel 3023: 		     '',$env{'form.previous'},$env{'form.sortposts'},'','','',
1.133     albertel 3024: 		     $numpicks);
1.101     raeburn  3025:       return OK;
                   3026:   }
1.157     albertel 3027:   if ($env{'form.applysort'}) {
                   3028:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.applysort'});
1.133     albertel 3029:       &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0',
1.157     albertel 3030: 		     '',$env{'form.previous'},$env{'form.sortposts'},
                   3031: 		     $env{'form.rolefilter'},$env{'form.statusfilter'},
                   3032: 		     $env{'form.sectionpick'});
1.100     raeburn  3033:       return OK;
1.157     albertel 3034:   } elsif ($env{'form.cmd'} eq 'sortfilter') {
                   3035:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
                   3036:       &print_sortfilter_options($r,$symb,$env{'form.previous'},$feedurl);
1.100     raeburn  3037:       return OK;
1.157     albertel 3038:   } elsif ($env{'form.navtime'}) {
1.99      raeburn  3039:       my %discinfo = ();
                   3040:       my @resources = ();
1.157     albertel 3041:       if (defined($env{'form.navmaps'})) {
                   3042:           if ($env{'form.navmaps'} =~ /:/) {
                   3043:               @resources = split/:/,$env{'form.navmaps'};
1.128     raeburn  3044:           } else {
1.157     albertel 3045:               @resources = ("$env{'form.navmaps'}");
1.128     raeburn  3046:           }
1.99      raeburn  3047:       } else {
1.128     raeburn  3048:           &has_discussion(\@resources);
1.99      raeburn  3049:       }
                   3050:       my $numitems = @resources;
                   3051:       my $feedurl = '/adm/navmaps';
1.157     albertel 3052:       if ($env{'form.navurl'}) { $feedurl .= '?'.$env{'form.navurl'}; }
1.99      raeburn  3053:       my %lt = &Apache::lonlocal::texthash(
                   3054:           'mnpa' => 'Marked "New" posts as read in a total of',
1.128     raeburn  3055:           'robb' => 'resources/bulletin boards.',
                   3056:           'twnp' => 'There are currently no resources or bulletin boards with unread discussion postings.'
1.99      raeburn  3057:       );       
                   3058:       foreach (@resources) {
                   3059:           my $ressymb=$_;
1.132     albertel 3060: 	  &Apache::lonenc::check_decrypt(\$ressymb);
1.99      raeburn  3061:           my $lastkey = $ressymb.'_lastread';
1.157     albertel 3062:           $discinfo{$lastkey} = $env{'form.navtime'};
1.99      raeburn  3063:       }
1.128     raeburn  3064:       my $textline = "<b>$lt{'mnpa'} $numitems $lt{'robb'}</b>";
                   3065:       if ($numitems > 0) {
1.157     albertel 3066:           &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',
                   3067: 			     \%discinfo,$env{'user.domain'},$env{'user.name'});
1.128     raeburn  3068:       } else {
                   3069:           $textline = "<b>$lt{'twnp'}</b>";
                   3070:       }
1.99      raeburn  3071:       &Apache::loncommon::content_type($r,'text/html');
                   3072:       $r->send_http_header;
1.150     albertel 3073:       my $logo=&Apache::loncommon::lonhttpdurl('/adm/lonIcons/lonlogos.gif');
1.152     albertel 3074:       my $html=&Apache::lonxml::xmlbegin();
1.99      raeburn  3075:       $r->print (<<ENDREDIR);
1.152     albertel 3076: $html
1.99      raeburn  3077: <head>
                   3078: <title>New posts marked as read</title>
                   3079: <meta http-equiv="pragma" content="no-cache" />
                   3080: <meta HTTP-EQUIV="Refresh" CONTENT="2; url=$feedurl" />
                   3081: </head>
                   3082: <body bgcolor="#FFFFFF" onLoad='if (window.name!="loncapaclient") { this.document.reldt.submit(); self.close(); }'>
1.150     albertel 3083: <img align="right" src="$logo" />
1.128     raeburn  3084: $textline
1.99      raeburn  3085: <form name="reldt" action="$feedurl" target="loncapaclient">
                   3086: </form>
1.121     albertel 3087: <br /><a href="$feedurl">Continue</a>
1.99      raeburn  3088: </body>
                   3089: </html>
                   3090: ENDREDIR
                   3091:       return OK;
1.157     albertel 3092:   } elsif ($env{'form.modifydisp'}) {
                   3093:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.modifydisp'});
1.133     albertel 3094:       my ($dispchgA,$dispchgB,$markchg,$toggchg) = 
1.157     albertel 3095: 	  split(/_/,$env{'form.changes'});
                   3096:       &print_display_options($r,$symb,$env{'form.previous'},$dispchgA,
1.133     albertel 3097: 			     $dispchgB,$markchg,$toggchg,$feedurl);
1.97      raeburn  3098:       return OK;
1.157     albertel 3099:   } elsif ($env{'form.markondisp'} || $env{'form.markonread'} ||
                   3100: 	   $env{'form.allposts'}   || $env{'form.onlyunread'} ||
                   3101: 	   $env{'form.onlyunmark'} || $env{'form.toggoff'}    ||
                   3102: 	   $env{'form.toggon'}     || $env{'form.markread'}) {
                   3103:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
1.137     albertel 3104:       my %discinfo;
1.133     albertel 3105: # ------------------------ Modify setting for read/unread toggle for each post 
1.157     albertel 3106:       if ($env{'form.toggoff'}) { $discinfo{$symb.'_readtoggle'}=0; }
                   3107:       if ($env{'form.toggon'})  { $discinfo{$symb.'_readtoggle'}=1; }
1.133     albertel 3108: # --------- Modify setting for identification of 'NEW' posts in this discussion
1.157     albertel 3109:       if ($env{'form.markondisp'}) {
1.137     albertel 3110: 	  $discinfo{$symb.'_lastread'} = time;
                   3111: 	  $discinfo{$symb.'_markondisp'} = 1;
                   3112:       }
1.157     albertel 3113:       if ($env{'form.markonread'}) {
                   3114: 	  if ( $env{'form.previous'} > 0 ) {
                   3115: 	      $discinfo{$symb.'_lastread'} = $env{'form.previous'};
1.137     albertel 3116: 	  }
                   3117: 	  $discinfo{$symb.'_markondisp'} = 0;
1.84      raeburn  3118:       }
1.133     albertel 3119: # --------------------------------- Modify display setting for this discussion 
1.157     albertel 3120:       if ($env{'form.allposts'}) {
1.137     albertel 3121: 	  $discinfo{$symb.'_showonlyunread'} = 0;
                   3122: 	  $discinfo{$symb.'_showonlyunmark'} = 0;
1.84      raeburn  3123:       }
1.157     albertel 3124:       if ($env{'form.onlyunread'}) { $discinfo{$symb.'_showonlyunread'} = 1;  }
                   3125:       if ($env{'form.onlyunmark'}) { $discinfo{$symb.'_showonlyunmark'} = 1;  }
1.137     albertel 3126: # ----------------------------------------------------- Mark new posts not NEW 
1.157     albertel 3127:       if ($env{'form.markread'})   { $discinfo{$symb.'_lastread'} = time; }
                   3128:       &Apache::lonnet::put('nohist_'.$env{'request.course.id'}.'_discuss',
                   3129: 			   \%discinfo,$env{'user.domain'},$env{'user.name'});
                   3130:       my $previous=$env{'form.previous'};
                   3131:       if ($env{'form.markondisp'}) { $previous=undef; }
1.133     albertel 3132:       &redirect_back($r,$feedurl,&mt('Changed display status').'<br />',
                   3133: 		     '0','0','',$previous);
1.84      raeburn  3134:       return OK;
1.157     albertel 3135:   } elsif (($env{'form.hide'}) || ($env{'form.unhide'})) {
1.15      www      3136: # ----------------------------------------------------------------- Hide/unhide
1.157     albertel 3137:       my $entry=$env{'form.hide'}?$env{'form.hide'}:$env{'form.unhide'};
1.133     albertel 3138:       my ($symb,$idx)=split(/\:\:\:/,$entry);
                   3139:       ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
1.15      www      3140: 
1.157     albertel 3141:       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   3142:                           $env{'course.'.$env{'request.course.id'}.'.domain'},
                   3143: 		          $env{'course.'.$env{'request.course.id'}.'.num'});
1.15      www      3144: 
1.133     albertel 3145:       my $currenthidden=$contrib{'hidden'};
                   3146:       my $currentstudenthidden=$contrib{'studenthidden'};
1.15      www      3147: 
1.157     albertel 3148:       my $crs='/'.$env{'request.course.id'};
                   3149:       if ($env{'request.course.sec'}) {
                   3150: 	  $crs.='_'.$env{'request.course.sec'};
1.133     albertel 3151:       }
                   3152:       $crs=~s/\_/\//g;
                   3153:       my $seeid=&Apache::lonnet::allowed('rin',$crs);
1.102     raeburn  3154: 
1.157     albertel 3155:       if ($env{'form.hide'}) {
1.133     albertel 3156: 	  $currenthidden.='.'.$idx.'.';
                   3157: 	  unless ($seeid) {
                   3158: 	      $currentstudenthidden.='.'.$idx.'.';
                   3159: 	  }
                   3160:       } else {
                   3161: 	  $currenthidden=~s/\.$idx\.//g;
                   3162:       }
                   3163:       my %newhash=('hidden' => $currenthidden);
1.157     albertel 3164:       if ( ($env{'form.hide'}) && (!$seeid) ) {
1.133     albertel 3165: 	  $newhash{'studenthidden'} = $currentstudenthidden;
                   3166:       }
1.38      www      3167: 
1.157     albertel 3168:       &Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},
                   3169:                            $env{'course.'.$env{'request.course.id'}.'.domain'},
                   3170: 			   $env{'course.'.$env{'request.course.id'}.'.num'});
1.38      www      3171: 
1.133     albertel 3172:       &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',
1.157     albertel 3173: 		     '0','0','',$env{'form.previous'});
1.135     albertel 3174:       return OK;
1.157     albertel 3175:   } elsif ($env{'form.cmd'}=~/^(threadedoff|threadedon)$/) {
                   3176:       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
                   3177:       if ($env{'form.cmd'} eq 'threadedon') {
1.69      www      3178: 	  &Apache::lonnet::put('environment',{'threadeddiscussion' => 'on'});
                   3179: 	  &Apache::lonnet::appenv('environment.threadeddiscussion' => 'on');
                   3180:       } else {
                   3181:  	  &Apache::lonnet::del('environment',['threadeddiscussion']);
                   3182: 	  &Apache::lonnet::delenv('environment\.threadeddiscussion');
1.72      albertel 3183:       }
1.133     albertel 3184:       &redirect_back($r,$feedurl,&mt('Changed discussion view mode').'<br />',
1.157     albertel 3185: 		     '0','0','',$env{'form.previous'});
1.135     albertel 3186:       return OK;
1.157     albertel 3187:   } elsif ($env{'form.deldisc'}) {
1.38      www      3188: # --------------------------------------------------------------- Hide for good
1.157     albertel 3189:       my ($symb,$idx)=split(/\:\:\:/,$env{'form.deldisc'});
1.133     albertel 3190:       ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
1.157     albertel 3191:       my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   3192:                           $env{'course.'.$env{'request.course.id'}.'.domain'},
                   3193: 		          $env{'course.'.$env{'request.course.id'}.'.num'});
1.135     albertel 3194:       my %newhash=('deleted' => $contrib{'deleted'}.".$idx.");
1.157     albertel 3195:       &Apache::lonnet::store(\%newhash,$symb,$env{'request.course.id'},
                   3196: 			   $env{'course.'.$env{'request.course.id'}.'.domain'},
                   3197: 			   $env{'course.'.$env{'request.course.id'}.'.num'});
1.135     albertel 3198:       &redirect_back($r,$feedurl,&mt('Changed discussion status').'<br />',
1.157     albertel 3199: 		     '0','0','',$env{'form.previous'});
1.135     albertel 3200:       return OK;
1.157     albertel 3201:   } elsif ($env{'form.preview'}) {
1.33      www      3202: # -------------------------------------------------------- User wants a preview
                   3203:       &show_preview($r);
1.135     albertel 3204:       return OK;
1.157     albertel 3205:   } elsif ($env{'form.attach'}) {
1.108     raeburn  3206: # -------------------------------------------------------- Work on attachments
                   3207:       &Apache::loncommon::content_type($r,'text/html');
                   3208:       $r->send_http_header;
                   3209:       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','addnewattach','delnewattach','timestamp','numoldver','idx','anondiscuss','discuss']);
1.133     albertel 3210:       my (@currnewattach,@currdelold,@keepold);
1.108     raeburn  3211:       &process_attachments(\@currnewattach,\@currdelold,\@keepold);
1.157     albertel 3212:       if (exists($env{'form.addnewattach.filename'})) {
                   3213:           unless (length($env{'form.addnewattach'})>131072) {
                   3214:               my $subdir = 'feedback/'.$env{'form.timestamp'};
1.108     raeburn  3215:               my $newattachment=&Apache::lonnet::userfileupload('addnewattach',undef,$subdir);
1.139     albertel 3216: 	      push @currnewattach, $newattachment;
1.108     raeburn  3217:           }
                   3218:       }
1.133     albertel 3219:       my $attachmenturls;
1.157     albertel 3220:       my ($symb) = &get_feedurl_and_clean_symb($env{'form.attach'});
                   3221:       my $idx = $env{'form.idx'};
1.108     raeburn  3222:       if ($idx) {
1.157     albertel 3223:           my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
                   3224:                          $env{'course.'.$env{'request.course.id'}.'.domain'},
                   3225:                          $env{'course.'.$env{'request.course.id'}.'.num'});
1.108     raeburn  3226:           $attachmenturls = $contrib{$idx.':attachmenturl'};
                   3227:       }
1.133     albertel 3228:       &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,
                   3229: 			  $attachmenturls);
1.135     albertel 3230:       return OK;
1.157     albertel 3231:   } elsif ($env{'form.export'}) {
1.116     raeburn  3232:       &Apache::loncommon::content_type($r,'text/html');
                   3233:       $r->send_http_header;
1.157     albertel 3234:       my ($symb,$feedurl) = &get_feedurl_and_clean_symb($env{'form.export'});
1.133     albertel 3235:       my $mode='board';
1.116     raeburn  3236:       my $status='OPEN';
1.157     albertel 3237:       my $previous=$env{'form.previous'};
1.116     raeburn  3238:       if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library)$/) {
                   3239:           $mode='problem';
                   3240:           $status=$Apache::inputtags::status[-1];
                   3241:       }
                   3242:       my $discussion = &list_discussion($mode,$status,$symb); 
                   3243:       my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion');
                   3244:       $r->print($bodytag.$discussion);                                     
                   3245:       return OK;
1.15      www      3246:   } else {
                   3247: # ------------------------------------------------------------- Normal feedback
1.157     albertel 3248:       my $feedurl=$env{'form.postdata'};
1.133     albertel 3249:       $feedurl=~s/^http\:\/\///;
                   3250:       $feedurl=~s/^$ENV{'SERVER_NAME'}//;
                   3251:       $feedurl=~s/^$ENV{'HTTP_HOST'}//;
                   3252:       $feedurl=~s/\?.+$//;
1.8       www      3253: 
1.133     albertel 3254:       my $symb;
1.157     albertel 3255:       if ($env{'form.replydisc'}) {
                   3256: 	  $symb=(split(/\:\:\:/,$env{'form.replydisc'}))[0];
1.133     albertel 3257: 	  my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
                   3258: 	  $feedurl=&Apache::lonnet::clutter($url);
1.157     albertel 3259:       } elsif ($env{'form.editdisc'}) {
                   3260: 	  $symb=(split(/\:\:\:/,$env{'form.editdisc'}))[0];
1.52      www      3261: 	  my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
1.133     albertel 3262: 	  $feedurl=&Apache::lonnet::clutter($url);
1.157     albertel 3263:       } elsif ($env{'form.origpage'}) {
1.133     albertel 3264: 	  $symb=""; 
                   3265:       } else {
                   3266: 	  $symb=&Apache::lonnet::symbread($feedurl);
                   3267:       }
                   3268:       unless ($symb) {
1.157     albertel 3269: 	  $symb=$env{'form.symb'};
1.133     albertel 3270: 	  if ($symb) {
                   3271: 	      my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb);
                   3272: 	      $feedurl=&Apache::lonnet::clutter($url);
                   3273: 	  }
                   3274:       }
                   3275:       &Apache::lonenc::check_decrypt(\$symb);
                   3276:       my $goahead=1;
                   3277:       if ($feedurl=~/\.(problem|exam|quiz|assess|survey|form)$/) {
                   3278: 	  unless ($symb) { $goahead=0; }
                   3279:       }
                   3280:       # backward compatibility (bulletin boards used to be 'wrapped')
1.159     raeburn  3281:       &dewrapper(\$feedurl);
1.133     albertel 3282:       if (!$goahead) {
                   3283:           # Ambiguous Problem Resource
                   3284: 	  $r->internal_redirect('/adm/ambiguous');
                   3285: 	  return OK;
1.31      www      3286:       }
1.8       www      3287: # Go ahead with feedback, no ambiguous reference
1.133     albertel 3288:       unless (
                   3289: 	  (
                   3290: 	   ($feedurl=~m:^/res:) && ($feedurl!~m:^/res/adm:)
                   3291: 	   ) 
                   3292: 	  || 
1.157     albertel 3293: 	  ($env{'request.course.id'} && ($feedurl!~m:^/adm:))
1.133     albertel 3294: 	  ||
1.157     albertel 3295: 	  ($env{'request.course.id'} && ($symb=~/^bulletin\_\_\_/))
1.133     albertel 3296: 	  ) {
1.135     albertel 3297: 	  &Apache::loncommon::content_type($r,'text/html');
                   3298: 	  $r->send_http_header;
1.133     albertel 3299: # Unable to give feedback
                   3300: 	  &no_redirect_back($r,$feedurl);
                   3301:       }
1.6       albertel 3302: # --------------------------------------------------- Print login screen header
1.157     albertel 3303:       unless ($env{'form.sendit'}) {
1.135     albertel 3304: 	  &Apache::loncommon::content_type($r,'text/html');
                   3305: 	  $r->send_http_header;
1.141     raeburn  3306: 	  my $options=&screen_header($feedurl,$symb);
1.133     albertel 3307: 	  if ($options) {
                   3308: 	      &mail_screen($r,$feedurl,$options);
                   3309: 	  } else {
                   3310: 	      &fail_redirect($r,$feedurl);
                   3311: 	  }
                   3312: 	  return OK;
1.6       albertel 3313:       }
                   3314:       
                   3315: # Get previous user input
1.9       albertel 3316:       my $prevattempts=&Apache::loncommon::get_previous_attempt(
1.157     albertel 3317:                                    $symb,$env{'user.name'},$env{'user.domain'},
                   3318: 				   $env{'request.course.id'});
1.6       albertel 3319: 
                   3320: # Get output from resource
                   3321:       my $usersaw=&resource_output($feedurl);
                   3322: 
1.50      albertel 3323: # Get resource answer (need to allow student to view grades for this to work)
                   3324:       &Apache::lonnet::appenv(('allowed.vgr'=>'F'));
1.40      albertel 3325:       my $useranswer=&Apache::loncommon::get_student_answers(
1.157     albertel 3326:                                    $symb,$env{'user.name'},$env{'user.domain'},
                   3327: 		                   $env{'request.course.id'});
1.50      albertel 3328:       &Apache::lonnet::delenv('allowed.vgr');
1.42      www      3329: # Get attachments, if any, and not too large
                   3330:       my $attachmenturl='';
1.157     albertel 3331:       if (($env{'form.origpage'}) || ($env{'form.editdisc'}) ||
                   3332: 	  ($env{'form.replydisc'})) {
1.133     albertel 3333: 	  my ($symb,$idx);
1.157     albertel 3334: 	  if ($env{'form.replydisc'}) {
                   3335: 	      ($symb,$idx)=split(/\:\:\:/,$env{'form.replydisc'});
                   3336: 	  } elsif ($env{'form.editdisc'}) {
                   3337: 	      ($symb,$idx)=split(/\:\:\:/,$env{'form.editdisc'});
                   3338: 	  } elsif ($env{'form.origpage'}) {
                   3339: 	      $symb = $env{'form.symb'};
1.133     albertel 3340: 	  }
1.132     albertel 3341: 	  &Apache::lonenc::check_decrypt(\$symb);
1.133     albertel 3342: 	  my @currnewattach = ();
                   3343: 	  my @deloldattach = ();
                   3344: 	  my @keepold = ();
                   3345: 	  &process_attachments(\@currnewattach,\@deloldattach,\@keepold);
                   3346: 	  $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|;
                   3347: 	  $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx);
1.157     albertel 3348:       } elsif ($env{'form.attachment.filename'}) {
                   3349: 	  unless (length($env{'form.attachment'})>131072) {
1.82      albertel 3350: 	      $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback');
1.42      www      3351: 	  }
                   3352:       }
1.6       albertel 3353: # Filter HTML out of message (could be nasty)
1.157     albertel 3354:       my $message=&clear_out_html($env{'form.comment'});
1.6       albertel 3355: 
                   3356: # Assemble email
1.8       www      3357:       my ($email,$citations)=&assemble_email($feedurl,$message,$prevattempts,
1.133     albertel 3358: 					     $usersaw,$useranswer);
1.40      albertel 3359:  
1.6       albertel 3360: # Who gets this?
                   3361:       my ($typestyle,%to) = &decide_receiver($feedurl);
                   3362: 
                   3363: # Actually send mail
1.43      www      3364:       my ($status,$numsent)=&send_msg($feedurl,$email,$citations,
1.133     albertel 3365: 				      $attachmenturl,%to);
1.13      www      3366: 
                   3367: # Discussion? Store that.
                   3368: 
1.32      albertel 3369:       my $numpost=0;
1.157     albertel 3370:       if ($env{'form.discuss'} || $env{'form.anondiscuss'}) {
                   3371: 	  my $subject = &clear_out_html($env{'form.subject'});
                   3372: 	  my $anonmode=(defined($env{'form.anondiscuss'}));
1.133     albertel 3373: 	  $typestyle.=&adddiscuss($symb,$message,$anonmode,$attachmenturl,
                   3374: 				  $subject);
1.32      albertel 3375: 	  $numpost++;
1.14      www      3376:       }
1.133     albertel 3377: 	  
1.6       albertel 3378: # Receipt screen and redirect back to where came from
1.157     albertel 3379:       &redirect_back($r,$feedurl,$typestyle,$numsent,$numpost,$status,$env{'form.previous'});
1.133     albertel 3380:   }
                   3381:   return OK;
                   3382: } 
1.6       albertel 3383: 
1.133     albertel 3384: sub wrap_symb {
                   3385:     my ($ressymb)=@_;
                   3386:     if ($ressymb =~ /bulletin___\d+___/) {
                   3387:         unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
                   3388:             $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|;
                   3389:         }
1.6       albertel 3390:     }
1.133     albertel 3391:     return $ressymb;
                   3392: }
                   3393: sub dewrapper {
                   3394:     my ($feedurl)=@_;
                   3395:     if ($$feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
                   3396:         $$feedurl=~s|^/adm/wrapper||;
                   3397:     }
                   3398: }
                   3399: 
                   3400: sub get_feedurl {
                   3401:     my ($symb)=@_;
                   3402:     my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
                   3403:     my $feedurl = &Apache::lonnet::clutter($url);
                   3404:     &dewrapper(\$feedurl);
                   3405:     return $feedurl;
1.15      www      3406: }
1.1       www      3407: 
1.133     albertel 3408: sub get_feedurl_and_clean_symb {
                   3409:     my ($symb)=@_;
                   3410:     &Apache::lonenc::check_decrypt(\$symb);
                   3411: # backward compatibility (bulletin boards used to be 'wrapped')
                   3412:     unless ($symb =~ m|bulletin___\d+___adm/wrapper|) {
                   3413: 	$symb=~s|(bulletin___\d+___)|$1adm/wrapper|;
                   3414:     }
                   3415:     my $feedurl = &get_feedurl($symb);
                   3416:     return ($symb,$feedurl);
                   3417: }
1.1       www      3418: 1;
                   3419: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.