--- loncom/interface/lonfeedback.pm 2006/11/29 03:23:02 1.220 +++ loncom/interface/lonfeedback.pm 2009/05/06 13:37:56 1.271 @@ -1,7 +1,7 @@ # The LearningOnline Network # Feedback # -# $Id: lonfeedback.pm,v 1.220 2006/11/29 03:23:02 raeburn Exp $ +# $Id: lonfeedback.pm,v 1.271 2009/05/06 13:37:56 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -44,7 +44,6 @@ use HTML::LCParser(); use Apache::lonspeller(); use Apache::longroup; use Cwd; -use lib '/home/httpd/lib/perl/'; use LONCAPA; sub discussion_open { @@ -75,6 +74,9 @@ sub discussion_visible { sub list_discussion { my ($mode,$status,$ressymb,$imsextras,$group)=@_; + unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); } + unless ($ressymb) { return ''; } + $ressymb=&wrap_symb($ressymb); my $outputtarget=$env{'form.grade_target'}; if (defined($env{'form.export'})) { if($env{'form.export'}) { @@ -86,14 +88,29 @@ sub list_discussion { $outputtarget = 'export'; } } - if (not &discussion_visible($status)) { return ''; } + if (not &discussion_visible($status)) { + if ($mode ne 'board') { + &Apache::lonenc::check_encrypt(\$ressymb); + return '
'.&send_message_link($ressymb); + } + } if ($group ne '' && $mode eq 'board') { if (&check_group_priv($group,'vgb') ne 'ok') { return ''; } } - my @bgcols = ("#cccccc","#eeeeee"); + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('boards'); + if ($blocked) { + &Apache::lonenc::check_encrypt(\$ressymb); + if ($mode ne 'board') { + $blocktext.='
'.&send_message_link($ressymb); + } + return $blocktext; + } + + my @bgcols = ("LC_disc_old_item","LC_disc_new_item"); my $discussiononly=0; if ($mode eq 'board') { $discussiononly=1; } unless ($env{'request.course.id'}) { return ''; } @@ -103,9 +120,6 @@ sub list_discussion { $crs.='_'.$env{'request.course.sec'}; } $crs=~s/\_/\//g; - unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); } - unless ($ressymb) { return ''; } - $ressymb=&wrap_symb($ressymb); my $encsymb=&Apache::lonenc::check_encrypt($ressymb); my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs) && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form|task)$/)); @@ -133,7 +147,7 @@ sub list_discussion { my $previous = 0; my $visit = 0; my $newpostsflag = 0; - my @posters = split/\&/,$dischash{$userpickkey}; + my @posters = split(/\&/,$dischash{$userpickkey}); # Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts. &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','grouppick','totposters']); @@ -162,19 +176,19 @@ sub list_discussion { my ($classgroups,$studentgroups); if ($env{'form.rolefilter'}) { %roleshash = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum); - foreach (keys %roleshash) { - my ($role,$uname,$udom,$sec) = split/:/,$_; + foreach my $rolekey (keys(%roleshash)) { + my ($role,$uname,$udom,$sec) = split(/:/,$rolekey); if ($role =~ /^cr/) { $role = 'cr'; } - my ($end,$start) = split/:/,$roleshash{$_}; + my ($end,$start) = split(/:/,$roleshash{$rolekey}); my $now = time; my $status = 'Active'; if (($now < $start) || ($end > 0 && $now > $end)) { $status = 'Expired'; } if ($uname && $udom) { - push @{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status; + push(@{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status); } } my ($classlist,$keylist) = @@ -184,7 +198,7 @@ sub list_discussion { while (my ($student,$data) = each %$classlist) { my ($section,$status) = ($data->[$sec_index], $data->[$status_index]); - push @{$roleinfo{$student}}, 'st:'.$section.':'.$status; + push(@{$roleinfo{$student}}, 'st:'.$section.':'.$status); } ($classgroups,$studentgroups) = &Apache::loncoursedata::get_group_memberships($classlist,$keylist, @@ -420,56 +434,12 @@ imscp_v1p1.xsd http://www.imsglobal.org/ } |; - $discussion.='
'; - $discussion .=''; - + $discussion.=''. + "\n".'
'. - ''; - my $escsymb=&escape($ressymb); - if ($visible>2) { - $discussion.=''; - if ($newpostsflag) { - if (!$markondisp) { - $discussion .=''; - } - } else { - $discussion .= ''; - } - $discussion .= '
'. - ''.&mt('Threaded View').'  '. - ''.&mt('Chronological View').'   - '.&mt('Sorting/Filtering options').'  '; - } else { - $discussion .= ''; - } - $discussion .=''.&mt('Export').'?  '. - &mt('Preferences on what is marked as NEW'). - '
'.&mt('Mark NEW posts no longer new').''; - } else { - $discussion .= '
  
'; + $discussion .= &action_links_bar($colspan,$ressymb,$visible, + $newpostsflag,$group, + $prevread,$markondisp); + my $escsymb=&escape($ressymb); my $numhidden = keys(%notshown); if ($numhidden > 0) { my $colspan = $maxdepth+1; @@ -493,39 +463,39 @@ imscp_v1p1.xsd http://www.imsglobal.org/ # Choose sort mechanism my @showposts = (); if ($sortposts eq 'descdate') { - @showposts = (sort { $b <=> $a } keys %alldiscussion); + @showposts = (sort { $b <=> $a } keys(%alldiscussion)); } elsif ($sortposts eq 'thread') { - @showposts = (sort { $a <=> $b } keys %alldiscussion); + @showposts = (sort { $a <=> $b } keys(%alldiscussion)); } elsif ($sortposts eq 'subject') { - foreach (sort keys %subjectsort) { - push @showposts, @{$subjectsort{$_}}; + foreach my $key (sort(keys(%subjectsort))) { + push(@showposts, @{$subjectsort{$key}}); } } elsif ($sortposts eq 'username') { - foreach my $domain (sort keys %usernamesort) { - foreach (sort keys %{$usernamesort{$domain}}) { - push @showposts, @{$usernamesort{$domain}{$_}}; + foreach my $domain (sort(keys(%usernamesort))) { + foreach my $key (sort(keys(%{$usernamesort{$domain}}))) { + push(@showposts, @{$usernamesort{$domain}{$key}}); } } } elsif ($sortposts eq 'lastfirst') { - foreach my $last (sort keys %namesort) { - foreach (sort keys %{$namesort{$last}}) { - push @showposts, @{$namesort{$last}{$_}}; + foreach my $last (sort(keys(%namesort))) { + foreach my $key (sort(keys(%{$namesort{$last}}))) { + push(@showposts, @{$namesort{$last}{$key}}); } } } else { - @showposts = (sort { $a <=> $b } keys %alldiscussion); + @showposts = (sort { $a <=> $b } keys(%alldiscussion)); } my $currdepth = 0; my $firstidx = $alldiscussion{$showposts[0]}; - foreach (@showposts) { + foreach my $post (@showposts) { unless (($sortposts eq 'thread') || (($sortposts eq '') && ($env{'environment.threadeddiscussion'})) || ($outputtarget eq 'export')) { - $alldiscussion{$_} = $_; + $alldiscussion{$post} = $post; } - unless ( ($notshown{$alldiscussion{$_}} eq '1') || ($shown{$alldiscussion{$_}} == 0) ) { + unless ( ($notshown{$alldiscussion{$post}} eq '1') || ($shown{$alldiscussion{$post}} == 0) ) { if ($outputtarget ne 'tex' && $outputtarget ne 'export') { $discussion.="\n"; } - my $thisdepth=$depth[$alldiscussion{$_}]; + my $thisdepth=$depth[$alldiscussion{$post}]; if ($outputtarget ne 'tex' && $outputtarget ne 'export') { for (1..$thisdepth) { $discussion.=''; @@ -534,52 +504,52 @@ imscp_v1p1.xsd http://www.imsglobal.org/ my $colspan=$maxdepth-$thisdepth+1; if ($outputtarget eq 'tex') { #cleanup block - $discussionitems[$alldiscussion{$_}]=~s/]*)>/
   
/; - $discussionitems[$alldiscussion{$_}]=~s/]*)>]*)>/
/; + $discussionitems[$alldiscussion{$post}]=~s/]*)>//; + $discussionitems[$alldiscussion{$post}]=~s/]*)>]*)>/'; } } @@ -588,8 +558,8 @@ imscp_v1p1.xsd http://www.imsglobal.org/ my $colspan=$maxdepth+1; $discussion .= < -
/; my $threadinsert=''; if ($thisdepth > 0) { $threadinsert='
Reply: '.$thisdepth.''; } - $discussionitems[$alldiscussion{$_}]=~s/<\/td>]*)>/$threadinsert<\/td>
/; - $discussionitems[$alldiscussion{$_}]=~s/]+)>(Edit|Hide|Delete|Reply|Submissions)<\/a>//g; - $discussionitems[$alldiscussion{$_}]=~s/(|<\/b>|<\/a>|]+)>)//g; + $discussionitems[$alldiscussion{$post}]=~s/<\/td>]*)>/$threadinsert<\/td>/; + $discussionitems[$alldiscussion{$post}]=~s/]+)>(Edit|Hide|Delete|Reply|Submissions)<\/a>//g; + $discussionitems[$alldiscussion{$post}]=~s/(|<\/b>|<\/a>|]+)>)//g; - $discussionitems[$alldiscussion{$_}]='\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.$discussionitems[$alldiscussion{$_}]; - $discussion.=$discussionitems[$alldiscussion{$_}]; + $discussionitems[$alldiscussion{$post}]='\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.$discussionitems[$alldiscussion{$post}]; + $discussion.=$discussionitems[$alldiscussion{$post}]; } elsif ($outputtarget eq 'export') { - my $postfilename = $alldiscussion{$_}.'-'.$imsitems{$alldiscussion{$_}}{'timestamp'}.'.html'; + my $postfilename = $alldiscussion{$post}.'-'.$imsitems{$alldiscussion{$post}}{'timestamp'}.'.html'; if ($manifestok) { - if (($depth[$alldiscussion{$_}] <= $currdepth) && ($alldiscussion{$_} != $firstidx)) { + if (($depth[$alldiscussion{$post}] <= $currdepth) && ($alldiscussion{$post} != $firstidx)) { print $manifestfile ' '."\n"; } - $currdepth = $depth[$alldiscussion{$_}]; + $currdepth = $depth[$alldiscussion{$post}]; print $manifestfile "\n". - ''. - ''.$imsitems{$alldiscussion{$_}}{'title'}.''; + ''. + ''.$imsitems{$alldiscussion{$post}}{'title'}.''; $imsresources .= "\n". - ''."\n". + ''."\n". ''."\n". - $imsfiles{$alldiscussion{$_}}{$imsitems{$alldiscussion{$_}}{'currversion'}}."\n". + $imsfiles{$alldiscussion{$post}}{$imsitems{$alldiscussion{$post}}{'currversion'}}."\n". ''; } my $postingfile; my $postingfilename = $tempexport.'/'.$postfilename; if ($postingfile = Apache::File->new('>'.$postingfilename)) { print $postingfile 'Discussion Post'. - $imsitems{$alldiscussion{$_}}{'title'}.' '. - $imsitems{$alldiscussion{$_}}{'sender'}. - $imsitems{$alldiscussion{$_}}{'timestamp'}.'

'. - $imsitems{$alldiscussion{$_}}{'message'}.'
'. - $imsitems{$alldiscussion{$_}}{'attach'}.''."\n"; + $imsitems{$alldiscussion{$post}}{'title'}.' '. + $imsitems{$alldiscussion{$post}}{'sender'}. + $imsitems{$alldiscussion{$post}}{'timestamp'}.'

'. + $imsitems{$alldiscussion{$post}}{'message'}.'
'. + $imsitems{$alldiscussion{$post}}{'attach'}.''."\n"; close($postingfile); } else { - $discussion .= $lt{'aerr'}.' '.$alldiscussion{$_}.'
'; + $discussion .= $lt{'aerr'}.' '.$alldiscussion{$post}.'
'; } - $copyresult.=&replicate_attachments($imsitems{$alldiscussion{$_}}{'allattachments'},$tempexport); + $copyresult.=&replicate_attachments($imsitems{$alldiscussion{$post}}{'allattachments'},$tempexport); } else { - $discussion.='
'. $discussionitems[$alldiscussion{$_}]. + $discussion.=''. $discussionitems[$alldiscussion{$post}]. '
- + '; + return $discussion; +} + sub postingform_display { my ($mode,$ressymb,$now,$subject,$comment,$outputtarget,$attachnum, $currnewattach,$currdelold,$group) = @_; @@ -815,11 +860,16 @@ ENDDISCUSS if ($group ne '') { $postingform .=''; } + my $blockblog = &Apache::loncommon::blocking_status('blogs'); + if (!$blockblog) { + $postingform .= &add_blog_checkbox(); + } $postingform .= "\n"; if ($outputtarget ne 'tex') { $postingform .= &generate_attachments_button('',$attachnum,$ressymb, $now,$currnewattach, - $currdelold,'',$mode); + $currdelold,'',$mode, + $blockblog); if ((ref($currnewattach) eq 'ARRAY') && (@{$currnewattach} > 0)) { $newattachmsg = '
'.$lt{'newa'}.'
'; if (@{$currnewattach} > 1) { @@ -851,6 +901,9 @@ sub build_posting_display { $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}); + my $see_anonymous = + &Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')); + if ((@{$grouppick} == 0) || (grep(/^all$/,@{$grouppick}))) { $skip_group_check = 1; } @@ -901,7 +954,7 @@ sub build_posting_display { $$visible++; if ($contrib{$idx.':history'}) { if ($contrib{$idx.':history'} =~ /:/) { - my @oldversions = split/:/,$contrib{$idx.':history'}; + my @oldversions = split(/:/,$contrib{$idx.':history'}); $numoldver = @oldversions; } else { $numoldver = 1; @@ -940,35 +993,37 @@ sub build_posting_display { if ($subject eq '') { if (defined($$subjectsort{'__No subject'})) { - push @{$$subjectsort{'__No subject'}}, $idx; + push(@{$$subjectsort{'__No subject'}}, $idx); } else { @{$$subjectsort{'__No subject'}} = ("$idx"); } } else { if (defined($$subjectsort{$subject})) { - push @{$$subjectsort{$subject}}, $idx; + push(@{$$subjectsort{$subject}}, $idx); } else { @{$$subjectsort{$subject}} = ("$idx"); } } - if ((!$contrib{$idx.':anonymous'}) || (&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')))) { + if (!$contrib{$idx.':anonymous'} || $see_anonymous) { $sender=&Apache::loncommon::aboutmewrapper( $plainname, $contrib{$idx.':sendername'}, $contrib{$idx.':senderdomain'}).' ('. - $contrib{$idx.':sendername'}.' at '. + $contrib{$idx.':sendername'}.':'. $contrib{$idx.':senderdomain'}.')'; if ($contrib{$idx.':anonymous'}) { $sender.=' ['.$$anonhash{$key}.'] '. $screenname; } - + if ($see_anonymous) { + $sender.=&Apache::loncommon::student_image_tag($contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'}); + } # Set up for sorting by domain, then username unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) { %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = (); } if (defined($$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}})) { - push @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx; + push(@{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx); } else { @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}} = ("$idx"); } @@ -988,7 +1043,7 @@ sub build_posting_display { %{$$namesort{$lastname}} = (); } if (defined($$namesort{$lastname}{$firstname})) { - push @{$$namesort{$lastname}{$firstname}}, $idx; + push(@{$$namesort{$lastname}{$firstname}}, $idx); } else { @{$$namesort{$lastname}{$firstname}} = ("$idx"); } @@ -1044,7 +1099,7 @@ sub build_posting_display { %{$$usernamesort{'__anon'}} = (); } if (defined($$usernamesort{'__anon'}{'__anon'})) { - push @{$$usernamesort{'__anon'}{'__anon'}}, $idx; + push(@{$$usernamesort{'__anon'}{'__anon'}}, $idx); } else { @{$$usernamesort{'__anon'}{'__anon'}} = ("$idx"); } @@ -1053,7 +1108,7 @@ sub build_posting_display { %{$$namesort{'__anon'}} = (); } if (defined($$namesort{'__anon'}{'__anon'})) { - push @{$$namesort{'__anon'}{'__anon'}}, $idx; + push(@{$$namesort{'__anon'}{'__anon'}}, $idx); } else { @{$$namesort{'__anon'}{'__anon'}} = ("$idx"); } @@ -1186,14 +1241,14 @@ sub build_posting_display { $$newitem{$idx} = 1; $$discussionitems[$idx] .= '

- '; + '; } else { $$newitem{$idx} = 0; $$discussionitems[$idx] .= '

NEW
'.&mt('NEW').'
'; } - $$discussionitems[$idx] .= ''; @@ -1213,7 +1268,7 @@ sub build_posting_display { } $$discussionitems[$idx].='
'.&mt('Earlier version(s) were posted on: '); if ($contrib{$idx.':history'} =~ m/:/) { - @postversions = split/:/,$contrib{$idx.':history'}; + @postversions = split(/:/,$contrib{$idx.':history'}); } else { @postversions = ("$contrib{$idx.':history'}"); } @@ -1236,9 +1291,9 @@ sub filter_regexp { my $skiptest = 1; if (@{$rolefilter} > 0) { my @okrolefilter = (); - foreach (@{$rolefilter}) { - unless ($_ eq '') { - push @okrolefilter, $_; + foreach my $role (@{$rolefilter}) { + unless ($role eq '') { + push(@okrolefilter, $role); } } if (@okrolefilter > 0) { @@ -1256,9 +1311,9 @@ sub filter_regexp { } if (@{$sectionpick} > 0) { my @oksectionpick = (); - foreach (@{$sectionpick}) { - unless ($_ eq '') { - push @oksectionpick, $_; + foreach my $sec (@{$sectionpick}) { + unless ($sec eq '') { + push(@oksectionpick, $sec); } } if ((@oksectionpick > 0) && (!grep/^all$/,@oksectionpick)) { @@ -1320,7 +1375,7 @@ sub get_post_contents { } &get_post_versions($messages,$$contrib{$idx.':message'},1); &get_post_versions($subjects,$$contrib{$idx.':subject'},1); - push @postversions,$$contrib{$idx.':timestamp'}; + push(@postversions,$$contrib{$idx.':timestamp'}); $end = @postversions; } else { &get_post_versions($messages,$$contrib{$idx.':message'},1,$numver); @@ -1348,8 +1403,8 @@ sub get_post_contents { $$imsfiles{$idx}{$i} = ''; if ($attachmsg) { $$attachtxt{$i} = '
'.&mt('Attachments').':
'; - foreach (sort keys %currattach) { - if ($$allattachments{$_}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) { + foreach my $key (sort(keys(%currattach))) { + if ($$allattachments{$key}{'filename'} =~ m-^/uploaded/([^/]+/[^/]+)(/feedback)?(/?\d*)/([^/]+)$-) { my $fname = $1.$3.'/'.$4; $$imsfiles{$idx}{$i} .= ''."\n"; $$attachtxt{$i}.= ''.$4.'
'; @@ -1382,11 +1437,11 @@ END sub replicate_attachments { my ($attachrefs,$tempexport) = @_; my $response; - foreach my $id (keys %{$attachrefs}) { + foreach my $id (keys(%{$attachrefs})) { if ($$attachrefs{$id}{'filename'} =~ m-^/uploaded/([^/]+)/([^/]+)(/feedback)?(/?\d*)/([^/]+)$-) { my $path = $tempexport; my $tail = $1.'/'.$2.$4; - my @extras = split/\//,$tail; + my @extras = split(/\//,$tail); my $destination = $tempexport.'/'.$1.'/'.$2.$4.'/'.$5; if (!-e $destination) { my $i= 0; @@ -1418,7 +1473,7 @@ sub replicate_attachments { } sub mail_screen { - my ($r,$feedurl,$options) = @_; + my ($r,$feedurl,$options,$caller_symb,$attachmaxtext) = @_; if (exists($env{'form.origpage'})) { &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss','blog','group','ref']); } @@ -1428,10 +1483,9 @@ sub mail_screen { 'myqu' => 'My question/comment/feedback:', 'title' => 'Title', 'reta' => 'Retained attachments', - 'atta' => 'Attachment (128 KB max size)', - ); - my $title=&Apache::lonnet::gettitle($feedurl); - if (!$title) { $title = $feedurl; } + 'atta' => 'Attachment', + ); + my $restitle = &get_resource_title($caller_symb,$feedurl); my $quote=''; my $subject = ''; my $comment = ''; @@ -1497,7 +1551,7 @@ END unless (($contrib{'hidden'}=~/\.$idx\./) || ($contrib{'deleted'}=~/\.$idx\./)) { if ($contrib{$idx.':history'}) { if ($contrib{$idx.':history'} =~ /:/) { - my @oldversions = split/:/,$contrib{$idx.':history'}; + my @oldversions = split(/:/,$contrib{$idx.':history'}); $numoldver = @oldversions; } else { $numoldver = 1; @@ -1506,7 +1560,7 @@ END if ($env{'form.replydisc'}) { if ($contrib{$idx.':history'}) { if ($contrib{$idx.':history'} =~ /:/) { - my @oldversions = split/:/,$contrib{$idx.':history'}; + my @oldversions = split(/:/,$contrib{$idx.':history'}); $numoldver = @oldversions; } else { $numoldver = 1; @@ -1520,7 +1574,7 @@ END if ($idx > 0) { my %subversions = (); &get_post_versions(\%subversions,$contrib{$idx.':subject'},1,$numoldver); - $subject = &mt('Re: ')..$subversions{$numoldver}; + $subject = &mt('Re: ').$subversions{$numoldver}; } $subject = &HTML::Entities::encode($subject,'<>&"'); } else { @@ -1565,7 +1619,7 @@ END $comment = &unescape($env{'form.comment'}); &process_attachments(\@currnewattach,\@currdelold,\@keepold); } - my $latexHelp=&Apache::loncommon::helpLatexCheatsheet(); + my $latexHelp=&Apache::loncommon::helpLatexCheatsheet(undef,undef,1); my $send=&mt('Send'); my $alert = &mt('Please select a feedback type.'); my $js= <print(<$title +

$restitle

$prevtag @@ -1631,8 +1685,8 @@ END END } elsif ($env{'form.editdisc'}) { $r->print(< - + + END } $r->print(<$lt{'myqu'}

$latexHelp +

+

$lt{'title'}:

   '. + $$discussionitems[$idx] .= '  '. ''.$subject.'  '. $sender.' '.$vgrlink.' ('. &Apache::lonlocal::locallocaltime($posttime).')