--- loncom/interface/londocs.pm 2016/11/26 15:39:52 1.615 +++ loncom/interface/londocs.pm 2019/04/11 14:22:35 1.660 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.615 2016/11/26 15:39:52 raeburn Exp $ +# $Id: londocs.pm,v 1.660 2019/04/11 14:22:35 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -45,6 +45,8 @@ use Apache::lontemplate(); use Apache::lonsimplepage(); use Apache::lonhomework(); use Apache::lonpublisher(); +use Apache::lonparmset(); +use Apache::loncourserespicker(); use HTML::Entities; use HTML::TokeParser; use GDBM_File; @@ -52,6 +54,7 @@ use File::MMagic; use File::Copy; use Apache::lonlocal; use Cwd; +use UUID::Tiny ':std'; use LONCAPA qw(:DEFAULT :match); my $iconpath; @@ -142,7 +145,43 @@ sub clean { return $title; } - +sub default_folderpath { + my ($coursenum,$coursedom,$navmapref) = @_; + return unless ($coursenum && $coursedom && ref($navmapref)); +# Check if entire course is hidden and/or encrypted + my ($hiddenmap,$encryptmap,$folderpath,$hiddentop); + my $toplevel = "uploaded/$coursedom/$coursenum/default.sequence"; + unless (ref($$navmapref)) { + $$navmapref = Apache::lonnavmaps::navmap->new(); + } + if (ref($$navmapref)) { + if (lc($$navmapref->get_mapparam(undef,$toplevel,"0.hiddenresource")) eq 'yes') { + my $filterFunc = sub { my $res = shift; return (!$res->randomout() && !$res->is_map()) }; + my @resources = $$navmapref->retrieveResources($toplevel,$filterFunc,1,1); + unless (@resources) { + $hiddenmap = 1; + unless ($env{'request.role.adv'}) { + $hiddentop = 1; + if ($env{'form.folder'}) { + undef($env{'form.folder'}); + } + } + } + } + if (lc($$navmapref->get_mapparam(undef,$toplevel,"0.encrypturl")) eq 'yes') { + $encryptmap = 1; + } + } + unless ($hiddentop) { + $folderpath='default&'.&escape(&mt('Main Content')). + '::'.$hiddenmap.':'.$encryptmap.'::'; + } + if (wantarray) { + return ($folderpath,$hiddentop); + } else { + return $folderpath; + } +} sub dumpcourse { my ($r) = @_; @@ -567,9 +606,9 @@ sub recurse_html { } else { $relfile = $dependency; $depurl = $currurlpath; - $depurl =~ s{[^/]+$}{}; + $depurl =~ s{[^/]+$}{}; $depurl .= $dependency; - ($newcontainer) = ($depurl =~ m{^\Q$prefix\E(.+)$}); + ($newcontainer) = ($depurl =~ m{^\Q$prefix\E(.+)$}); } next if ($relfile eq ''); my $newname = $replacehash->{$container}; @@ -618,11 +657,12 @@ sub group_import { } } if ($url) { - if ($url =~ m{^(/adm/$coursedom/$coursenum/(\d+)/exttool)s?\:?(.*)$}) { + if ($url =~ m{^(/adm/$coursedom/$coursenum/(\d+)/ext\.tool)\:?(.*)$}) { $url = $1; my $marker = $2; my $info = $3; my ($toolid,%toolhash,%toolsettings); + my @extras = ('linktext','explanation','crslabel','crstitle','crsappend'); my @toolinfo = split(/:/,$info); if ($residx) { %toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum); @@ -632,28 +672,42 @@ sub group_import { } $toolid =~ s/\D//g; ($toolhash{'target'},$toolhash{'width'},$toolhash{'height'}, - $toolhash{'crslabel'},$toolhash{'crstitle'}) = @toolinfo; - $toolhash{'crslabel'} = &unescape($toolhash{'crslabel'}); - $toolhash{'crstitle'} = &unescape($toolhash{'crstitle'}); + $toolhash{'linktext'},$toolhash{'explanation'},$toolhash{'crslabel'}, + $toolhash{'crstitle'},$toolhash{'crsappend'},$toolhash{'gradable'}) = @toolinfo; + foreach my $item (@extras) { + $toolhash{$item} = &unescape($toolhash{$item}); + } + if ($folder =~ /^supplemental/) { + delete($toolhash{'gradable'}); + } else { + $toolhash{'gradable'} =~ s/\D+//g; + } if (ref($ltitoolsref) eq 'HASH') { - my @deleted; if (ref($ltitoolsref->{$toolid}) eq 'HASH') { - if ($ltitoolsref->{$toolid}->{'url'} =~ m{^https://}) { - $url =~ s/exttool$/exttools/; - } + my @deleted; $toolhash{'id'} = $toolid; - if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'window')) { + if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') || + ($toolhash{'target'} eq 'window')) { if ($toolhash{'target'} eq 'window') { foreach my $item ('width','height') { $toolhash{$item} =~ s/^\s+//; $toolhash{$item} =~ s/\s+$//; + if ($toolhash{$item} =~ /\D/) { + delete($toolhash{$item}); + if ($residx) { + if ($toolsettings{$item}) { + push(@deleted,$item); + } + } + } } } } elsif ($residx) { $toolhash{'target'} = $toolsettings{'target'}; if ($toolhash{'target'} eq 'window') { - $toolhash{'width'} = $toolsettings{'width'}; - $toolhash{'height'} = $toolsettings{'height'}; + foreach my $item ('width','height') { + $toolhash{$item} = $toolsettings{$item}; + } } } elsif (ref($ltitoolsref->{$toolid}->{'display'}) eq 'HASH') { $toolhash{'target'} = $ltitoolsref->{$toolid}->{'display'}->{'target'}; @@ -663,40 +717,93 @@ sub group_import { } } if ($toolhash{'target'} eq 'iframe') { - delete($toolhash{'width'}); - delete($toolhash{'height'}); - if ($residx) { - if ($toolsettings{'width'}) { - push(@deleted,'width'); + foreach my $item ('width','height','linktext','explanation') { + delete($toolhash{$item}); + if ($residx) { + if ($toolsettings{$item}) { + push(@deleted,$item); + } } - if ($toolsettings{'height'}) { - push(@deleted,'height'); + } + } elsif ($toolhash{'target'} eq 'tab') { + foreach my $item ('width','height') { + delete($toolhash{$item}); + if ($residx) { + if ($toolsettings{$item}) { + push(@deleted,$item); + } } } } if (ref($ltitoolsref->{$toolid}->{'crsconf'}) eq 'HASH') { - foreach my $item ('label','title') { + foreach my $item ('label','title','linktext','explanation') { + my $crsitem; + if (($item eq 'label') || ($item eq 'title')) { + $crsitem = 'crs'.$item; + } else { + $crsitem = $item; + } if ($ltitoolsref->{$toolid}->{'crsconf'}->{$item}) { - $toolhash{'crs'.$item} =~ s/^\s+//; - $toolhash{'crs'.$item} =~ s/\s+$//; - if ($toolhash{'crs'.$item} eq '') { - delete($toolhash{'crs'.$item}); + $toolhash{$crsitem} =~ s/^\s+//; + $toolhash{$crsitem} =~ s/\s+$//; + if ($toolhash{$crsitem} eq '') { + delete($toolhash{$crsitem}); } } else { - delete($toolhash{'crs'.$item}); + delete($toolhash{$crsitem}); } - if (($residx) && (exists($toolsettings{'crs'.$item}))) { - unless (exists($toolhash{'crs'.$item})) { - push(@deleted,'crs'.$item); + if (($residx) && (exists($toolsettings{$crsitem}))) { + unless (exists($toolhash{$crsitem})) { + push(@deleted,$crsitem); } } } } + if ($toolhash{'passback'}) { + my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4); + $toolhash{'gradesecret'} = $gradesecret; + $toolhash{'gradesecretdate'} = time; + } + if ($toolhash{'roster'}) { + my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4); + $toolhash{'rostersecret'} = $rostersecret; + $toolhash{'rostersecretdate'} = time; + } + my $changegradable; + if (($residx) && ($folder =~ /^default/)) { + if ($toolsettings{'gradable'}) { + unless (($toolhash{'gradable'}) || (defined($LONCAPA::map::zombies[$residx]))) { + push(@deleted,'gradable'); + $changegradable = 1; + } + } elsif ($toolhash{'gradable'}) { + $changegradable = 1; + } + if (($caller eq 'londocs') && (defined($LONCAPA::map::zombies[$residx]))) { + $changegradable = 1; + if ($toolsettings{'gradable'}) { + $toolhash{'gradable'} = 1; + } + } + } my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum); if ($putres eq 'ok') { if (@deleted) { &Apache::lonnet::del('exttool_'.$marker,\@deleted,$coursedom,$coursenum); - } + } + if (($changegradable) && ($folder =~ /^default/)) { + my $val; + if ($toolhash{'gradable'}) { + $val = 'yes'; + } else { + $val = 'no'; + } + &LONCAPA::map::storeparameter($residx,'parameter_0_gradable',$val, + 'string_yesno'); + &remember_parms($residx,'gradable','set',$val); + } + } else { + return (&mt('Failed to save update to external tool.'),1); } } } @@ -712,8 +819,8 @@ sub group_import { $donechk = 1; } if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$}) { - &contained_map_check($url,$folder,\%removefrommap,\%removeparam, - \%addedmaps,\%hierarchy,\%titles,$allmaps); + &contained_map_check($url,$folder,$coursenum,$coursedom,\%removefrommap, + \%removeparam,\%addedmaps,\%hierarchy,\%titles,$allmaps); $importuploaded = 1; } elsif ($url =~ m{^/res/.+\.(page|sequence)$}) { next if ($allmaps->{$url}); @@ -753,7 +860,7 @@ $initialtext END $env{'form.output'}=$newhtml; - my $result = + my $result = &Apache::lonnet::finishuserfileupload($coursenum,$coursedom, 'output', "$filepath/$residx/$fname.html"); @@ -879,11 +986,12 @@ sub log_docs { sub docs_change_log { my ($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath,$canedit)=@_; my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/); + my $navmap; my $js = ''."\n". -'
'. +''. '

'. &mt($message,' "/adm/coursedocs?tools=1&verify=1&checkstale=$env{'form.checkstale'}", + text=>'Results', + faq=>273, + bug=>'Instructor Interface'}); + &verifycontent($r,$env{'form.checkstale'}); + } else { + &contentverifyform($r); + } } elsif ($allowed && $env{'form.listsymbs'}) { &init_breadcrumbs('listsymbs','List Content IDs'); &list_symbs($r); + } elsif ($allowed && $env{'form.shorturls'}) { + &init_breadcrumbs('shorturls','Set/Display Shortened URLs','Docs_Short_URLs'); + &short_urls($r,$canedit); } elsif ($allowed && $env{'form.docslog'}) { &init_breadcrumbs('docslog','Show Log'); my $folder = $env{'form.folder'}; @@ -5066,6 +5465,8 @@ sub handler { $r->internal_redirect($redirect); return OK; } + } else { + $r->internal_redirect($redirect); } } } @@ -5079,6 +5480,26 @@ sub handler { 'forcesupplement','forcestandard', 'tools','symb','command','supppath']); + foreach my $item ('forcesupplement','forcestandard','tools') { + next if ($env{'form.'.$item} eq ''); + unless ($env{'form.'.$item} eq '1') { + delete($env{'form.'.$item}); + } + } + + if ($env{'form.command'}) { + unless ($env{'form.command'} =~ /^(direct|directnav|editdocs|editsupp|contents|home)$/) { + delete($env{'form.command'}); + } + } + + if ($env{'form.symb'}) { + my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($env{'form.symb'}); + unless (($id =~ /^\d+$/) && (&Apache::lonnet::is_on_map($resurl))) { + delete($env{'form.symb'}); + } + } + # standard=1: this is a "new-style" course with an uploaded map as top level # standard=2: this is a "old-style" course, and there is nothing we can do @@ -5101,6 +5522,38 @@ sub handler { my $toolsflag=0; if ($env{'form.tools'}) { $toolsflag=1; } + if ($env{'form.folderpath'} ne '') { + my @items = split(/\&/,$env{'form.folderpath'}); + my $badpath; + for (my $i=0; $i<@items; $i++) { + my $odd = $i%2; + if (($odd) && (!$supplementalflag) && ($items[$i] !~ /^[^:]*:(|\d+):(|1):(|1):(|1):(|1)$/)) { + $badpath = 1; + } elsif ((!$odd) && ($items[$i] !~ /^(default|supplemental)(|_\d+)$/)) { + $badpath = 1; + } + last if ($badpath); + } + if ($badpath) { + delete($env{'form.folderpath'}); + } + } + + if ($env{'form.supppath'} ne '') { + my @items = split(/\&/,$env{'form.supppath'}); + my $badpath; + for (my $i=0; $i<@items; $i++) { + my $odd = $i%2; + if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) { + $badpath = 1; + } + last if ($badpath); + } + if ($badpath) { + delete($env{'form.supppath'}); + } + } + my $script=''; my $showdoc=0; my $addentries = {}; @@ -5108,15 +5561,15 @@ sub handler { my $containertag; my $pathitem; my %ltitools; + my $hiddentop; my $navmap; - my $hiddentop; + my $filterFunc = sub { my $res = shift; return (!$res->randomout() && !$res->is_map()) }; # Do we directly jump somewhere? - if (($env{'form.command'} eq 'direct') || ($env{'form.command'} eq 'directnav')) { if ($env{'form.symb'} ne '') { $env{'form.folderpath'}= - &Apache::loncommon::symb_to_docspath($env{'form.symb'}); + &Apache::loncommon::symb_to_docspath($env{'form.symb'},\$navmap); &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => $env{'form.command'}.'_'.$env{'form.symb'}}); } elsif ($env{'form.supppath'} ne '') { @@ -5125,12 +5578,10 @@ sub handler { $env{'form.command'}.'_'.$env{'form.supppath'}}); } } elsif ($env{'form.command'} eq 'editdocs') { - $env{'form.folderpath'} = 'default&'. - &escape(&mt('Main Content').':::::'); + $env{'form.folderpath'} = &default_folderpath($coursenum,$coursedom,\$navmap); &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => $env{'form.command'}}); } elsif ($env{'form.command'} eq 'editsupp') { - $env{'form.folderpath'} = 'supplemental&'. - &escape('Supplemental Content'); + $env{'form.folderpath'} = &supplemental_base(); &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => '/adm/supplemental'}); } elsif ($env{'form.command'} eq 'contents') { &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => '/adm/navmaps'}); @@ -5178,22 +5629,27 @@ sub handler { ($env{'form.folderpath'} ne '') && (!$supplementalflag)) { my $folderurl; my @pathitems = split(/\&/,$env{'form.folderpath'}); - my $container = $pathitems[-2]; - if ($container ne '') { - $folderurl = "uploaded/$coursedom/$coursenum/$container"; + my $folder = $pathitems[-2]; + if ($folder eq '') { + undef($env{'form.folderpath'}); + } else { + $folderurl = "uploaded/$coursedom/$coursenum/$folder"; if ((split(/\:/,$pathitems[-1]))[4]) { $folderurl .= '.page'; } else { $folderurl .= '.sequence'; } - $navmap = Apache::lonnavmaps::navmap->new(); + unless (ref($navmap)) { + $navmap = Apache::lonnavmaps::navmap->new(); + } if (ref($navmap)) { if (lc($navmap->get_mapparam(undef,$folderurl,"0.hiddenresource")) eq 'yes') { - undef($env{'form.folderpath'}); + my @resources = $navmap->retrieveResources($folderurl,$filterFunc,1,1); + unless (@resources) { + undef($env{'form.folderpath'}); + } } } - } else { - undef($env{'form.folderpath'}); } } @@ -5202,29 +5658,11 @@ sub handler { unless ($env{'form.folderpath'}) { if ($supplementalflag) { $env{'form.folderpath'}=&supplemental_base(); - } else { - $env{'form.folderpath'}='default&'.&escape(&mt('Main Content'). - ':::::'); - if (($allowed) && (!$env{'request.role.adv'})) { -# If allowed and user's role is not advanced check entire course is not hidden - unless (ref($navmap)) { - $navmap = Apache::lonnavmaps::navmap->new(); - } - if (ref($navmap)) { - if (lc($navmap->get_mapparam(undef,"uploaded/$coursedom/$coursenum/default.sequence", - "0.hiddenresource")) eq 'yes') { - undef($env{'form.folderpath'}); - $hiddentop = 1; - if ($env{'form.folder'}) { - undef($env{'form.folder'}); - } - } - } - } + } elsif ($allowed) { + ($env{'form.folderpath'},$hiddentop) = &default_folderpath($coursenum,$coursedom,\$navmap); } } - # Store this unless ($toolsflag) { if (($allowed) && ($env{'form.folderpath'} ne '')) { @@ -5245,8 +5683,12 @@ sub handler { } else { if ($env{'form.folder'} eq '' || $env{'form.folder'} eq 'supplemental') { - $folderpath='default&'. - &escape(&mt('Main Content').':::::'); + if ($env{'form.folder'} eq 'supplemental') { + $folderpath=&supplemental_base(); + } elsif (!$hiddentop) { + $folderpath='default&'. + &escape(&mt('Main Content').':::::'); + } } } $containertag = ''; @@ -5286,7 +5728,7 @@ sub handler { my $tid = 1; my @tabids; if ($supplementalflag) { - @tabids = ('002','ee2','ff2'); + @tabids = ('002','dd2','ee2','ff2'); $tid = 2; } else { @tabids = ('aa1','bb1','cc1','ff1'); @@ -5296,10 +5738,11 @@ sub handler { } } my $tabidstr = join("','",@tabids); - %ltitools = &Apache::lonnet::get_domain_ltitools($coursedom); + %ltitools = &Apache::lonnet::get_domain_lti($coursedom,'consumer'); my $posslti = keys(%ltitools); + my $hostname = $r->hostname(); $script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti, - $londocroot,$canedit). + $londocroot,$canedit,$hostname,\$navmap). &history_tab_js(). &inject_data_js(). &Apache::lonhtmlcommon::resize_scrollbox_js('docs',$tabidstr,$tid). @@ -5331,7 +5774,7 @@ sub handler { {'force_register' => $showdoc,})); } elsif ($toolsflag) { my ($breadtext,$breadtitle); - $breadtext = "$crstype Contents"; + $breadtext = "$crstype Editor"; if ($canedit) { $breadtitle = 'Editing '.$crstype.' Contents'; } else { @@ -5351,7 +5794,7 @@ sub handler { {'bread_crumbs' => $brcrum,})); } else { my ($breadtext,$breadtitle,$helpitem); - $breadtext = "$crstype Contents"; + $breadtext = "$crstype Editor"; if ($canedit) { $breadtitle = 'Editing '.$crstype.' Contents'; $helpitem = 'Docs_Adding_Course_Doc'; @@ -5383,6 +5826,7 @@ sub handler { undef($hadchanges); $uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom, \%allfiles,\%codebase,$context,$crstype); + undef($navmap); if ($hadchanges) { &mark_hash_old(); } @@ -5398,7 +5842,7 @@ sub handler { my ($destination,$dir_root) = &embedded_destination(); my $url_root = '/uploaded/'.$docudom.'/'.$docuname; my $actionurl = '/adm/coursedocs'; - my ($result,$flag) = + my ($result,$flag) = &Apache::loncommon::upload_embedded('coursedoc',$destination, $docuname,$docudom,$dir_root,$url_root,undef,undef,undef,$state, $actionurl); @@ -5409,11 +5853,11 @@ sub handler { my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'}; my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'}; my ($destination,$dir_root) = &embedded_destination(); - my $result = + my $result = &Apache::loncommon::modify_html_refs('coursedoc',$destination, $docuname,$docudom,undef, $dir_root); - $r->print($result.&return_to_editor()); + $r->print($result.&return_to_editor()); } elsif ($env{'form.phase'} eq 'decompress_uploaded') { $uploadphase = 'decompress_phase_one'; $r->print(&decompression_phase_one(). @@ -5439,7 +5883,7 @@ sub handler { 'impo' => 'Import', 'lnks' => 'Import from Stored Links', 'impm' => 'Import from Assembled Map', - 'imcr' => 'Import from Course Resources', + 'imcr' => 'Import from Course Resources', 'extr' => 'External Resource', 'extt' => 'External Tool', 'selm' => 'Select Map', @@ -5450,7 +5894,7 @@ sub handler { 'navc' => 'Table of Contents', 'sipa' => 'Simple Course Page', 'sipr' => 'Simple Problem', - 'webp' => 'Blank Web Page (editable)', + 'webp' => 'Blank Web Page (editable)', 'stpr' => 'Standard Problem', 'news' => 'New sub-directory', 'crpr' => 'Create Problem', @@ -5482,7 +5926,7 @@ sub handler { 'webctce4' => 'WebCT 4 Campus Edition', 'yes' => 'Yes', 'no' => 'No', - 'er' => 'Editing rights unavailable for your current role', + 'er' => 'Editing rights unavailable for your current role.', ); # ----------------------------------------------------------------------------- @@ -5512,7 +5956,7 @@ sub handler { if ($disk_quota == 0) { $percent = 100.0; } else { - $percent = 100*($current_disk_usage/$disk_quota); + $percent = 100*($usage/$disk_quota); } $usage = sprintf("%.2f",$usage); $quota = sprintf("%.2f",$quota); @@ -5679,6 +6123,11 @@ CRSFORM $containertag

+
+ + + $containertag +
HIDDENFORM $r->print(&makesimpleeditform($pathitem)."\n". @@ -5701,7 +6150,7 @@ HIDDENFORM } # - + my $hostname = $r->hostname(); my $savefolderpath; if ($allowed) { @@ -5715,9 +6164,13 @@ HIDDENFORM } my $postexec=''; if ($folder eq 'default') { + my $windowname = 'loncapaclient'; + if ($env{'request.lti.login'}) { + $windowname .= 'lti'; + } $r->print(''."\n" ); @@ -5730,7 +6183,7 @@ HIDDENFORM my $newnavform=(< - + $pathitem @@ -5740,7 +6193,7 @@ HIDDENFORM NNFORM my $newsmppageform=(< - + $pathitem $lt{'sipa'} @@ -5750,7 +6203,7 @@ NSPFORM my $newsmpproblemform=(< - + $pathitem $lt{'sipr'} @@ -5761,7 +6214,7 @@ NSPROBFORM my $newdropboxform=(< - + $pathitem $lt{'drbx'} @@ -5771,7 +6224,7 @@ NDBFORM my $newexuploadform=(< - + $pathitem $lt{'scuf'} @@ -5781,7 +6234,7 @@ NEXUFORM my $newbulform=(< - + $pathitem $lt{'bull'} @@ -5791,7 +6244,7 @@ NBFORM my $newaboutmeform=(< - + $pathitem @@ -5802,7 +6255,7 @@ NAMFORM my $newaboutsomeoneform=(< - + $pathitem $lt{'abou'} @@ -5811,7 +6264,7 @@ NASOFORM my $newrosterform=(< - + $pathitem @@ -5832,7 +6285,7 @@ NROSTFORM } my $newwebpageform =(< - + $pathitem $lt{'webp'} @@ -5899,7 +6352,7 @@ NWEBFORM $numauthor ++; } } - my ($pickdir,$showtitle);; + my ($pickdir,$showtitle); if ($numauthor) { my @order; my $defrole; @@ -6015,7 +6468,7 @@ NWEBFORM