Diff for /loncom/interface/londocs.pm between versions 1.709 and 1.713

version 1.709, 2024/01/10 20:07:37 version 1.713, 2024/12/22 03:12:53
Line 48  use Apache::lonpublisher(); Line 48  use Apache::lonpublisher();
 use Apache::loncourserespicker();  use Apache::loncourserespicker();
 use HTML::Entities;  use HTML::Entities;
 use HTML::TokeParser;  use HTML::TokeParser;
   use HTML::LCParser;
 use GDBM_File;  use GDBM_File;
 use File::MMagic;  use File::MMagic;
 use File::Copy;  use File::Copy;
Line 268  ENDJS Line 269  ENDJS
     $r->print(&startContentScreen('tools'));      $r->print(&startContentScreen('tools'));
     my ($home,$other,%outhash)=&authorhosts();      my ($home,$other,%outhash)=&authorhosts();
     unless ($home) {      unless ($home) {
           $r->print('<p class="LC_info">'.&mt('No author or co-author roles on this server.').'</p>'); 
         $r->print(&endContentScreen());          $r->print(&endContentScreen());
         return '';          return '';
     }      }
Line 276  ENDJS Line 278  ENDJS
     if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {      if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
 # Do the dumping  # Do the dumping
  unless ($outhash{'home_'.$env{'form.authorspace'}}) {   unless ($outhash{'home_'.$env{'form.authorspace'}}) {
             $r->print(&endContentScreen());              $r->print('<p class="LC_info">'.&mt('Selected Authoring Space is not on this server.').'</p>'.
                         &endContentScreen());
             return '';              return '';
         }          }
  my ($ca,$cd)=split(/\:/,$env{'form.authorspace'});   my ($ca,$cd)=split(/\:/,$env{'form.authorspace'});
Line 572  $contents{webreferences}.' Line 575  $contents{webreferences}.'
         if (!ref($navmap)) {          if (!ref($navmap)) {
             $r->print($errormsg);              $r->print($errormsg);
         } else {          } else {
             $r->print('<div id="searching">'.&mt('Searching ...').'</div>');  
             $r->rflush();  
             my ($preamble,$formname);  
             $formname = 'dumpdoc';  
     unless ($home==1) {  
         $preamble = '<div class="LC_left_float">'.  
             '<fieldset><legend>'.  
                             &mt('Select the Authoring Space').  
                             '</legend><select name="authorspace">';  
     }  
             my @orderspaces = ();  
     foreach my $key (sort(keys(%outhash))) {  
                 if ($key=~/^home_(.+)$/) {  
                     if ($1 eq $env{'user.name'}.':'.$env{'user.domain'}) {  
                         unshift(@orderspaces,$1);  
                     } else {  
                         push(@orderspaces,$1);  
                     }  
                 }   
             }  
             if ($home>1) {  
                 $preamble .= '<option value="" selected="selected">'.&mt('Select').'</option>';  
             }  
             foreach my $user (@orderspaces) {  
  if ($home==1) {  
     $preamble .= '<input type="hidden" name="authorspace" value="'.$user.'" />';  
  } else {  
     $preamble .= '<option value="'.$user.'">'.$user.' - '.  
          &Apache::loncommon::plainname(split(/\:/,$user)).'</option>';  
         }  
     }  
     unless ($home==1) {  
         $preamble .= '</select></fieldset></div>'."\n";  
     }  
     my $title=$origcrsdata{'description'};      my $title=$origcrsdata{'description'};
     $title=~s/[\/\s]+/\_/gs;      $title=~s/[\/\s]+/\_/gs;
     $title=&clean($title);      $title=&clean($title);
     $preamble .= '<div class="LC_left_float">'.      my $formname = 'dumpdoc';
                          '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'.      my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash);
                          '<input type="text" size="50" name="authorfolder" value="'.      my %uploadedfiles;
                          $title.'" />'.  
                          '</fieldset></div><div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";  
             my %uploadedfiles;  
     &tiehash();      &tiehash();
     foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) {      foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) {
         my ($ext)=($file=~/\.(\w+)$/);          my ($ext)=($file=~/\.(\w+)$/);
Line 640  $contents{webreferences}.' Line 606  $contents{webreferences}.'
     $r->print(&endContentScreen());      $r->print(&endContentScreen());
 }  }
   
   sub authorspace_selector {
       my ($r,$formname,$home,$title,%outhash) = @_;
       $r->print('<div id="searching">'.&mt('Searching ...').'</div>'."\n");
       $r->rflush();
       my $preamble;
       unless ($home==1) {
           $preamble = '<div class="LC_left_float">'.
                       '<fieldset><legend>'.
                       &mt('Select the Authoring Space').
                       '</legend><select name="authorspace">';
       }
       my @orderspaces = ();
       foreach my $key (sort(keys(%outhash))) {
           if ($key=~/^home_(.+)$/) {
               if ($1 eq $env{'user.name'}.':'.$env{'user.domain'}) {
                   unshift(@orderspaces,$1);
               } else {
                   push(@orderspaces,$1);
               }
           }
       }
       if ($home>1) {
           $preamble .= '<option value="" selected="selected">'.&mt('Select').'</option>';
       }
       foreach my $user (@orderspaces) {
           if ($home==1) {
               $preamble .= '<input type="hidden" name="authorspace" value="'.$user.'" />';
           } else {
               $preamble .= '<option value="'.$user.'">'.$user.' - '.
                            &Apache::loncommon::plainname(split(/\:/,$user)).'</option>';
           }
       }
       unless ($home==1) {
           $preamble .= '</select></fieldset></div>'."\n";
       }
       $preamble .= '<div class="LC_left_float">'.
                    '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'.
                    '<input type="text" size="50" name="authorfolder" value="'.$title.'" />'."\n".
                    '</fieldset></div><div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
       return $preamble;
   }
   
 sub recurse_html {  sub recurse_html {
     my ($mm,$prefix,$currdirpath,$currurlpath,$container,$item,$replacehash,$deps) = @_;      my ($mm,$prefix,$currdirpath,$currurlpath,$container,$item,$replacehash,$deps) = @_;
     return unless ((ref($replacehash) eq 'HASH') && (ref($deps) eq 'HASH'));      return unless ((ref($replacehash) eq 'HASH') && (ref($deps) eq 'HASH'));
Line 684  sub recurse_html { Line 692  sub recurse_html {
     return;      return;
 }  }
   
   sub copycrsauthored {
       my ($r,$coursenum,$coursedom,$coursehome,$readonly) = @_;
       my ($starthash,$js);
       unless (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
           $js = <<"ENDJS";
   <script type="text/javascript">
   // <![CDATA[
   
   function hide_searching() {
       if (document.getElementById('searching')) {
           document.getElementById('searching').style.display = 'none';
       }
       return;
   }
   
   // ]]>
   </script>
   ENDJS
           $starthash = {
                            add_entries => {'onload' => "hide_searching();"},
                        };
       }
       $r->print(&Apache::loncommon::start_page('Copy from Course Authoring to User Authoring',$js,$starthash)."\n".
                 &Apache::lonhtmlcommon::breadcrumbs('Copy from Course Authoring Space')."\n");
       $r->print(&startContentScreen('tools'));
       my ($home,$other,%outhash)=&authorhosts();
       unless ($home) {
           $r->print('<p class="LC_info">'.&mt('No author or co-author roles on this server.').'</p>');
           $r->print(&endContentScreen());
           return '';
       }
       my %origcrsdata=&Apache::lonnet::coursedescription($env{'request.course.id'});
       my $exclude = &Apache::lonnet::priv_exclude();
       my $srcurl = "/priv/$coursedom/$coursenum";
       my $srctop = $r->dir_config('lonDocRoot').$srcurl;
       if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
           $r->print('<h3>'.&mt('Copying Files and/or Sub-directories').'</h3>');
           if ($readonly) {
               $r->print('<p class="LC_info">'.
                         &mt('You do not have permission to copy files and/or directories from Course Authoring Space.').
                         '</p>'.
                         &endContentScreen());
               return '';
           }
           unless ($outhash{'home_'.$env{'form.authorspace'}}) {
               $r->print('<p class="LC_info">'.&mt('Selected Authoring Space is not on this server.').'</p>'.
                         &endContentScreen());
               return '';
           }
           my ($ca,$cd)=split(/\:/,$env{'form.authorspace'});
           my $desturl = "/priv/$cd/$ca";
           my $desttop = $r->dir_config('lonDocRoot').$desturl;
           my $subdir = &clean($env{'form.authorfolder'});
           $subdir = &cleandir($subdir);
           if ($subdir eq '') {
               $r->print('<p class="LC_info">'.&mt('After removal of disallowed characters target sub-directory name was blank.').'</p>'.
                         &endContentScreen());
               return '';
           } elsif ($subdir =~/^_+$/) {
               $r->print('<p class="LC_info">'.&mt('After replacement of non-alphanumeric characters with _ in target sub-directory name, nothing but underscores was left.').'</p>'.
                         &endContentScreen());
               return '';
           }
           my $is_course_home;
           my @ids=&Apache::lonnet::current_machine_ids();
           if (($coursehome ne '') && (grep(/^\Q$coursehome\E$/,@ids))) {
               $is_course_home = 1;
           }
           my (%tocopy,%dirs_to_make,%files_to_copy);
           map { $tocopy{&unescape($_)} = 1; } &Apache::loncommon::get_env_multiple('form.copytouser');
           if (keys(%tocopy)) {
               my (%subdirs,%files);
               &Apache::lonnet::recursedirs($home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files);
               foreach my $possible (sort(keys(%tocopy))) {
                   if ($possible =~ m{/$}) {
                       my $possdir = $possible;
                       $possdir =~ s{^/+|/+$}{}g;
                       if (exists($subdirs{$possdir})) {
                           $dirs_to_make{$possdir} = 1;
                       } else {
                           delete($tocopy{$possible});
                       }
                   } else {
                       my ($path,$fname) = ($possible =~ m{(.*/)([^/]+)$});
                       my $found = 0;
                       if ($path eq '/') {
                           if (ref($files{$path}) eq 'HASH') {
                               if (exists($files{$path}{$fname})) {
                                   $found = 1;
                                   $files_to_copy{$fname} = 1;
                               }
                           }
                       } else {
                           $path =~ s{^/+|/+$}{}g;
                           if (ref($files{$path}) eq 'HASH') {
                               if (exists($files{$path}{$fname})) {
                                   $dirs_to_make{$path} = 1;
                                   $files_to_copy{"$path/$fname"} = 1;
                                   $found = 1;
                               }
                           }
                       }
                       unless ($found) {
                           delete($tocopy{$possible});
                       }
                   }
               }
           } else {
               $r->print('<p>'.&mt('No files or directories selected for copying').'</p>');
               $r->print(&endContentScreen());
               return '';
           }
           if (keys(%tocopy)) {
               my ($notopdir,%newdir,%newfile,%checkdeps);
               $r->print('<p>'.&mt('Copy to: [_1]',
                                   '<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
                         '</p>'."\n");
               unless ($is_course_home) {
                   $r->print('<p class="LC_info>'.&mt("Session needs to be hosted on course's home server.").
                             '</p>'.
                             &endContentScreen());
                   return '';
               }
               if (keys(%dirs_to_make)) {
                   if ($is_course_home) {
                       unless (-e $desttop.'/'.$subdir) {
                           mkdir($desttop.'/'.$subdir,0755);
                       }
                       if (-e $desttop.'/'.$subdir) {
                           foreach my $dir (sort(keys(%dirs_to_make))) {
                               my @dirs=split(/\//,$dir);
                               my $path="$desttop/$subdir";
                               my $makepath=$path;
                               my $fail;
                               for (my $i=0;$i<@dirs;$i++) {
                                   $makepath.='/'.$dirs[$i];
                                   unless (-e $makepath) {
                                       unless (mkdir($makepath,0755)) {
                                           $fail = 1;
                                           last;
                                       }
                                       if (($i == scalar(@dirs)-1) && (!$fail))  {
                                           $newdir{$dir} = 1;
                                       }
                                   }
                               }
                               if ($fail) {
                                   $r->print('<p class="LC_warning">'.&mt('Target directory: [_1] does not exist, and could not be created.',
                                                                          '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$dir.'</span>').
                                             '</p>'."\n");
                               }
                           }
                       } else {
                           $notopdir = 1;
                       }
                   }
               }
               if (keys(%files_to_copy)) {
                   if ($is_course_home) {
                       unless (-e $desttop.'/'.$subdir) {
                           mkdir($desttop.'/'.$subdir,0755);
                       }
                       if (-e $desttop.'/'.$subdir) {
                           my $num = 0;
                           foreach my $file (keys(%files_to_copy)) {
                               my ($fail,$dup,$dir_is_file,$src,$dest,$path,$fname);
                               if ($file =~ m{/}) {
                                   ($path,$fname) = ($file =~ m{^(.+)/([^/]+)$});
                                   if (-d "$desttop/$subdir/$path") {
                                       if (-e "$desttop/$subdir/$path/$fname") {
                                           $dup = 1;
                                       } else {
                                           $src = "$srctop/$path/$fname";
                                           $dest = "$desttop/$subdir/$path/$fname";
                                       }
                                   } elsif (-f "$desttop/$subdir/$path") {
                                       $dir_is_file = 1;
                                   } else {
                                       $fail = 1;
                                   }
                               } elsif (-e "$desttop/$subdir/$file") {
                                   $dup = 1;
                               } else {
                                   $src = "$srctop/$file";
                                   $dest = "$desttop/$subdir/$file";
                                   $fname = $file;
                               }
                               if ($fail) {
                                   $r->print('<p class="LC_warning">'.&mt('Target directory: [_1] does not exist, and could not be created.',
                                                                          '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$path.'</span>').
                                             '</p>'."\n");
                               } elsif ($dup) {
                                   $r->print('<p class="LC_warning">'.&mt('Target file: [_1] already exists -- not overwriting.',
                                                                          '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$file.'</span>').
                                             '</p>'."\n");
                               } elsif ($dir_is_file) {
                                   $r->print('<p class="LC_warning">'.&mt('Target directory: [_1] name is already in a use for a file -- not overwriting.',
                                                                          '<span class="LC_filename">'.$desturl.'/'.$subdir.'/'.$file.'</span>').
                                             '</p>'."\n");
                               } elsif (($src ne '') && ($dest ne '')) {
                                   if (&File::Copy::copy($src,$dest)) {
                                       $newfile{$file} = 1;
                                       if ((-e $src.'.meta') && (!-e $dest.'.meta')) {
                                           if (&File::Copy::copy($src.'.meta',$dest.'.meta')) {
                                               if (open(my $fh,'<',$dest.'.meta')) {
                                                   my ($output,$now);
                                                   $now = time;
                                                   while (my $line=<$fh>) {
                                                       chomp($line);
                                                       if ($line eq "<authorspace>$coursenum:$coursedom</authorspace>") {
                                                           $output .= "<authorspace>$ca:$cd</authorspace>\n";
                                                       } elsif ($line eq '<copyright>custom</copyright>') {
                                                           $output .= "<copyright>default</copyright>\n";
                                                       } elsif ($line =~ m{^<creationdate>\d+</creationdate>$}) {
                                                           $output .= "<creationdate>$now</creationdate>\n";
                                                       } elsif ($line eq "<customdistributionfile>/res/$coursedom/$coursenum/default.rights</customdistributionfile>") {
                                                           $output .= "<customdistributionfile></customdistributionfile>\n";
                                                       } elsif ($line eq "<domain>$coursedom</domain>") {
                                                           $output .= "<domain>$cd</domain>\n";
                                                       } elsif ($line =~ m{^<lastrevisiondate>\d+</lastrevisiondate>$}) {
                                                           $output .= "<lastrevisiondate>$now</lastrevisiondate>\n";
                                                       } elsif ($line =~ m{^<modifyinguser>$match_username:$match_domain</modifyinguser>$}) {
                                                           $output .= "<modifyinguser>$env{'user.name'}:$env{'user.domain'}</modifyinguser>\n";
                                                       } elsif ($line eq "<owner>$coursenum:$coursedom</owner>") {
                                                           $output .= "<owner>$ca:$cd</owner>\n";
                                                       } elsif ($line =~ m{^<dependencies>(.+)</dependencies>$}) {
                                                           my @deps = split(/\s*,\s*/,$1);
                                                           my @newdeps;
                                                           my $changed = 0;
                                                           foreach my $dep (@deps) {
                                                               if ($dep =~ m{^/res/$coursedom/$coursenum/(.+)$}) {
                                                                   my $rest = $1;
                                                                   push(@newdeps,"/res/$cd/$ca/$rest");
                                                                   $checkdeps{$rest} = 1;
                                                                   $changed ++;
                                                               } else {
                                                                   push(@newdeps,$dep);
                                                               }
                                                           }
                                                           if ($changed) {
                                                               $output .= '<dependencies>'.join(',',@newdeps).'</dependencies>'."\n";
                                                           }
                                                       } else {
                                                           $output .= "$line\n";
                                                       }
                                                   }
                                                   close($fh);
                                                   if (open(my $fh,'>',$dest.'.meta')) {
                                                       print $fh $output;
                                                       close($fh);
                                                   }
                                               }
                                           }
                                       }
                                       my ($ext) = ($file =~ /\.(\w+)$/);
                                       my $embstyle=&Apache::loncommon::fileembstyle($ext);
                                       if ($embstyle eq 'ssi') {
                                           my $outstring='';
                                           my $changes = 0;
                                           my @parser;
                                           $parser[0]=HTML::LCParser->new($src);
                                           $parser[-1]->xml_mode(1);
                                           my $token;
                                           while (@parser) {
                                               while ($token=$parser[-1]->get_token) {
                                                   if ($token->[0] eq 'S') {
                                                       my $tag=$token->[1];
                                                       my $lctag=lc($tag);
                                                       my %parms=%{$token->[2]};
                                                       foreach my $type ('src','href','background','bgimg') {
                                                           foreach my $key (keys(%parms)) {
                                                               if ($key =~ /^$type$/i) {
                                                                   next if (($lctag eq 'img') && ($type eq 'src') &&
                                                                            ($parms{$key} =~ m{^data\:image/gif;base64,}));
                                                                   if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                       $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
                                                                       $changes ++;
                                                                   }
                                                               }
                                                           }
                                                       }
                                                       # probably a <randomlabel> image type <label>
                                                       # or a <image> tag inside <imageresponse> or <drawimage>
                                                       if (($lctag eq 'label' && defined($parms{'description'}))
                                                            || ($lctag eq 'image') || ($lctag eq 'import')) {
                                                           my $next_token=$parser[-1]->get_token();
                                                           if ($next_token->[0] eq 'T') {
                                                               $next_token->[1] =~ s/[\n\r\f]+//g;
                                                               if ($next_token->[1] =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                   $next_token->[1] =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
                                                                   $changes ++;
                                                               }
                                                           }
                                                           $parser[-1]->unget_token($next_token);
                                                       }
                                                       if ($lctag eq 'applet') {
                                                           my $havecodebase=0;
                                                           foreach my $key (keys(%parms)) {
                                                               if (lc($key) eq 'codebase') {
                                                                   if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                       $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
                                                                       $changes ++;
                                                                   }
                                                                   $havecodebase = 1;
                                                               }
                                                           }
                                                           unless ($havecodebase) {
                                                               foreach my $key (keys(%parms)) {
                                                                   if ($key =~ /(archive|code|object)/i) {
                                                                       if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                           $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/si};
                                                                           $changes ++;
                                                                       }
                                                                   }
                                                               }
                                                           }
                                                       }
                                                       my $newparmstring='';
                                                       my $endtag='';
                                                       foreach my $parkey (keys(%parms)) {
                                                           if ($parkey eq '/') {
                                                               $endtag=' /';
                                                           } else {
                                                               my $quote=($parms{$parkey}=~/\"/?"'":'"');
                                                               $newparmstring.=' '.$parkey.'='.$quote.$parms{$parkey}.$quote;
                                                           }
                                                       }
                                                       if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }
                                                       $outstring.='<'.$tag.$newparmstring.$endtag.'>';
                                                       if ($lctag eq 'm' || $lctag eq 'answer' || $lctag eq 'display' ||
                                                           $lctag eq 'tex') {
                                                           $outstring.=&Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
                                                       } elsif ($lctag eq 'script') {
                                                           if ($parms{'type'} eq 'loncapa/perl') {
                                                               $outstring.=&Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
                                                           } else {
                                                               my $needsupdate;
                                                               my $script = &Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
                                                               if ($script =~ m{\.addMediaSrc\((["'])((?!\1).+)\1\);}) {
                                                                   my $src = $2;
                                                                   if ($src =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                       $needsupdate = 1;
                                                                   }
                                                               }
                                                               if ($script =~ /\(document,\s*(['"])script\1,\s*\[([^\]]+)\]\);/s) {
                                                                   my $scriptslist = $2;
                                                                   my $needsupdate = 1;
                                                                   my @srcs = split(/\s*,\s*/,$scriptslist);
                                                                   foreach my $src (@srcs) {
                                                                       if ($src =~ /(["'])(?:(?!\1).)+\.js\1/) {
                                                                           my $quote = $1;
                                                                           my ($url) = ($src =~ m/\Q$quote\E([^$quote]+)\Q$quote\E/);
                                                                           if ($url =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                               $needsupdate = 1;
                                                                           }
                                                                       }
                                                                   }
                                                               }
                                                               if ($script =~ m{loadScript\(\s*(['"])((?:(?!\1).)+\.js)\1,\s*function}is) {
                                                                   my $src = $2;
                                                                   if ($src =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
                                                                       $needsupdate = 1;
                                                                   }
                                                               }
                                                               if ($needsupdate) {
                                                                   $script =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/gsi};
                                                                   $changes ++;
                                                               }
                                                               $outstring .= $script;
                                                           }
                                                       }
                                                   } elsif ($token->[0] eq 'E') {
                                                       if ($token->[2]) {
                                                           unless ($token->[1] eq 'allow') {
                                                               $outstring.='</'.$token->[1].'>';
                                                           }
                                                       }
                                                   } else {
                                                        $outstring.=$token->[1];
                                                   }
                                               }
                                               pop(@parser);
                                           }
                                           if ($changes) {
                                               if (open(my $fh,'>',$dest)) {
                                                   print $fh $outstring;
                                                   close($fh);
                                               }
                                           }
                                       }
                                   }
                               }
                           }
                       } else {
                           $notopdir = 1;
                       }
                   }
               }
               if ($notopdir) {
                   $r->print('<p><span class="LC_info">'.&mt('No files or sub-directories copied').'</span><br />'."\n".
                             '<span class="LC_warning">'.&mt('Target directory: [_1] does not exist, and could not be created.',
                                                             '<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
                             '</span></p>'."\n");
               }
               if (keys(%newdir)) {
                    $r->print('<p>'.&mt('Created the following directories in [_1]:','<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
                              '</p>'."\n".
                              '<ul><li>'.join('</li><li>',sort(keys(%newdir))).'</li></ul></p>'."\n");
               }
               if (keys(%newfile)) {
                   $r->print('<p>'.&mt('Copied the following files to [_1]:','<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
                             '</p>'."\n".
                             '<ul><li>'.join('</li><li>',sort(keys(%newfile))).'</li></ul></p>'."\n");
               }
               if (keys(%checkdeps)) {
                   my %missingdep;
                   foreach my $depfile (sort(keys(%checkdeps))) {
                       unless (-e "$desttop/$depfile") {
                           $missingdep{$depfile} = 1;
                       }
                   }
                   if (keys(%missingdep)) {
                       $r->print('<p>'.&mt('You may also need to copy the following missing dependencies for files copied to [_1]:',
                                           '<span class="LC_filename">'.$desturl.'/'.$subdir.'</span>').
                             '</p>'."\n".
                             '<ul><li>'.join('</li><li>',sort(keys(%missingdep))).'</li></ul></p>'."\n");
                   }
               }
           } else {
               $r->print('<p>'.&mt('No currently existing files or directories in Course Authoring Space selected for copying').'</p>');
               $r->print(&endContentScreen());
               return '';
           }
       } else {
           my $formname = 'copycrsauthored';
           my $chkname = 'copytouser';
           my $context = 'crsauthored';
           my (%subdirs,%files,@dirs_by_depth,@files_by_depth,%parent,%children,%hierarchy,@checked_maps);
           &Apache::lonnet::recursedirs($home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files);
           foreach my $key (keys(%subdirs)) {
               next if (($key eq '/') || ($key eq ''));
               my @items = split(/\//,$key);
               my $dir = pop(@items);
               my $depth = scalar(@items);
               my $path;
               if (!$depth) {
                   $path = '/';
               } else {
                   $path = join('/',@items);
               }
               $dirs_by_depth[$depth]{$path}{$dir} = 1;
           }
           foreach my $path (keys(%files)) {
               next if ($path eq '');
               my $depth;
               if ($path eq '/') {
                   $depth = 0;
               } else {
                   $depth = scalar(split(/\//,$path));
               }
               if (ref($files{$path}) eq 'HASH') {
                   foreach my $file (keys(%{$files{$path}})) {
                       $files_by_depth[$depth]{$path}{$file} = 1;
                   }
               }
           }
           my ($info,$display,$onsubmit,$togglebuttons,$disabled);
           if ($readonly) {
               $disabled = ' disabled="disabled"';
           }
           if ($disabled) {
               $togglebuttons = '<br />';
           } else {
               $togglebuttons = '<input type="button" value="'.&mt('check all').'" '.
                                'onclick="javascript:checkAll(document.'.$formname.'.'.$chkname.')" />'.
                                '&nbsp;&nbsp;<input type="button" value="'.&mt('uncheck all').'"'.
                                ' onclick="javascript:uncheckAll(document.'.$formname.'.'.$chkname.')" />';
           }
           my $title=$origcrsdata{'description'};
           $title=~s/[\/\s]+/\_/gs;
           $title=&clean($title);
           my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash);
           my $display = '<form name="'.$formname.'" action="" method="post">'."\n".
                         $preamble."\n".
                         '<div class="LC_float_left">'."\n".
                         '<fieldset>'."\n".
                         '<legend>'.&mt('Content to copy').('&nbsp;'x4).$togglebuttons.'</legend>'."\n".
                         '<span class="LC_fontsize_medium">'.
                         &mt('Choose the files and/or folders to copy from Course Authoring to User Authoring').
                         '</span><br /><br />'."\n";
           my $count = 0;
           my $startcount = 4 + $home;
           my $lastcontainer = $startcount;
           $display .= &Apache::loncommon::start_data_table()."\n".
                       &Apache::loncommon::start_data_table_header_row().
                       '<th>'.&mt('Copy?').'</th>'.
                       '<th>'.&mt('Title').'</th>'.
                       &Apache::loncommon::end_data_table_header_row()."\n";
           $count = &recurse_crsauthored(0,\@dirs_by_depth,\@files_by_depth,'/',$startcount,
                                         $count,\$display,\%parent,\%children,$readonly,
                                         $formname,$chkname,\$lastcontainer);
           $display .= &Apache::loncommon::end_data_table().'</fieldset>';
           unless ($readonly) {
               $display .= '</div><div style="padding:0;clear:both;margin:0;border:0"></div>'.
                           '<div>'.
                           '<input type="submit" name="copyauthored" value="'.&mt("Copy Selected Content").'" />'.
                           '</div>';
           }
           $display .= &Apache::loncourserespicker::respicker_javascript($startcount,$count,$context,$formname,\%children,
                                                                         \%hierarchy,\@checked_maps,$home,$chkname);
           $r->print($display);
       }
       $r->print(&endContentScreen());
   }
   
   sub recurse_crsauthored {
       my ($currdepth,$dirs_by_depth,$files_by_depth,$currpath,$startcount,$count,$displayref,
           $parent,$children,$readonly,$formname,$chkname,$lastcontainerref) = @_;
       return $count unless ((ref($dirs_by_depth) eq 'ARRAY') && (ref($files_by_depth) eq 'ARRAY'));
       my ($disabled,$hasdirs,$hasfiles,%unique,%dirs,%files);
       if ((ref($dirs_by_depth->[$currdepth]) eq 'HASH') &&
           (ref($dirs_by_depth->[$currdepth]{$currpath}) eq 'HASH')) {
           $hasdirs = 1;
           %dirs = %{$dirs_by_depth->[$currdepth]{$currpath}};
           map { $unique{$_} = 1; } keys(%dirs);
       }
       if ((ref($files_by_depth->[$currdepth]) eq 'HASH') &&
           (ref($files_by_depth->[$currdepth]{$currpath}) eq 'HASH')) {
           $hasfiles = 1;
           %files = %{$files_by_depth->[$currdepth]{$currpath}};
           map { $unique{$_} = 1; } keys(%files);
       }
       if ($readonly) {
           $disabled = ' disabled="disabled"';
       }
       my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons");
       my $whitespace =
           '<img src="'.$location.'/whitespace_21.gif" class="LC_docs_spacer" alt="" />';
       $parent->{$currdepth} = $$lastcontainerref;
       foreach my $item (sort { lc($a) cmp lc($b) } (keys(%unique))) {
           next if ($item eq '');
           my $currelem;
           if ($hasdirs && exists($dirs{$item})) {
               $count ++;
               my $deeper = $currdepth+1;
               my ($newpath,$showpath);
               if ($currpath eq '/') {
                   $newpath = $item;
                   $showpath = $currpath.$item.'/';
               } else {
                   $newpath = $currpath.'/'.$item;
                   $showpath = '/'.$currpath.'/'.$item.'/';
               }
               $currelem = $count+$startcount;
               $$lastcontainerref = $currelem;
               $children->{$parent->{$currdepth}} .= $currelem.':';
               my $icon = 'src="'.$location.'/navmap.folder.open.gif" alt="'.&mt('Folder').'"';
               $$displayref .= &Apache::loncommon::start_data_table_row().
                               '<td><input type="checkbox" name="'.$chkname.'" value="'.&escape($showpath).'" '.
                               'onclick="javascript:checkFolder(document.'.$formname.','."'$currelem'".')" '.
                               $disabled.' /></td><td>';
               for (my $i=0; $i<$currdepth; $i++) {
                   $$displayref .= "$whitespace\n";
               }
               $$displayref .= '<img '.$icon.' />&nbsp;'.$item.'</td>'.
                               &Apache::loncommon::end_data_table_row()."\n";
               $count = &recurse_crsauthored($deeper,$dirs_by_depth,$files_by_depth,$newpath,
                                             $startcount,$count,$displayref,$parent,$children,
                                             $readonly,$formname,$chkname,$lastcontainerref);
           }
           if ($hasfiles && exists($files{$item})) {
               $count ++;
               $currelem = $count+$startcount;
               $children->{$parent->{$currdepth}} .= $currelem.':';
               my $icon = 'src="'.&Apache::loncommon::icon($item).'"';
               my ($ext) = ($item =~ /\.([^.]+)$/);
               my $alttext;
               if (lc($ext) eq 'problem') {
                   $alttext = ' alt="'.&mt('Problem Icon').'"';
               } elsif ($ext =~ /^x?html?$/i) {
                   $alttext = ' alt="'.&mt('Web Page Icon').'"';
               } elsif ($ext =~ /^(jpg|gif|png|svg|jpeg)$/) {
                   $alttext = ' alt="'.&mt('Image Icon').'"';
               } else {
                   $alttext = ' alt="'.&mt('Resource Icon').'"';
               }
               my $showpath;
               if ($currpath eq '/') {
                   $showpath = $currpath;
               } else {
                   $showpath = "/$currpath/";
               }
               $$displayref .= &Apache::loncommon::start_data_table_row().
                               '<td><input type="checkbox" name="'.$chkname.'" value="'.&escape($showpath.$item).'" '.
                               'onclick="javascript:checkResource(document.'.$formname.','."'$currelem'".')" '.
                               $disabled.' /></td><td>';
               for (my $i=0; $i<$currdepth; $i++) {
                   $$displayref .= "$whitespace\n";
               }
               $$displayref .= '<img '.$icon.$alttext.' />&nbsp;'.$item.'</td>'.
                               &Apache::loncommon::end_data_table_row()."\n";
           }
       }
       $$lastcontainerref = $parent->{$currdepth};
       return $count;
   }
   
 sub group_import {  sub group_import {
     my ($coursenum, $coursedom, $folder, $container, $caller, $ltitoolsref, @files) = @_;      my ($coursenum, $coursedom, $folder, $container, $caller, $ltitoolsref, @files) = @_;
     my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap,      my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap,
Line 5402  sub short_urls { Line 6017  sub short_urls {
         }          }
         my %currtiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);          my %currtiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);
         $r->print(&Apache::loncourserespicker::create_picker($navmap,'shorturls',$formname,$crstype,undef,          $r->print(&Apache::loncourserespicker::create_picker($navmap,'shorturls',$formname,$crstype,undef,
                                                              undef,undef,undef,undef,undef,\%currtiny,$readonly));                                                               undef,undef,undef,undef,undef,\%currtiny,undef,$readonly));
     }      }
     $r->print(&endContentScreen());      $r->print(&endContentScreen());
 }  }
Line 5877  sub handler { Line 6492  sub handler {
     my $crstype = &Apache::loncommon::course_type();      my $crstype = &Apache::loncommon::course_type();
     my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};      my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};      my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
       my $coursehome=$env{'course.'.$env{'request.course.id'}.'.home'};
   
 # get docroot  # get docroot
     my $londocroot = $r->dir_config('lonDocRoot');      my $londocroot = $r->dir_config('lonDocRoot');
Line 5967  sub handler { Line 6583  sub handler {
   } elsif ($canedit && $env{'form.dumpcourse'}) {    } elsif ($canedit && $env{'form.dumpcourse'}) {
       &init_breadcrumbs('dumpcourse','Copy uploaded content to Authoring Space');        &init_breadcrumbs('dumpcourse','Copy uploaded content to Authoring Space');
       &dumpcourse($r);        &dumpcourse($r);
     } elsif (($canedit || $canview) && ($env{'form.copyauthored'})) {
         &init_breadcrumbs('copyauthored','Copy from Course Authoring to User Authoring');
         my $readonly;
         if (!$canedit) {
             $readonly = 1;
         }
         &copycrsauthored($r,$coursenum,$coursedom,$coursehome,$readonly);
   } elsif ($canedit && $env{'form.exportcourse'}) {    } elsif ($canedit && $env{'form.exportcourse'}) {
       &init_breadcrumbs('exportcourse','IMS Export');        &init_breadcrumbs('exportcourse','IMS Export');
       &Apache::imsexport::exportcourse($r);        &Apache::imsexport::exportcourse($r);
Line 6694  SEDFFORM Line 7317  SEDFFORM
             $checkcrsres = 1;              $checkcrsres = 1;
         } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.crsauthor'} ne '0') {          } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.crsauthor'} ne '0') {
             my %domdefs=&Apache::lonnet::get_domain_defaults($coursedom);              my %domdefs=&Apache::lonnet::get_domain_defaults($coursedom);
             if ($domdefs{'crsauthor'}) {              my $type = lc($env{'course.'.$env{'request.course.id'}.'.type'});
               unless (($type eq 'community') || ($type eq 'placement')) {
                   $type = 'unofficial';
                   if ($env{'course.'.$env{'request.course.id'}.'internal.coursecode'} ne '') {
                       $type = 'official';
                   } elsif ($env{'course.'.$env{'request.course.id'}.'internal.textbook'} ne '') {
                       $type = 'textbook';
                   } else {
                       $type = 'unofficial';
                   }
               }
               if ($domdefs{$type.'crsauthor'}) {
                 $checkcrsres = 1;                  $checkcrsres = 1;
             }              }
         }          }
Line 7607  sub generate_admin_menu { Line 8241  sub generate_admin_menu {
                                          'ct'   => 'Display/Set Shortened URLs for Deep-linking',                                           'ct'   => 'Display/Set Shortened URLs for Deep-linking',
                                          'ca'   => "Enter $crstype Authoring Space",                                           'ca'   => "Enter $crstype Authoring Space",
                                          'imse' => 'Export contents to IMS Archive',                                           'imse' => 'Export contents to IMS Archive',
                                          'dcd'  => "Copy $crstype Content to Authoring Space",                                           'dcd'  => 'Copy uploaded content to Authoring Space',
                                            'cpc'  => 'Copy from Course Authoring to User Authoring',
             );              );
     my ($candump,$dumpurl);      my ($candump,$dumpurl,$exportcrsurl);
     if ($home + $other > 0) {      if ($home + $other > 0) {
         $candump = 'F';          $candump = 'F';
         if ($home) {          if ($home) {
             $dumpurl = "javascript:injectData(document.courseverify,'dummy','dumpcourse','$lt{'dcd'}')";              $dumpurl = "javascript:injectData(document.courseverify,'dummy','dumpcourse','$lt{'dcd'}')";
               $exportcrsurl = "javascript:injectData(document.courseverify,'dummy','copyauthored','$lt{'cpc'}')";
         } else {          } else {
             my @hosts;              my @hosts;
             foreach my $aurole (keys(%outhash)) {              foreach my $aurole (keys(%outhash)) {
Line 7627  sub generate_admin_menu { Line 8263  sub generate_admin_menu {
                                &HTML::Entities::encode($env{'request.role'},'"<>&').'&amp;origurl='.                                 &HTML::Entities::encode($env{'request.role'},'"<>&').'&amp;origurl='.
                                &HTML::Entities::encode('/adm/coursedocs?dumpcourse=1','"<>&');                                 &HTML::Entities::encode('/adm/coursedocs?dumpcourse=1','"<>&');
                 $dumpurl = "javascript:dump_needs_switchserver('$switchto')";                  $dumpurl = "javascript:dump_needs_switchserver('$switchto')";
                   $exportcrsurl = $dumpurl;
             } else {              } else {
                 $dumpurl = "javascript:choose_switchserver_window()";                  $dumpurl = "javascript:choose_switchserver_window()";
                   $exportcrsurl = $dumpurl;
             }              }
         }          }
     }      }
Line 7710  sub generate_admin_menu { Line 8348  sub generate_admin_menu {
                 },                  },
                 ]                  ]
         });          });
           if (($crsauname eq $coursenum) && ($crsaudom eq $coursedom)) {
               if ((ref($menu[1]) eq 'HASH') && (ref($menu[1]->{'items'}) eq 'ARRAY')) {
                   push(@{$menu[1]->{items}},
                        {   linktext   => $lt{'cpc'},
                            url        => $exportcrsurl,
                            permission => 'F',
                            help       => 'Docs_Export_Course_Author',
                            icon       => 'res.png',
                            linktitle  => $lt{'cpc'},
                        });
               }
           }
     }      }
     return '<form action="/adm/coursedocs" method="post" name="courseverify">'."\n".      return '<form action="/adm/coursedocs" method="post" name="courseverify">'."\n".
            '<input type="hidden" id="dummy" />'."\n".             '<input type="hidden" id="dummy" />'."\n".

Removed from v.1.709  
changed lines
  Added in v.1.713


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>